package com.navercorp.pinpoint.profiler.instrument;
import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
/**
* @author Woonduk Kang(emeroad)
*/
public class BytecodeDumpTransformer implements ClassFileTransformer {
private final ClassFileTransformer delegate;
private final BytecodeDumpService bytecodeDumpService;
public static ClassFileTransformer wrap(ClassFileTransformer classFileTransformer, ProfilerConfig profilerConfig) {
return new BytecodeDumpTransformer(classFileTransformer, profilerConfig);
}
private BytecodeDumpTransformer(ClassFileTransformer delegate, ProfilerConfig profilerConfig) {
if (delegate == null) {
throw new NullPointerException("delegate must not be null");
}
if (profilerConfig == null) {
throw new NullPointerException("profilerConfig must not be null");
}
this.delegate = delegate;
this.bytecodeDumpService = new ASMBytecodeDumpService(profilerConfig);
}
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
byte[] transformBytes = null;
boolean success = false;
try {
transformBytes = delegate.transform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
success = true;
return transformBytes;
} finally {
this.bytecodeDumpService.dumpBytecode("original bytecode dump", className, classfileBuffer, loader);
final boolean bytecodeChanged = isChanged(classfileBuffer, transformBytes);
if (success && bytecodeChanged) {
this.bytecodeDumpService.dumpBytecode("transform bytecode dump", className, transformBytes, loader);
}
}
}
private boolean isChanged(byte[] classfileBuffer, byte[] transformBytes) {
if (transformBytes == null) {
return false;
}
if (classfileBuffer == transformBytes) {
return false;
}
return true;
}
}