Цель состоит в том, чтобы инструмент только для классов из моего проекта, но для целей тестирования я временно настроил агент для инструментов все пакеты, включая классы, нагрузки на jdk. < /p>
. До выполнения агента Java.
Код: Выделить всё
jdk.internal.reflect.MethodAccessorGenerator
< /code>
Этот класс динамически генерирует другой класс через: < /p>
return JLA.defineClass(newLoader, name, bytes, null, "__ClassDefiner__");
< /code>
Этот код запускает преобразование класса класса, даже для динамически сгенерированных классов.
i заключаю, что если это разрешено без ограничения на собственном уровне JVM, то это должно быть возможно для прибора этих сгенерированных классов.package jdk.internal.reflect;
import java.lang.reflect.InvocationTargetException;
import java.rmi.server.RemoteObject;
public class GeneratedSerializationConstructorAccessor1 extends SerializationConstructorAccessorImpl {
public Object newInstance(Object[] var1) throws InvocationTargetException {
RemoteObject var10000;
RemoteObject var10001;
try {
var10000 = new RemoteObject;
var10001 = var10000;
if (var1 != null && var1.length != 0) {
throw new IllegalArgumentException();
}
} catch (NullPointerException | ClassCastException var3) {
throw new IllegalArgumentException(var3.toString());
}
try {
var10001.();
return var10000;
} catch (Throwable var2) {
throw new InvocationTargetException(var2);
}
}
}
Когда я инструментарует этот класс с простой линией трассировки, он работает отлично:
Код: Выделить всё
package jdk.internal.reflect;
import fr.code.api.CodeMonitoring;
import java.lang.reflect.InvocationTargetException;
import java.rmi.server.RemoteObject;
public class GeneratedSerializationConstructorAccessor1 extends SerializationConstructorAccessorImpl {
private static boolean b_code_newInstance_0;
public Object newInstance(Object[] var1) throws InvocationTargetException {
CodeMonitoring.callMethod("jdk/internal/reflect/GeneratedSerializationConstructorAccessor1", "newInstance", "([Ljava/lang/Object;)Ljava/lang/Object;");
RemoteObject var10000;
RemoteObject var10001;
try {
var10000 = new RemoteObject;
var10001 = var10000;
if (var1 != null && var1.length != 0) {
throw new IllegalArgumentException();
}
} catch (NullPointerException | ClassCastException var3) {
throw new IllegalArgumentException(var3.toString());
}
try {
var10001.();
return var10000;
} catch (Throwable var2) {
throw new InvocationTargetException(var2);
}
}
}
Однако, если я назначу результат вызова метода логической переменной, JVM сбои:
Код: Выделить всё
b_code_newInstance_0 = CodeMonitoring.callMethod("jdk/internal/reflect/GeneratedSerializationConstructorAccessor1", "newInstance", "([Ljava/lang/Object;)Ljava/lang/Object;");
< /code>
[b] наблюдаемая проблема < /strong> < /p>
В Java 8 это запускает исключение:
Java.lang.noclassDeffounderRorrish> Вопрос < /strong> < /p>
Я понимаю, что этот класс является внутренним, динамически сгенерированным классом в Java.
Поскольку его можно инструментально, мне просто любопытно понять, почему присвоение результата логическому выбору, в то время как простой метод не делает. Примечание [/b]
Сгенерированный код, будь то в Java 8 или Java 21, имеет основную версию Bytecode 49, которая соответствует Java 5.
Код ASM, используемый для изменения этого байткода, следующим:
public void visitCode() {
super.visitCode();
mv.visitLdcInsn(className);
mv.visitLdcInsn(name);
mv.visitLdcInsn(descriptor);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "fr/deadcode/api/CodeMonitoring", "callMethod", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z", false);
mv.visitFieldInsn(Opcodes.PUTSTATIC, className, field, "Z");
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... elegatingc
Мобильная версия