Я пытаюсь сделать это, перезаписав байт-код класса, используя ASM 4.0, чтобы заменить все методы native
с заглушками <<20 > .
Пока у меня есть это:
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
вообще. Кто-нибудь, у кого есть опыт работы с 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()
. Как это бывает, hashCode()
один из нативных методов, который я (возможно, неправильно) лишил его модификатора native
. Настолько ясно, что он вызывает методы native
-stripped, которые вызывают проблему.
Что кажется действительно нечетным, так это то, что трассировка стека составляет всего 16 кадров; Я бы предпочел, чтобы он получил больше StackOverflowError
.