2017-11-30 5 views
0

添付するプログラムのコードは以下の通りです。エージェントを実行プロセスに接続すると、バイトバディトランスが有効にならないようです。

public class Foo { 

} 

public class TestEntry { 
public TestEntry() { 

} 

public static void main(String[] args) throws Exception { 
    try 
    { 
     while(true) 
     { 
      System.out.println(new Foo().toString()); 
      Thread.sleep(1000); 
     } 
    } 
    catch(Exception e) 
    {} 
} 
} 

Foo.toString()が次のエージェントを使用して 'test'を返すようにしようとしています。

public class InjectionAgent { 

public InjectionAgent() { 

} 

public static void agentmain(String args, Instrumentation inst) throws Exception 
{ 
    System.out.println("agentmain Args:" + args); 
    new AgentBuilder.Default() 
    .type(ElementMatchers.named("Foo")) 
    .transform(new AgentBuilder.Transformer() { 

     @Override 
     public Builder<?> transform(Builder<?> arg0, TypeDescription arg1, 
       ClassLoader arg2, JavaModule arg3) { 
      return arg0.method(ElementMatchers.named("toString")) 
        .intercept(FixedValue.value("test")); 
     } 

    }).installOn(inst); 
} 

public static void premain(String args, Instrumentation inst) throws Exception 
{ 
    System.out.println("premain Args:" + args); 
    new AgentBuilder.Default() 
    .type(ElementMatchers.named("Foo")) 
    .transform(new AgentBuilder.Transformer() { 

     @Override 
     public Builder<?> transform(Builder<?> arg0, TypeDescription arg1, 
       ClassLoader arg2, JavaModule arg3) { 
      return arg0.method(ElementMatchers.named("toString")) 
        .intercept(FixedValue.value("test")); 
     } 

    }).installOn(inst); 
} 
} 

私は、-javaagentの方法を使用した場合に成功しましたが、添付の方法は失敗しましたが、ここでは添付のコードです。

public class Injection { 

    public Injection() { 
    } 

    public static void main(String[] args) throws AttachNotSupportedException, IOException, AgentLoadException, AgentInitializationException, InterruptedException { 
    VirtualMachine vm = null; 
    String agentjarpath = args[0]; 
    vm = VirtualMachine.attach(args[1]); 

    vm.loadAgent(agentjarpath, "This is Args to the Agent."); 
    vm.detach(); 
    } 

} 

Iは===========取り付けた後、TestEntryの出力は

[Byte Buddy] DISCOVERY Foo [sun.[email protected], null, loaded=true]

[Byte Buddy] TRANSFORM Foo [[email protected], null, loaded=true]

[Byte Buddy] COMPLETE Foo [[email protected], null, loaded=true]

[email protected]

[email protected]

[email protected]

[email protected]

[email protected]

を示し、エージェントにAgentBuilder.Listener.StreamWriting.toSystemOut()を追加しようとしました============================================================================================================== =========== 私はこの

public class Foo { 
    public String Bar() 
    { 
    return "Bar"; 
    } 
} 

のようにFooの中のパブリックメソッド「バー」を定義した後、私は次のようにFoo.Barを()「修正」を返し作るしようとしていました方法:

public static void agentmain(String args, Instrumentation inst) throws Exception 
{ 
    System.out.println("agentmain Args:" + args); 
    premain(args, inst); 

    new AgentBuilder.Default() 
    .with(RedefinitionStrategy.RETRANSFORMATION) 
    .disableClassFormatChanges() 
    .with(AgentBuilder.Listener.StreamWriting.toSystemOut()) 
    .type(ElementMatchers.named("Foo")) 
    .transform(new AgentBuilder.Transformer() { 

     @Override 
     public Builder<?> transform(Builder<?> arg0, TypeDescription arg1, 
       ClassLoader arg2, JavaModule arg3) { 
      return arg0.visit(Advice.to(InjectionTemplate.class).on(ElementMatchers.named("Bar"))); 
     } 

    }) 


    .installOn(inst); 

} 
static class InjectionTemplate { 

    @Advice.OnMethodExit 
    static void exit(@Advice.Return String self) { 
     System.out.println(self.toString() + " " + self.getClass().toString()); 
     self = new String("modified"); 
    } 

} 

が、私はこのエラーを得た:

java.lang.IllegalStateException: Cannot write to read-only parameter class java.lang.String at 1

任意の提案を?

+0

'Foo'には' toString() 'メソッドがありません。再定義はメソッドの追加をサポートしていません。メンバーの追加または削除をサポートするのはロード時計装のみです。 – Holger

+0

戻り値の読み取り専用属性をfalseに設定する必要があります。 –

+0

@Rafael私は、それが今動作することを確認します。もう一つの質問ですが、私の再定義を取り除くことは可能ですか?いくつかの状況については、プログラムを元の状態に戻したいのですが... – surlary

答えて

0

エージェントの再定義を使用しているようではありません。あなたは使用してそれを活性化させることができます。

new AgentBuilder.Default() 
    .with(RedefinitionStrategy.RETRANSFORMATION) 
    .disableClassFormatChanges(); 

最後の部分は、(動的コードの進化VM、ホットスポットのカスタムビルドの顕著な例外を除いて)ほとんどのJVM上で必要とされます。フィールドやメソッドを追加しないようにByte Buddyに指示します。ほとんどのVMではサポートされていません。

この場合、メソッドの元の実装を呼び出すことはできませんが、あなたのFixedValueでは必須ではありません。通常、Byte Buddyのユーザーは、クラスの動的変換を適用するエージェントを作成するときにAdviceを利用します。

+0

thx Rafaelと@Holger あなたの意見によると、私はさらなる試みをしました。私の更新を見てください。 – surlary

関連する問題