简体   繁体   中英

ClassTransformer not executing

USE CASE

I'm attempting to write a Java SE8 ClassFileTransformer implementation. The goal of this is Debugging. I'm well aware of BTrace but it doesn't really fit the bill for what I'm trying to do. What that is, is internal method level inspection. BTrace limits its breakpoints to entry/exit. I wanted to get into the details of this.

So I figured I'd do this myself with ASM now hard can it be?

( ASM is a byte code manipulation library used by ByteBuddy and BTrace)


PROBLEM

So I started by defining a simple ClassFileTransformer .

public class PreMainInjection {
    public static void premain(String agentArgs,
          Instrumentation inst) {
        inst.addTransformer(new EntryPoint(), true);
    }
}

public class EntryPoint implements ClassFileTransformer {
    public EntryPoint() { }
    @Override
    public byte[] transform(ClassLoader classloader, String name, 
           Class<?> clazz, ProtectionDomain prot, byte[] data) {
       System.out.printf("Loaded: %s\n", name);
    }
}

And this worked perfectly :DI see a list of all the classes as the application I'm inspecting start.

So now I bring in ASM.

public class PreMainInjection {
    public static void premain(String agentArgs,
          Instrumentation inst) {
        inst.addTransformer(new EntryPoint(), true);
    }
}

public class EntryPoint implements ClassFileTransformer {
    public EntryPoint() { }
    @Override
    public byte[] transform(ClassLoader classloader, String name, 
           Class<?> clazz, ProtectionDomain prot, byte[] data) {
       ClassReader reader = new ClassReader(bytes);
       ClassNode node = new ClassNode();
       ClassWriter writer = new ClassWriter(
           ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS);
       reader.accept(node, ClassReader.EXPAND_FRAMES);
       System.out.printf("Name: %s", node.name);
       node.accept(writer);
       return writer.toByteArray();
    }
}

This works... so far as my app doesn't break. But I never see a single debug output.

So what is going on?

To expand further if my agent just does

 System.out.printf("Loaded %s\n", name);
 return null;

The app still works and I can see the outputs. So I'm deeply confused.

To answer your first question how hard ASM can be: very hard.

To get to your actual point: you are probably getting an exception before reaching the print output. With a class file transformer, exceptions are suppressed if they escape the transform method. Did you try to wrap the code in a try-catch block to see if an exception is raised?

There is also a chance that you did not bundle ASM with your agent. In this case, you would get an error rather than an exception during your transformer's execution. Finally, I would try your agent without frame computation as this requires access to all referenced class files which can also be a source of problems.

So I appear to be hitting a weird edge case

ClassNode 's internal fields are only instantiated after a full visit of the ClassReader has been conducted. As that is the case it is statically provable System.out.printf("Name: %s", node.name); will always return a NullPointerException at compile time.

So I believe the JVM simply doesn't load my ClassFileTransformer .

Either way I have the system working.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM