添付するプログラムのコードは以下の通りです。エージェントを実行プロセスに接続すると、バイトバディトランスが有効にならないようです。
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]
を示し、エージェントに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
任意の提案を?
'Foo'には' toString() 'メソッドがありません。再定義はメソッドの追加をサポートしていません。メンバーの追加または削除をサポートするのはロード時計装のみです。 – Holger
戻り値の読み取り専用属性をfalseに設定する必要があります。 –
@Rafael私は、それが今動作することを確認します。もう一つの質問ですが、私の再定義を取り除くことは可能ですか?いくつかの状況については、プログラムを元の状態に戻したいのですが... – surlary