2017-07-04 9 views
0

addTransformer、removeTransformer、およびreTransformerにインストゥルメントを学習しようとしています。別のスレッドでInstrument 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

トランスを削除すると、すでに変換されたクラスが古い状態にリセットされたわけではありません。これが起こるには、既にロードされているクラスを明示的に再変換する必要があります。あなたの最初の例では、変圧器が取り除かれた後に問題のクラスがロードされていると仮定していますが、2番目の例ではこれは当てはまりません。

クラスファイルトランスは、どのスレッドからも削除できます。

+0

あなたはinteceptorを追加したクラスを再変換する必要があることを意味しますか? –

+0

それは正しいです。 –

+0

しかし、removeTransformerの後に 'instrumentation.retransformClasses(Test.class);を追加してもまだ動作しません。私と共有するデモはありますか? –

関連する問題