Я надеялся создать монитор с помощью инструментария ASM для регистрации вызовов на java.lang.ProcessBuilder. Однако мои попытки, похоже, терпят неудачу. Ниже приведен пример кода примера. В принципе, этот код просто добавляет nop в конструктор java.lang.ProcessBuilder, а затем записывает новый (и оригинальный) файл класса в каталог с измененным классом. Это полностью для тестирования, поскольку я хотел убедиться, что все работает правильно, и я мог проверить измененный байт-код за пределами запуска агента. Если я укажу этот примерный код на другой (не-java.lang) класс, все будет работать. Можно ли изменить java.lang.ProcessBuilder с помощью javaagent?Использование ASM для мониторинга java.lang.ProcessBuilder
Спасибо заранее,
Джереми
public class Instrumentor {
public static void agentmain(String agentArgs, Instrumentation instrumentation) {
instrument(instrumentation);
}
public static void premain(String agentArgument, Instrumentation instrumentation) {
instrument(instrumentation);
}
private static void instrument(Instrumentation instrumentation) {
try {
instrumentation.addTransformer(new SampleTransformer());
} catch (TransformerException ex) {
Logger.getLogger(Instrumentor.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
//--------------------------------
public class SampleTransformer implements ClassFileTransformer {
public SampleTransformer() throws TransformerException {
}
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
if ("java/lang/ProcessBuilder".equals(className)) {
System.out.println("attempting to process " + className);
ClassReader cr = new ClassReader(classfileBuffer);
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
SampleClassAdapter adapter = new SampleClassAdapter(cw);
cr.accept(adapter, 0);
byte[] clz = cw.toByteArray();
try {
System.out.println("write " + className);
File p = new File("target\\modified-classes\\");
p.mkdirs();
File f = new File(p, className.replace('/', '.') + ".class");
File o = new File(p, className.replace('/', '.') + ".original.class");
Files.write(Paths.get(f.getAbsolutePath()), clz);
Files.write(Paths.get(o.getAbsolutePath()), classfileBuffer);
} catch (IOException ex) {
Logger.getLogger(SampleTransformer.class.getName()).log(Level.SEVERE, null, ex);
}
return clz;
}
return classfileBuffer;
}
}
//------------------------
public class SampleClassAdapter extends ClassVisitor {
public SampleClassAdapter(ClassVisitor cv) {
super(Opcodes.ASM5, cv);
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
if (mv != null && "<init>".equals(name)) {
mv = new SampleMethodAdapter(mv, access, name, desc);
}
return mv;
}
}
//----------------------------------------
public class SampleMethodAdapter extends AdviceAdapter {
public SampleMethodAdapter(final MethodVisitor methodVisitor,
final int access, final String name, final String descriptor) {
super(Opcodes.ASM5, methodVisitor, access, name, descriptor);
}
@Override
protected void onMethodEnter() {
mv.visitInsn(Opcodes.NOP);
}
}