我正在对类路径中的所有类执行检测。这也包括JDK类。
如果我对我的班级(例如,HelloWorld)进行检测,则仪器代码会很好地工作。除此之外,我还会收到以下难看的错误。
java.lang.NoClassDefFoundError -klass:“ java / lang / NoClassDefFoundError”
Java运行时环境检测到致命错误:
内部错误(exceptions.cpp:427),pid = 35008,tid = 0x00007f8db6892700 致命错误:ExceptionMark析构函数不希望有任何待处理的异常
JRE版本:Java(TM)SE运行时环境(8.0_171-b11)(内部版本1.8.0_171-b11) Java虚拟机:Java HotSpot(TM)64位服务器虚拟机(25.171-b11混合模式linux-amd64压缩的oops) 无法写入核心转储。核心转储已被禁用。要启用核心转储,请在再次启动Java之前尝试“ ulimit -c unlimited”
包含更多信息的错误报告文件另存为: /home/user/yield_instrumentation/hs_err_pid35008.log
如果您要提交错误报告,请访问: http://bugreport.java.com/bugreport/crash.jsp ./run_agent.sh:第1行:35008中止了java -javaagent:yield_point.jar HelloWorld
错误日志文件包含以下内容:
----------------- T H R E A D ---------------
当前线程(0x00007f578c00b000):JavaThread“ main” [_thread_in_vm,id = 34854, 堆栈(0x00007f5794434000,0x00007f5794535000)]
堆栈:[0x00007f5794434000,0x00007f5794535000], sp = 0x00007f5794533a00,可用空间= 1022k本机帧:(J =已编译 Java代码,j =解释后的代码,Vv = VM代码,C =本机代码)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]线程:: 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 S ---------------
Java线程:(=>当前线程)0x00007f578c4de000 JavaThread “ C1 CompilerThread14”守护程序[_thread_blocked,id = 34901, 堆栈(0x00007f574b6f7000,0x00007f574b7f8000)] 0x00007f578c4dc000 JavaThread“ C1 CompilerThread13”守护程序[_thread_blocked,id = 34900, 堆栈(0x00007f574b7f8000,0x00007f574b8f9000)] 0x00007f578c4da000 JavaThread“ C1 CompilerThread12”守护程序[_thread_blocked,id = 34899, stack(0x00007f574b8f9000,0x00007f574b9fa000)]“ hs_err_pid34853.log” 1609L,80820C
下面是我的检测代码
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;
}
答案 0 :(得分:0)
这里是对该问题的详细解答。它与类加载器有关。在Java中,有多个类加载器,包括以下内容:
引导类加载器,用于加载所有与JDK相关的类。它具有某些路径来寻找到rt.jar的路径。
Classpath类加载器,用于加载类路径中的所有内容。
在需要时在运行时解析类。我要注入的代码包含对JDK之外的其他代码的引用(由引导类加载器加载)。在运行时,JDK将要求引导类加载器加载类,而这些类当然没有。它们是由classpath类加载器加载的。
为解决此问题,Java允许添加其他路径,以由默认的类加载器加载。
java -Xbootclasspath / p:javassist.jar:whatever.jar