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();
}
これは十分に単純なようです。ACC_NATIVE
メソッドを削除し、visitMethod()
他のすべては変更しません。しかし、これを行う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
メソッドの操作についてはまったく説明していません。native
ASMを使用した経験のある人は、メソッドの書き直しを機能させるために私が何をする必要があるかを知っていますか?
編集
申し訳ありませんが、その短くて役に立たないメッセージが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()
。たまたま、hashCode()
私が(おそらく間違って)native
修飾子を取り除いたネイティブメソッドの1つ。したがって、明らかに、問題の原因となっている-strippedメソッドを呼び出しています。native
本当に奇妙に思えるのは、スタックトレースの深さが16フレームしかないことです。それがだったことを考えると、私はもう少し期待していたでしょうStackOverflowError
。