2017-11-30 10 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(); 
    } 

} 

난 =========== 부착 후 TestEntry의 출력

[Byte Buddy] DISCOVERY Foo [[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.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