2015-01-16 2 views
0

Я надеялся создать монитор с помощью инструментария 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); 
} 

}

ответ

0

Вы можете изменить класс во время выполнения, но для начала я предлагаю попробовать скомпилировать вам собственную версию, которую вы переопределения на ботинке путь класса. После этого вы можете работать над тем, что ASM требуется для того, чтобы эта инъекция кода работала во время выполнения.

0

Я понял, в чем проблема. Вызов ClassReader для принятия необходимо включить флаг EXPAND_FRAMES.

cr.accept(adapter, ClassReader.EXPAND_FRAMES); 

После исправления этого вызова я был в состоянии успешно изменить байтовый код java.lang.ProcessBuilder.

 Смежные вопросы

  • Нет связанных вопросов^_^