我不知道Spring是否具有执行此操作的手段,但是AFAIK嵌入在Spring中的ASM类不包含TraceClassVisitor
。因此,如果您喜欢它的输出,则必须直接使用ASM(工件asm-util
),我假设您是为示例代码使用的。如果您想坚持使用板载工具,则只需编写一个转换器,即可将全字节代码作为类文件转储到文件中,然后使用JDK命令行工具javap
查看该文件,例如通过javap -c -p -v MyDumpedBytes.class
。
无论如何,一件容易的事是实现Java代理,并通过-javaagent:/path/to/my-agent.jar
将其附加到Java命令行,以启动Spring项目。我为您找到了this article,它说明了如何使用清单文件等实现简单的Java代理,以及如何通过Java Attach API将其附加到正在运行的进程。本文以Javassist为例,编写了一个转换器,但您可以改用ASM。
您的Java代理+转换器看起来像这样:
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.util.TraceClassVisitor;
import java.io.PrintWriter;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
class TraceClassTransformer implements ClassFileTransformer {
/**
* Attach agent dynamically after JVM start-up
*/
public static void agentmain(String commandLineOptions,Instrumentation instr) {
premain(commandLineOptions,instr);
}
/**
* Start agent via <code>-javaagent:/path/to/my-agent.jar=<i>options</i></code> JVM parameter
*/
public static void premain(String commandLineOptions,Instrumentation instrumentation) {
TraceClassTransformer transformer = new TraceClassTransformer();
instrumentation.addTransformer(transformer,true);
}
@Override
public byte[] transform(ClassLoader loader,String className,Class<?> classBeingRedefined,ProtectionDomain protectionDomain,byte[] classfileBuffer) throws IllegalClassFormatException {
dumpClass(classfileBuffer);
// Do not apply any transformation
return null;
}
private void dumpClass(byte[] classfileBuffer) {
TraceClassVisitor visitor = new TraceClassVisitor(new PrintWriter(System.out));
ClassReader reader = new ClassReader(classfileBuffer);
reader.accept(visitor,0);
}
}
只需确保代理的清单通过Can-Retransform-Classes: true
启用重新转换即可。
代理启动后,您可以致电instrumentation.retransformClasses(proxyInstance.getClass());
,然后享受日志输出。
为了使本示例更简单,让我们使用byte-buddy-agent
,它包含一个精巧的小工具集,用于在运行时附加转换器,而无需将它们包装到Java代理中。该构件很小,不包含其余的ByteBuddy,仅包含代理工具。
这将简化您的类(您可以保留或删除premain
和agentmain
方法,具体取决于您是否打算将该类用作Java代理):
import net.bytebuddy.agent.ByteBuddyAgent;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.util.TraceClassVisitor;
import java.io.Closeable;
import java.io.PrintWriter;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;
import java.lang.reflect.Proxy;
import java.security.ProtectionDomain;
class TraceClassTransformer implements ClassFileTransformer {
public static void main(String[] args) throws UnmodifiableClassException {
// Easy way to get an Instrumentation instance,so we can directly register our transformer on it
Instrumentation instrumentation = ByteBuddyAgent.install();
// I am just creating a Java dynamic proxy for a JRE interface. In your own application,// you would just get a reference to a dynamic proxy created by Spring.
Object proxyInstance = Proxy.newProxyInstance(
Closeable.class.getClassLoader(),new Class<?>[] { Closeable.class },(proxy,method,args1) -> null
);
// Register + use dummy ClassFileTransformer,then unregister again (optional)
TraceClassTransformer transformer = new TraceClassTransformer();
try {
instrumentation.addTransformer(transformer,true);
instrumentation.retransformClasses(proxyInstance.getClass());
}
finally {
instrumentation.removeTransformer(transformer);
}
}
@Override
public byte[] transform(ClassLoader loader,0);
}
}
运行示例main
类时,您将获得类似以下内容的控制台日志:
// class version 58.0 (58)
// access flags 0x11
public final class com/sun/proxy/$Proxy0 extends java/lang/reflect/Proxy implements java/io/Closeable {
// access flags 0xA
private static Ljava/lang/reflect/Method; m0
// access flags 0xA
private static Ljava/lang/reflect/Method; m1
// access flags 0xA
private static Ljava/lang/reflect/Method; m2
// access flags 0xA
private static Ljava/lang/reflect/Method; m3
// access flags 0x1
public <init>(Ljava/lang/reflect/InvocationHandler;)V
ALOAD 0
ALOAD 1
INVOKESPECIAL java/lang/reflect/Proxy.<init> (Ljava/lang/reflect/InvocationHandler;)V
RETURN
MAXSTACK = 2
MAXLOCALS = 2
(...)
本文链接:https://www.f2er.com/2009966.html