I am trying to use ASM in a javaagent to change the class that is being constructed (sun/misc/URLClassPath
) to another one (fommil/URLClassPath
) that inherits from it and overrides all the methods. I know that the target class (java/net/URLClassLoader
), which I am retransforming
, is the only thing that creates sun/misc/URLClassPath
s and only in its constructor.
The basic idea is something like this:
@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);
}
}
};
}
I can put a println
in fommil/URLClassPath
's constructor and see it being constructed!
However, none of fommil.URLClassPath
's methods are being called. Only the methods on the super class are ever called.
Even if I change the above code so that not only invokespecial
/ <init>
, but all calls to URLClassPath
are rewritten so that their invokevirtual
points to my class, my methods are still never called. I've even tried doing this for all of the inner classes of URLClassLoader
.
So why are the invokevirtual
s not finding the override methods, even when they are retransformed? Is what I'm doing - changing the type of the thing being constructed - just fundamentally not possible? If so, can somebody please explain why?
I am aware that instrumenting core JDK classes is pretty evil, but frankly I don't really have much of an alternative.
The only thing left to try is to instrument all classes that try to instantiate URLClassLoader
and have them poke into the internal ucp
field and replace it with my implementation.