java - Override Thread.sleep() -
we have few classes extends base class. noticed use quit few sleeps method , wanted log when sleep occurs. there way override thread.sleep method in can add custom logic ( ie logging) , call actual thread.sleep()? way wouldn't have change places thread.sleep being used in bases classes. i'm open other options well.
you cannot override thread.sleep
method, cannot instrument or transform either it's native method. 1 way automatically add logging places call thread.sleep using java agent.
while following approach works , quite fun, in case it's better refactor calls thread.sleep
separate method , add logging there.
you can find introduction java agents here. in nutshell it's special mechanism allows (among other) transformation of loaded java byte code. following example of java agent class automatically enhances calls thread.sleep system.out logging , measure time spent in method:
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); } }); } /** * method enhances calls thread.sleep logging. */ 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(); (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.tobytecode(); } } catch (exception e) { system.err.println("could not instrument " + name + ", exception : " + e.getmessage()); } { if (cl != null) { cl.detach(); } } return b; } }
you need compile loggeragent.jar file , include following meta-inf/manifest.mf in it:
manifest-version: 1.0 premain-class: fi.schafer.agent.loggingagent boot-class-path: javassist.jar
download javaassist , put same folder jar compiled agent. run application parameter -javaagent:loggeragent.jar
.
you can download full example. extract it, open folder release , run application java -cp loggeragent.jar -javaagent:loggeragent.jar test
more information , more examples can found in excellent article.
Comments
Post a Comment