0

The code of my program to be attached is as below.

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)
    {}
}
}

What I attempt to do is to make Foo.toString() returns 'test' by using the following agent.

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); 
}
}

I notice that, it was successful when I using -javaagent way, whereas attach way failed, here is code for attach.

    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 tried to add AgentBuilder.Listener.StreamWriting.toSystemOut() to the agent, after attaching, the output of TestEntry shows

[Byte Buddy] DISCOVERY Foo [sun.misc.Launcher$AppClassLoader@33909752, null, loaded=true]

[Byte Buddy] TRANSFORM Foo [sun.misc.Launcher$AppClassLoader@33909752, null, loaded=true]

[Byte Buddy] COMPLETE Foo [sun.misc.Launcher$AppClassLoader@33909752, null, loaded=true]

Foo@7f31245a

Foo@6d6f6e28

Foo@135fbaa4

Foo@45ee12a7

Foo@330bedb4

==================================Update===================================== I defined a public method 'Bar' in Foo like this

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

and then I was trying to make Foo.Bar() returns "modified" in the following way:

    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");
    }

}

but I got this error:

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

any suggestions?

Community
  • 1
  • 1
surlary
  • 1
  • 1
  • `Foo` does not have a `toString()` method. Redefinition does not support adding methods. Only load-time Instrumentation supports adding or removing members. – Holger Dec 01 '17 at 09:57
  • You need to set the return values read only attribute to false. – Rafael Winterhalter Dec 04 '17 at 10:44
  • @Rafael i see, it works now. One more question, is it possible to remove my redefinition? as for some situation I'd like to make the program back to original state... – surlary Dec 05 '17 at 03:53
  • The returned class file transformer offers a reset method. – Rafael Winterhalter Dec 05 '17 at 06:28
  • yes, i noticed ResettableClassFileTransformer.reset method. but it only works in the same agent that registered the transformation, is it possible to reset in the other agent? @Rafael – surlary Dec 05 '17 at 08:51
  • You always need a reference to the class file transformer to unregister it. If you can get hold of this reference, invoking the method is the easiest way. Without the reference, you cannot do what you want. – Rafael Winterhalter Dec 05 '17 at 16:15
  • i see @Rafael, after test i noticed, besides the reference to classfiletransformer, reference to the instrumentation is also required to do reset in future. – surlary Dec 06 '17 at 01:53

1 Answers1

0

It does not seem like you are using redefinition for your agent. You can activate it using:

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

The last part is required on most JVMs (with the notable exception of the dynamic code evolution VM, a custom build of HotSpot). It tells Byte Buddy to not add fields or methods, what most VMs do not support.

In this case, it is no longer possible to invoke the original implementation of a method what is however not required for your FixedValue. Typically, users of Byte Buddy take advantage of Advice when creating an agent that applies dynamic transformations of classes.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
  • thx Rafael and @Holger. Acoording to you guys' comments, I made further attempt, please take a look at my update. – surlary Dec 04 '17 at 09:12