Ich versuche, ASM in einem javaagent to change the class that is being constructed (sun/misc/URLClassPath
) zu einem anderen (fommil/URLClassPath
) zu verwenden, der davon erbt und alle Methoden überschreibt. Ich weiß, dass die Zielklasse (java/net/URLClassLoader
), die ich bin retransforming
, ist das einzige, was sun/misc/URLClassPath
s und nur in seinem Konstruktor erstellt.wie man eine andere Klasse durch Instrumentierung/ASM instanziiert
Die Grundidee ist so etwas wie dieses:
@Override
public MethodVisitor visitMethod(int access,
String name,
String desc,
String signature,
String[] exceptions) {
MethodVisitor visitor = super.visitMethod(access, name, desc, signature, exceptions);
return new MethodVisitor(Opcodes.ASM5, visitor) {
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
if (opcode == Opcodes.INVOKESPECIAL && "sun/misc/URLClassPath".equals(owner) && "<init>".equals(name)) {
super.visitMethodInsn(opcode, "fommil/URLClassPath", name, desc, itf);
} else {
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
}
};
}
ich einen println
in fommil/URLClassPath
‚s Konstruktor setzen können und sehen es aufgebaut ist!
Es wird jedoch keiner der Methoden fommil.URLClassPath
aufgerufen. Nur die Methoden der Superklasse werden immer aufgerufen.
Auch wenn ich den obigen Code ändern, so dass nicht nur invokespecial
/<init>
, aber alle Anrufe auf URLClassPath
neu geschrieben werden, so dass ihre invokevirtual
Punkte zu meiner Klasse, meine Methoden noch nie genannt. Ich habe sogar versucht, dies für alle inneren Klassen von URLClassLoader
zu tun.
Warum finden die invokevirtual
s nicht die Override-Methoden, auch wenn sie erneut umgewandelt werden? Was ich mache - die Art des zu konstruierenden Gegenstandes zu verändern - ist grundsätzlich nicht möglich? Wenn ja, kann jemand bitte erklären warum?
Ich bin mir bewusst, dass die Instrumentierung JDK Kern-Klassen ist ziemlich böse, aber ehrlich gesagt habe ich nicht wirklich viel von einer Alternative.
Das einzige, was noch zu versuchen ist, ist das Instrumentieren aller Klassen, die versuchen, URLClassLoader
zu instanziieren und sie in das interne ucp
Feld stecken zu lassen und es durch meine Implementierung zu ersetzen.
hinzu. Sie verwenden Invokespecial, das für Konstruktoren ist (was korrekt ist), nicht invokevirtual, das für Methoden ist, die überschrieben werden können. –
@PeterLawrey lesen Sie den Code erneut, ich weiß, was Sie sagen. Das ist nicht das Problem. – fommil
Ich habe nicht gesagt, dass es war, weshalb ich kommentiert habe. Ich vermute, dass der URLCLassLoader aufgerufen wird, bevor die Umwandlung eintreten kann. Etwas muss die Klassen laden, die Ihr Transformator verwendet. –