Skip to content
This repository was archived by the owner on May 2, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions jsonde.instrumentation/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,6 @@
<artifactId>asm</artifactId>
<version>${asm.version}</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-util</artifactId>
<version>${asm.version}</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-commons</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -34,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;
}

Expand Down Expand Up @@ -101,11 +99,25 @@ 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();

// Uncomment code below to debug

/*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;

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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, "<clinit>", "()V", null, null),
0, "<clinit>", "()V"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,25 +45,46 @@ 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);

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) + ";"));
Expand Down Expand Up @@ -94,6 +115,8 @@ protected void onMethodEnter() {
Type.getMethodDescriptor(enterMethod),
false);

// TODO: insert custom logic like handling SQL queries or HTTP requests here

}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
Original file line number Diff line number Diff line change
@@ -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);

}

}
Original file line number Diff line number Diff line change
@@ -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);

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class SimpleClass {
}

public void method() {

throw new RuntimeException();
}

}
Original file line number Diff line number Diff line change
@@ -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();
}

}
Loading