From dbfe2758501f369d8c389844549d8ce0ebdd52a9 Mon Sep 17 00:00:00 2001 From: bedrin Date: Sun, 24 May 2015 12:54:25 +0300 Subject: [PATCH 1/3] Count invocations of preConstructor --- jsonde.instrumentation/pom.xml | 5 + .../instrumentation/ByteCodeTransformer.java | 16 +- .../instrumentation/MethodTransformer.java | 19 ++ .../instrumentation/TransformerCallback.java | 11 + .../TestInstrumentSingleMethod.java | 10 +- .../TestInstrumentSuperConsrtuctor.java | 36 +++ .../TestInstrumentXMLString.java | 31 ++ .../profiler/InvocationCountingProfiler.java | 7 +- .../instrumentation/samples/SimpleClass.java | 2 +- .../samples/SuperConstructor.java | 18 ++ .../instrumentation/samples/XMLString.java | 283 ++++++++++++++++++ .../java/com/jsonde/profiler/Profiler.java | 5 + 12 files changed, 434 insertions(+), 9 deletions(-) create mode 100755 jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/TestInstrumentSuperConsrtuctor.java create mode 100755 jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/TestInstrumentXMLString.java create mode 100755 jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/samples/SuperConstructor.java create mode 100755 jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/samples/XMLString.java diff --git a/jsonde.instrumentation/pom.xml b/jsonde.instrumentation/pom.xml index 562daf1..2c77077 100755 --- a/jsonde.instrumentation/pom.xml +++ b/jsonde.instrumentation/pom.xml @@ -37,6 +37,11 @@ asm-util ${asm.version} + org.ow2.asm asm-commons diff --git a/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/ByteCodeTransformer.java b/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/ByteCodeTransformer.java index e64f4e0..879aab5 100755 --- a/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/ByteCodeTransformer.java +++ b/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/ByteCodeTransformer.java @@ -4,10 +4,7 @@ import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.util.ASMifier; -import org.objectweb.asm.util.TraceClassVisitor; -import java.io.PrintWriter; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.security.ProtectionDomain; @@ -101,11 +98,22 @@ protected String getCommonSuperClass(String type1, String type2) { classVisitor = new ClassTransformer(callback, classWriter, loader, className, classBeingRedefined, protectionDomain); classReader.accept(classVisitor, ClassReader.EXPAND_FRAMES); + + byte[] bytes = classWriter.toByteArray(); /*classReader.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter( System.out)), 0);*/ + /* + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + CheckClassAdapter.verify(new ClassReader(bytes), false, pw); + if (!sw.toString().isEmpty()) { + System.out.println(sw.toString()); + }*/ + - return classWriter.toByteArray(); + return bytes; } diff --git a/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/MethodTransformer.java b/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/MethodTransformer.java index 48858f4..480fe1d 100755 --- a/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/MethodTransformer.java +++ b/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/MethodTransformer.java @@ -45,6 +45,25 @@ public MethodTransformer( private final Label startFinallyLabel = new Label(); + @Override + public void visitCode() { + super.visitCode(); + + boolean isConstructor = name.equals(ClassUtils.CONSTRUCTOR_METHOD_NAME); + + if ((ACC_STATIC & methodAccess) == 0 && isConstructor) { + Method enterMethod = callback.getPreEnterConstructor(); + visitLdcInsn(methodId); + visitMethodInsn( + INVOKESTATIC, + ClassUtils.getInternalClassName(enterMethod.getDeclaringClass().getName()), + enterMethod.getName(), + Type.getMethodDescriptor(enterMethod), + false); + } + + } + @Override protected void onMethodEnter() { visitLabel(startFinallyLabel); diff --git a/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/TransformerCallback.java b/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/TransformerCallback.java index 052049c..87c25ce 100755 --- a/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/TransformerCallback.java +++ b/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/TransformerCallback.java @@ -80,6 +80,17 @@ public Method getEnterConstructor() { } } + public Method getPreEnterConstructor() { + try { + return Profiler.class.getMethod("preEnterConstructor", long.class); + } catch (NoSuchMethodException e) { + for (Method m : Profiler.class.getDeclaredMethods()) { + System.out.println(m); + } + throw new RuntimeException(e); + } + } + public Method getDescribeClass() { try { return Profiler.class.getMethod("describeClass", long.class, Class.class); diff --git a/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/TestInstrumentSingleMethod.java b/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/TestInstrumentSingleMethod.java index bfd1aef..4d42cf8 100755 --- a/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/TestInstrumentSingleMethod.java +++ b/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/TestInstrumentSingleMethod.java @@ -18,10 +18,14 @@ public void testInstrumentSingleMethod() throws Exception { Class simpleClazz = transformingClassLoader.loadClass(SimpleClass.class.getName()); - simpleClazz.newInstance(); + Object o = simpleClazz.newInstance(); - assertEquals(2, invocationCountingProfiler.enterMethodImplCounter); - assertEquals(2, invocationCountingProfiler.leaveMethodImplCounter); + try { + simpleClazz.getMethod("method").invoke(o); + } catch (Exception e) {} + + assertEquals(3, invocationCountingProfiler.enterMethodImplCounter); + assertEquals(3, invocationCountingProfiler.leaveMethodImplCounter); assertEquals(1, invocationCountingProfiler.registerClassCounter); assertEquals(3, invocationCountingProfiler.registerMethodCounter); diff --git a/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/TestInstrumentSuperConsrtuctor.java b/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/TestInstrumentSuperConsrtuctor.java new file mode 100755 index 0000000..cdbcfd5 --- /dev/null +++ b/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/TestInstrumentSuperConsrtuctor.java @@ -0,0 +1,36 @@ +package com.jsonde.instrumentation; + +import com.jsonde.instrumentation.classloader.JSondeClassLoader; +import com.jsonde.instrumentation.profiler.InvocationCountingProfiler; +import com.jsonde.instrumentation.samples.SimpleClass; +import com.jsonde.instrumentation.samples.SuperConstructor; +import com.jsonde.profiler.Profiler; +import junit.framework.TestCase; + +public class TestInstrumentSuperConsrtuctor extends TestCase { + + public void testInstrumentSingleMethod() throws Exception { + + InvocationCountingProfiler invocationCountingProfiler = new InvocationCountingProfiler(); + + Profiler.initializeProfiler(invocationCountingProfiler); + + ClassLoader transformingClassLoader = new JSondeClassLoader(); + + Class simpleClazz = transformingClassLoader.loadClass(SuperConstructor.class.getName()); + + try { + Object o = simpleClazz.newInstance(); + } catch (Exception e) { + + } + + assertEquals("leave counters mismatch", 1, invocationCountingProfiler.leaveMethodImplCounter); + assertEquals("enter counters mismatch", 1, invocationCountingProfiler.enterMethodImplCounter); + assertEquals("preenter counters mismatch", 2, invocationCountingProfiler.preEnterConstructorImplCounter); + assertEquals(2, invocationCountingProfiler.registerClassCounter); + assertEquals(2, invocationCountingProfiler.registerMethodCounter); + + } + +} diff --git a/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/TestInstrumentXMLString.java b/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/TestInstrumentXMLString.java new file mode 100755 index 0000000..5a1d138 --- /dev/null +++ b/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/TestInstrumentXMLString.java @@ -0,0 +1,31 @@ +package com.jsonde.instrumentation; + +import com.jsonde.instrumentation.classloader.JSondeClassLoader; +import com.jsonde.instrumentation.profiler.InvocationCountingProfiler; +import com.jsonde.instrumentation.samples.SimpleClass; +import com.jsonde.instrumentation.samples.XMLString; +import com.jsonde.profiler.Profiler; +import junit.framework.TestCase; + +public class TestInstrumentXMLString extends TestCase { + + public void testInstrumentSingleMethod() throws Exception { + + InvocationCountingProfiler invocationCountingProfiler = new InvocationCountingProfiler(); + + Profiler.initializeProfiler(invocationCountingProfiler); + + ClassLoader transformingClassLoader = new JSondeClassLoader(); + + Class simpleClazz = transformingClassLoader.loadClass(XMLString.class.getName()); + + Object o = simpleClazz.newInstance(); + + assertEquals(1, invocationCountingProfiler.enterMethodImplCounter); + assertEquals(1, invocationCountingProfiler.leaveMethodImplCounter); + assertEquals(1, invocationCountingProfiler.registerClassCounter); + assertEquals(9, invocationCountingProfiler.registerMethodCounter); + + } + +} diff --git a/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/profiler/InvocationCountingProfiler.java b/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/profiler/InvocationCountingProfiler.java index 6098b33..5741bc7 100755 --- a/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/profiler/InvocationCountingProfiler.java +++ b/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/profiler/InvocationCountingProfiler.java @@ -59,10 +59,15 @@ public void removeMessageListener(MessageListener messageListener) { //To change body of implemented methods use File | Settings | File Templates. } - protected void enterConstructorImpl(long methodId, Object object, Object[] arguments) { + protected void enterConstructorImpl(long methodId, Object object) { enterConstructorImplCounter++; } + @Override + public void preEnterConstructorImpl(long methodId) { + preEnterConstructorImplCounter++; + } + public void redefineClass(byte[] bytecode, String className, ClassLoader classLoader) { //To change body of implemented methods use File | Settings | File Templates. } diff --git a/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/samples/SimpleClass.java b/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/samples/SimpleClass.java index c186a11..6b38a58 100755 --- a/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/samples/SimpleClass.java +++ b/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/samples/SimpleClass.java @@ -11,7 +11,7 @@ public class SimpleClass { } public void method() { - + throw new RuntimeException(); } } diff --git a/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/samples/SuperConstructor.java b/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/samples/SuperConstructor.java new file mode 100755 index 0000000..54100fb --- /dev/null +++ b/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/samples/SuperConstructor.java @@ -0,0 +1,18 @@ +package com.jsonde.instrumentation.samples; + +public class SuperConstructor extends BaseClass { + + public SuperConstructor() { + super(); + System.out.println("child consrtuctor called"); + } +} + +class BaseClass { + + public BaseClass() { + System.out.println("super consrtuctor called"); + throw new RuntimeException(); + } + +} diff --git a/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/samples/XMLString.java b/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/samples/XMLString.java new file mode 100755 index 0000000..b704d52 --- /dev/null +++ b/jsonde.instrumentation/src/test/java/com/jsonde/instrumentation/samples/XMLString.java @@ -0,0 +1,283 @@ +package com.jsonde.instrumentation.samples; + +/** + * Created by bedrin on 24.05.2015. + */ +public class XMLString { + + /** The character array. */ + public char[] ch; + + /** The offset into the character array. */ + public int offset; + + /** The length of characters from the offset. */ + public int length; + + // + // Constructors + // + + /** Default constructor. */ + public XMLString() { + } // () + + /** + * Constructs an XMLString structure preset with the specified + * values. + * + * @param ch The character array. + * @param offset The offset into the character array. + * @param length The length of characters from the offset. + */ + public XMLString(char[] ch, int offset, int length) { + setValues(ch, offset, length); + } // (char[],int,int) + + /** + * Constructs an XMLString structure with copies of the values in + * the given structure. + *

+ * Note: This does not copy the character array; + * only the reference to the array is copied. + * + * @param string The XMLString to copy. + */ + public XMLString(XMLString string) { + setValues(string); + } // (XMLString) + + // + // Public methods + // + + /** + * Initializes the contents of the XMLString structure with the + * specified values. + * + * @param ch The character array. + * @param offset The offset into the character array. + * @param length The length of characters from the offset. + */ + public void setValues(char[] ch, int offset, int length) { + this.ch = ch; + this.offset = offset; + this.length = length; + } // setValues(char[],int,int) + + public void setValues(XMLString s) { + setValues(s.ch, s.offset, s.length); + } // setValues(XMLString) + + public void clear() { + this.ch = null; + this.offset = 0; + this.length = -1; + } // clear() + + /** + * Returns true if the contents of this XMLString structure and + * the specified array are equal. + * + * @param ch The character array. + * @param offset The offset into the character array. + * @param length The length of characters from the offset. + */ + public boolean equals(char[] ch, int offset, int length) { + if (ch == null) { + return false; + } + if (this.length != length) { + return false; + } + + for (int i=0; i 0 ? new String(ch, offset, length) : ""; + } // toString():String + +} + +class XMLStringBuffer + extends XMLString { + + // + // Constants + // + + + /** Default buffer size (32). */ + public static final int DEFAULT_SIZE = 32; + + // + // Data + // + + // + // Constructors + // + + /** + * + */ + public XMLStringBuffer() { + this(DEFAULT_SIZE); + } // () + + /** + * + * + * @param size + */ + public XMLStringBuffer(int size) { + ch = new char[size]; + } // (int) + + /** Constructs a string buffer from a char. */ + public XMLStringBuffer(char c) { + this(1); + append(c); + } // (char) + + /** Constructs a string buffer from a String. */ + public XMLStringBuffer(String s) { + this(s.length()); + append(s); + } // (String) + + /** Constructs a string buffer from the specified character array. */ + public XMLStringBuffer(char[] ch, int offset, int length) { + this(length); + append(ch, offset, length); + } // (char[],int,int) + + /** Constructs a string buffer from the specified XMLString. */ + public XMLStringBuffer(XMLString s) { + this(s.length); + append(s); + } // (XMLString) + + // + // Public methods + // + + /** Clears the string buffer. */ + public void clear() { + offset = 0; + length = 0; + } + + /** + * append + * + * @param c + */ + public void append(char c) { + if(this.length + 1 > this.ch.length){ + int newLength = this.ch.length * 2 ; + if(newLength < this.ch.length + DEFAULT_SIZE){ + newLength = this.ch.length + DEFAULT_SIZE; + } + char [] tmp = new char[newLength]; + System.arraycopy(this.ch, 0, tmp, 0, this.length); + this.ch = tmp; + } + this.ch[this.length] = c ; + this.length++; + } // append(char) + + /** + * append + * + * @param s + */ + public void append(String s) { + int length = s.length(); + if (this.length + length > this.ch.length) { + int newLength = this.ch.length * 2 ; + if(newLength < this.ch.length + length + DEFAULT_SIZE){ + newLength = this.ch.length + length+ DEFAULT_SIZE; + } + + char[] newch = new char[newLength]; + System.arraycopy(this.ch, 0, newch, 0, this.length); + this.ch = newch; + } + s.getChars(0, length, this.ch, this.length); + this.length += length; + } // append(String) + + /** + * append + * + * @param ch + * @param offset + * @param length + */ + public void append(char[] ch, int offset, int length) { + if (this.length + length > this.ch.length) { + int newLength = this.ch.length * 2 ; + if(newLength < this.ch.length + length + DEFAULT_SIZE){ + newLength = this.ch.length + length + DEFAULT_SIZE; + } + char[] newch = new char[newLength]; + System.arraycopy(this.ch, 0, newch, 0, this.length); + this.ch = newch; + } + //making the code more robust as it would handle null or 0 length data, + //add the data only when it contains some thing + if(ch != null && length > 0){ + System.arraycopy(ch, offset, this.ch, this.length, length); + this.length += length; + } + } // append(char[],int,int) + + /** + * append + * + * @param s + */ + public void append(XMLString s) { + append(s.ch, s.offset, s.length); + } // append(XMLString) + + +} // class XMLStringBuffer diff --git a/jsonde.profiler/src/main/java/com/jsonde/profiler/Profiler.java b/jsonde.profiler/src/main/java/com/jsonde/profiler/Profiler.java index acc327f..5e79d0f 100755 --- a/jsonde.profiler/src/main/java/com/jsonde/profiler/Profiler.java +++ b/jsonde.profiler/src/main/java/com/jsonde/profiler/Profiler.java @@ -42,6 +42,10 @@ public static void enterMethod(long methodId) { getProfiler().enterMethodImpl(methodId); } + public static void preEnterConstructor(long methodId) { + getProfiler().preEnterConstructorImpl(methodId); + } + public static final String ENTER_CONSTRUCTOR_METHOD_NAME = "enterConstructor"; public static final String ENTER_CONSTRUCTOR_METHOD_DESCRIPTOR = @@ -120,6 +124,7 @@ public static void enterConstructor(long methodId, Object that) { protected void describeClassImpl(long methodId, Class clazz) {}; public void enterMethodImpl(long methodId) {}; + public void preEnterConstructorImpl(long methodId) {}; protected void enterConstructorImpl(long methodId, Object that) {}; From 5b43ec762e9320dd70a1e517eaa06dd416cc40ae Mon Sep 17 00:00:00 2001 From: bedrin Date: Sun, 24 May 2015 16:37:09 +0300 Subject: [PATCH 2/3] Removed redundant dependency --- jsonde.instrumentation/pom.xml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/jsonde.instrumentation/pom.xml b/jsonde.instrumentation/pom.xml index 2c77077..f7c6a5d 100755 --- a/jsonde.instrumentation/pom.xml +++ b/jsonde.instrumentation/pom.xml @@ -32,16 +32,6 @@ asm ${asm.version} - - org.ow2.asm - asm-util - ${asm.version} - - org.ow2.asm asm-commons From 65f5e7823b3f00407d85c568ae17c353b9ef054f Mon Sep 17 00:00:00 2001 From: bedrin Date: Mon, 25 May 2015 00:17:55 +0300 Subject: [PATCH 3/3] Minor improvements --- .../instrumentation/ByteCodeTransformer.java | 8 +++++-- .../instrumentation/ClassTransformer.java | 2 +- .../instrumentation/MethodTransformer.java | 24 +++++++++++-------- .../com/jsonde/profiler/ProfilerImpl.java | 5 +++- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/ByteCodeTransformer.java b/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/ByteCodeTransformer.java index 879aab5..ba8dd21 100755 --- a/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/ByteCodeTransformer.java +++ b/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/ByteCodeTransformer.java @@ -31,8 +31,9 @@ public byte[] transform(ClassLoader loader, className = ClassUtils.getFullyQualifiedName(className); - - if (className.startsWith(transformerPackage)&& (!className.startsWith("com.jsonde.instrumentation.samples"))) { + if ((className.startsWith(transformerPackage) && (!className.startsWith("com.jsonde.instrumentation.samples"))) || + className.startsWith("org.objectweb.asm")) { + // DO NOT transform objectweb ASM and jSONDE itself !!!11 return classfileBuffer; } @@ -100,6 +101,9 @@ protected String getCommonSuperClass(String type1, String type2) { classReader.accept(classVisitor, ClassReader.EXPAND_FRAMES); byte[] bytes = classWriter.toByteArray(); + + // Uncomment code below to debug + /*classReader.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter( System.out)), 0);*/ diff --git a/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/ClassTransformer.java b/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/ClassTransformer.java index 14122dc..40aba40 100755 --- a/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/ClassTransformer.java +++ b/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/ClassTransformer.java @@ -128,7 +128,7 @@ public MethodVisitor visitMethod( @Override public void visitEnd() { if (!staticConstructorExists) { - // TODO: does NOT work for redefinition + // TODO: check if redefinition is supported /*GeneratorAdapter mv = new GeneratorAdapter( super.visitMethod(Opcodes.ACC_STATIC, "", "()V", null, null), 0, "", "()V" diff --git a/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/MethodTransformer.java b/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/MethodTransformer.java index 480fe1d..63c4679 100755 --- a/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/MethodTransformer.java +++ b/jsonde.instrumentation/src/main/java/com/jsonde/instrumentation/MethodTransformer.java @@ -71,18 +71,20 @@ protected void onMethodEnter() { boolean isConstructor = name.equals(ClassUtils.CONSTRUCTOR_METHOD_NAME); boolean isStaticConstructor = name.equals(ClassUtils.STATIC_CONSTRUCTOR_METHOD_NAME); - // todo: now we call this guy for all method but we should think about an improvement: - Method describeClassMethod = callback.getDescribeClass(); - visitLdcInsn(classId); - visitLdcInsn(Type.getType("L" + ClassUtils.getInternalClassName(className) + ";")); - visitMethodInsn( - INVOKESTATIC, - ClassUtils.getInternalClassName(describeClassMethod.getDeclaringClass().getName()), - describeClassMethod.getName(), - Type.getMethodDescriptor(describeClassMethod), - false); + if ((ACC_STATIC & methodAccess) != 0) { + Method describeClassMethod = callback.getDescribeClass(); + visitLdcInsn(classId); + visitLdcInsn(Type.getType("L" + ClassUtils.getInternalClassName(className) + ";")); + visitMethodInsn( + INVOKESTATIC, + ClassUtils.getInternalClassName(describeClassMethod.getDeclaringClass().getName()), + describeClassMethod.getName(), + Type.getMethodDescriptor(describeClassMethod), + false); + } if ((ACC_STATIC & methodAccess) != 0 && isStaticConstructor) { + // TODO: if redefinition is supported, we should use code below /*Method describeClassMethod = callback.getDescribeClass(); visitLdcInsn(classId); visitLdcInsn(Type.getType("L" + ClassUtils.getInternalClassName(className) + ";")); @@ -113,6 +115,8 @@ protected void onMethodEnter() { Type.getMethodDescriptor(enterMethod), false); + // TODO: insert custom logic like handling SQL queries or HTTP requests here + } @Override diff --git a/jsonde.profiler/src/main/java/com/jsonde/profiler/ProfilerImpl.java b/jsonde.profiler/src/main/java/com/jsonde/profiler/ProfilerImpl.java index 4f8ffd9..7ea8441 100755 --- a/jsonde.profiler/src/main/java/com/jsonde/profiler/ProfilerImpl.java +++ b/jsonde.profiler/src/main/java/com/jsonde/profiler/ProfilerImpl.java @@ -374,8 +374,8 @@ public void redefineClass( redefineClassesExecutor.execute(new Runnable() { public void run() { + Class clazz = null; try { - Class clazz; if (null == classLoader) { clazz = ClassLoader.getSystemClassLoader().loadClass(className); @@ -391,6 +391,9 @@ public void run() { instrumentation.redefineClasses(new ClassDefinition[]{classDefinition}); + } catch (VerifyError e) { + System.err.println("Error while transforming class " + className + " loaded by " + classLoader + " ; class is " + clazz); + e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (UnmodifiableClassException e) {