2017-07-04 54 views
0

我正在嘗試學習儀器以添加變形器,removeTransformer和reTransformer。儀器removeTransformer在不同線程中不工作

我試圖添加變壓器,它運作良好。

當我添加變壓器後,如下圖所示,除去變壓器,它也很好。

public static void premain(String agentArgs, Instrumentation instrumentation) { 
    ClassFileTransformer transformer = new ClassFileTransformer() { 
     public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { 
      if (!className.contains("Test")) { 
       return classfileBuffer; 
      } 
      ClassReader cr = new ClassReader(classfileBuffer); 

      ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); 
      cr.accept(new FieldAdapter(cw, new FieldNode(ASM5, Opcodes.ACC_PRIVATE, "hello", Type.getDescriptor(String.class), "test", "first")), 0); 
      return cw.toByteArray(); 
     } 
    }; 

    instrumentation.addTransformer(transformer, true); 
    instrumentation.removeTransformer(transformer); 
    } 

但是,當我試圖在不同線程中移除變壓器時,它不起作用。

public static void premain(String agentArgs, Instrumentation instrumentation) { 
    ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); 

    ClassFileTransformer transformer = new ClassFileTransformer() { 
     public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { 
      if (!className.contains("Test")) { 
       return classfileBuffer; 
      } 
      ClassReader cr = new ClassReader(classfileBuffer); 

      ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); 
      cr.accept(new FieldAdapter(cw, new FieldNode(ASM5, Opcodes.ACC_PRIVATE, "hello", Type.getDescriptor(String.class), "test", "first")), 0); 
      return cw.toByteArray(); 
     } 
    }; 
    instrumentation.addTransformer(transformer, true); 

    executor.scheduleAtFixedRate(new RemoveTransform(instrumentation, transformer), 3, 10, TimeUnit.SECONDS); 
} 
static class RemoveTransform implements Runnable { 
    private Instrumentation instrumentation; 
    private ClassFileTransformer classFileTransformer; 
    public RemoveTransform(Instrumentation instrumentation, ClassFileTransformer classFileTransformer) { 
     this.instrumentation = instrumentation; 
     this.classFileTransformer = classFileTransformer; 
    } 

    public void run() { 
     System.out.println("removed transform....."); 
     instrumentation.removeTransformer(classFileTransformer); 
    } 
} 

我檢查了輸出,我肯定是移除變壓器執行的線程。

回答

0

當你移除一個變壓器時,這並不意味着那些已經在復位時轉換到舊狀態的類。要發生這種情況,您必須顯式重新轉換已經加載的類。我假設在你的第一個例子中,所討論的類在變換器被移除後被加載,而在第二個例子中這不再是真的。

類文件轉換器可以從任何線程中刪除。

+0

你的意思是我必須重新轉換添加inteceptor的類? –

+0

這是正確的。 –

+0

但是在添加'instrumentation.retransformClasses(Test.class);'removeTransformer之後它仍然不起作用?你有一個演示與我分享? –