I am performing instrumentation on all classes in the class path. This includes the JDK classes as well.
Instrumentation code works very well if I instrument my class (HelloWorld for example). Other than that, I receive the below ugly error.
java.lang.NoClassDefFoundError - klass: 'java/lang/NoClassDefFoundError'
A fatal error has been detected by the Java Runtime Environment:
Internal Error (exceptions.cpp:427), pid=35008, tid=0x00007f8db6892700 fatal error: ExceptionMark destructor expects no pending exceptions
JRE version: Java(TM) SE Runtime Environment (8.0_171-b11) (build 1.8.0_171-b11) Java VM: Java HotSpot(TM) 64-Bit Server VM (25.171-b11 mixed mode linux-amd64 compressed oops) Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
An error report file with more information is saved as: /home/user/yield_instrumentation/hs_err_pid35008.log
If you would like to submit a bug report, please visit: http://bugreport.java.com/bugreport/crash.jsp ./run_agent.sh: line 1: 35008 Aborted java -javaagent:yield_point.jar HelloWorld
The error log files contains the following:
--------------- T H R E A D ---------------
Current thread (0x00007f578c00b000): JavaThread "main" [_thread_in_vm, id=34854, stack(0x00007f5794434000,0x00007f5794535000)]
Stack: [0x00007f5794434000,0x00007f5794535000], sp=0x00007f5794533a00, free space=1022k Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) V [libjvm.so+0xacfffa] VMError::report_and_die()+0x2ba V [libjvm.so+0x500189] report_fatal(char const*, int, char const*)+0x59 V [libjvm.so+0x582bd0] ExceptionMark::~ExceptionMark()+0xb0 V [libjvm.so+0xa7cea6] Threads::create_vm(JavaVMInitArgs*, bool*)+0x396 V [libjvm.so+0x6d6e44] JNI_CreateJavaVM+0x74 C [libjli.so+0x797e] JavaMain+0x9e C [libpthread.so.0+0x7494] start_thread+0xc4
--------------- P R O C E S S ---------------
Java Threads: ( => current thread ) 0x00007f578c4de000 JavaThread "C1 CompilerThread14" daemon [_thread_blocked, id=34901, stack(0x00007f574b6f7000,0x00007f574b7f8000)] 0x00007f578c4dc000 JavaThread "C1 CompilerThread13" daemon [_thread_blocked, id=34900, stack(0x00007f574b7f8000,0x00007f574b8f9000)] 0x00007f578c4da000 JavaThread "C1 CompilerThread12" daemon [_thread_blocked, id=34899, stack(0x00007f574b8f9000,0x00007f574b9fa000)] "hs_err_pid34853.log" 1609L, 80820C
Below is my instrumentation Code
public byte[] transform(ClassLoader loader, String className,
Class classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
byte[] byteCode = classfileBuffer;
try {
ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.makeClass(new ByteArrayInputStream(classfileBuffer));
CtClass greeting_ct = classPool.get("whatever.GreetingFactory");
/*if(!ctClass.getSimpleName().equalsIgnoreCase("HelloWorld")) {
return byteCode;
}*/
//The below returns all methods including constructors
CtBehavior[] all_methods = ctClass.getDeclaredBehaviors();
for (CtBehavior method : all_methods) {
MethodInfo methodInfo = method.getMethodInfo();
CodeAttribute code = methodInfo.getCodeAttribute();
CodeIterator instruction_iterator = code.iterator();
int instruction_loc=0;
Bytecode invoke_hi = new Bytecode(methodInfo.getConstPool());
invoke_hi.addInvokestatic(greeting_ct,"hello", void_non());
int pos = instruction_iterator.insertEx(invoke_hi.get());
instruction_iterator.insert(code.getExceptionTable(), pos);
}
ctClass.detatch(); //Without or without this statement ... result is the same
return ctClass.toBytecode();
} catch (Throwable ex) {
ex.printStackTrace();
}
return byteCode;
}
public static String void_non() {
String desc = Descriptor.ofMethod(CtClass.voidType, null);
return desc;
}