0

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/URLClassPaths 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 invokevirtuals 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.

8
  • You are using invokespecial which is for constructors (which is correct) not invokevirtual which is for methods which could be overridden. Commented Apr 16, 2016 at 17:59
  • @PeterLawrey read the code again, I'm aware of what you're saying. That's not the problem. Commented Apr 16, 2016 at 18:00
  • I didn't say it was which is why I commented. I suspect the URLCLassLoader is being called before your transformation can kick in. Something has to load the classes your transformer is using. Commented Apr 16, 2016 at 18:02
  • this is a retransform. Note the bit: "I can put a println in fommil/URLClassPath's constructor and see it being constructed!" Commented Apr 16, 2016 at 18:03
  • Is it being constructed in all places you need it to be used. e.g. say your JVM creates a URLClassLoader to load all the basic classes and your transformer. After some of the code has been changed, will your URLClassLoader change type, or will it continue to be used? Commented Apr 16, 2016 at 18:08

1 Answer 1

1

I got it!

Consider this simple code

import java.util.*; class Baz { public void baz() { List list = new ArrayList(); } } 

which produces

 0: new #2 // class java/util/ArrayList 3: dup 4: invokespecial #3 // Method java/util/ArrayList."<init>":()V 7: astore_1 8: return 

compared to

import java.util.*; class Baz { public void baz() { List list = new LinkedList(); } } 

which produces

 0: new #2 // class java/util/LinkedList 3: dup 4: invokespecial #3 // Method java/util/LinkedList."<init>":()V 7: astore_1 8: return 

Note the new keyword which has a type in it!

The problem is that if one wishes to change the constructor one must also change the type definition that is returned. i.e. add this

 @Override public void visitTypeInsn(int opcode, String type) { if ("sun/misc/URLClassPath".equals(type)) super.visitTypeInsn(opcode, "fommil/URLClassPath"); else super.visitTypeInsn(opcode, type); } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.