您不能重写
Thread.sleep方法,因为它是本机方法,所以无法对其进行分析或转换。一种方法是使用Java代理自动将日志记录添加到所有调用Thread.sleep的位置。
尽管下面的方法有效并且很有趣,但对于您而言,将所有对in的调用重构
Thread.sleep为一个单独的方法并在其中添加日志记录可能会更好。
您可以在此处找到Java代理的简介。简而言之,它是一种特殊的机制,允许(以及其他)转换已加载的Java字节码。以下Java
Agent类示例通过System.out日志记录自动增强了对Thread.sleep的所有调用,并测量了在该方法中花费的时间:
package fi.schafer.agent;import javassist.CannotCompileException;import javassist.ClassPool;import javassist.CtClass;import javassist.CtMethod;import javassist.expr.ExprEditor;import javassist.expr.MethodCall;import java.lang.instrument.ClassFileTransformer;import java.lang.instrument.IllegalClassFormatException;import java.lang.instrument.Instrumentation;import java.security.ProtectionDomain;public class LoggingAgent { public static void premain(String agentArgument, Instrumentation instrumentation) throws Exception { instrumentation.addTransformer(new ClassFileTransformer() { @Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { return doClass(className, classBeingRedefined, classfileBuffer); } }); } private static byte[] doClass(String name, Class clazz, byte[] b) { ClassPool pool = ClassPool.getDefault(); CtClass cl = null; try { cl = pool.makeClass(new java.io.ByteArrayInputStream(b)); final CtMethod[] targetMethods = cl.getDeclaredMethods(); for (CtMethod targetMethod : targetMethods) { targetMethod.instrument(new ExprEditor() { public void edit(final MethodCall m) throws CannotCompileException { if ("java.lang.Thread".equals(m.getClassName()) && "sleep".equals(m.getMethodName())) { m.replace("{long startMs = System.currentTimeMillis(); " + "$_ = $proceed($$); " + "long endMs = System.currentTimeMillis();" + "System.out.println("Logging Thread.sleep call execution, ms: " + (endMs-startMs));}"); } } }); return cl.toBytepre(); } } catch (Exception e) { System.err.println("Could not instrument " + name + ", exception : " + e.getMessage()); } finally { if (cl != null) { cl.detach(); } } return b; }}您将需要将其编译为loggerAgent.jar文件,并在其中包含以下meta-INF / MANIFEST.MF:
Manifest-Version: 1.0Premain-Class: fi.schafer.agent.LoggingAgentBoot-Class-Path: javassist.jar
下载JavaAssist并将其放入带有已编译Agent的jar所在的文件夹中。使用parameter运行您的应用程序
-javaagent:loggerAgent.jar。
您可以下载完整的示例。只需解压缩它,打开文件夹版本,然后使用
java-cp loggerAgent.jar -javaagent:loggerAgent.jar Test
更多信息和更多示例可以在这篇出色的文章中找到。



