我试图通过使用ASM 4.0重写类的字节码来实现这一点,用非native
存根替换所有native
方法。
到目前为止,我有这样的想法:
class ClassAdapter extends ClassVisitor {
public ClassAdapter(ClassVisitor cv) {
super(Opcodes.ASM4, cv);
}
@Override
public MethodVisitor visitMethod(int access, String base, String desc, String signature, String[] exceptions) {
return cv.visitMethod(access & ~Opcodes.ACC_NATIVE, base, desc, signature, exceptions);
}
}
,它由执行
private static byte[] instrument(byte[] originalBytes, ClassLoader loader) {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
ClassAdapter adapter = new ClassAdapter(cw);
ClassReader cr = new ClassReader(originalBytes);
cr.accept(adapter, ClassReader.SKIP_FRAMES);
return cw.toByteArray();
}
这似乎很简单:我从visitMethod()
中的方法中剥离了ACC_NATIVE
,并保持其他所有内容不变。但是,当我对java.lang.Object
执行此操作时,它将以
Exception in thread "main"
Exception: java.lang.StackOverflowError thrown from the UncaughtExceptionHandler in thread "main"
StackOverflow在检测时发生,而不是在运行时,我认为这是相当不寻常的。但是,如果我删除了& ~Opcodes.ACC_NATIVE
修饰符,java.lang.Object
会被重写(在本例中没有变化),并且可以完美地执行。
很明显,我没有做正确的事情,并且用非native
方法替换native
方法并不像去掉该方法上的native
修饰符那么简单,但是我不知道从哪里开始。ASM Docs根本不讨论使用native
方法。有使用ASM的经验的人知道我需要做什么才能让native
方法重写工作吗?
编辑
对不起,那条简短的、无用的消息是e.printStackTrace()
给我的,但使用e.getStackTrace()
我设法得到了一些有用的东西:
java.util.concurrent.ConcurrentHashMap.hash(ConcurrentHashMap.java:332)
java.util.concurrent.ConcurrentHashMap.put(ConcurrentHashMap.java:1124)
java.util.Collections$SetFromMap.add(Collections.java:3903)
sandbox.classloader.MyClassLoader.instrument(Unknown Source)
sandbox.classloader.MyClassLoader.loadClass(Unknown Source)
java.lang.ClassLoader.defineClass1(Native Method)
java.lang.ClassLoader.defineClass(ClassLoader.java:791)
java.lang.ClassLoader.defineClass(ClassLoader.java:634)
sandbox.classloader.MyClassLoader.findClass(Unknown Source)
sandbox.classloader.MyClassLoader.loadClass(Unknown Source)
sandbox.Tester.main(Unknown Source)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:601)
com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
因此,在我看来,错误实际上是在执行时发生的(例如,我错误地认为它是在检测时发生的),并且是调用hashCode()
的结果。碰巧的是,我(可能不正确地)从native
修饰符中剥离了一个原生方法hashCode()
。因此,很明显,它调用的是native
-stripped方法,这是导致问题的原因。
看起来奇怪的是,堆栈跟踪只有16帧深;如果它是一个StackOverflowError
,我会期望更多。
https://stackoverflow.com/questions/13274771
复制相似问题