我有一个代理,我正在动态加载到一个正在运行的java应用程序中,当它被连接时,这个应用程序会打开一个简单的swing jframe。它还允许在jframe内的textarea中添加新行。
我的目标是更改代理加载到的应用程序中某些方法的工作方式。
public class MyAgent {
public static void agentmain(String args, Instrumentation instrumentation) {
UI.openWindow();
UI.addMessage("Agent loaded: %s", args);
instrumentation.addTransformer(new MyTransformer());
instrumentation.redefineClasses(new ClassDefinition(Class.forName("app.TargetClass"), ...));
}
}
ui窗口在可从代理访问的另一个类中管理。它成功地打开一个窗口,并在加载代理时附加一条文本消息。
public class UI {
private static SwingWindow swingWindow;
public static void addMessage(String format, Object... args) {
System.out.println("UI: " + String.format(format, args));
swingWindow.appendToTextArea(format, args);
}
public static void openWindow() {
try {
SwingUtilities.invokeAndWait(() -> swingWindow = new SwingWindow());
}
catch (Exception e) {}
}
}
我使用javassist在我的转换器中生成字节码。
public class MyTransformer implements ClassFileTransformer {
@Override
public byte[] transform(ClassLoader loader, String className, ..., byte[] classBuffer) {
if (className.equals("app/TargetClass")) {
UI.addMessage("Now transforming the class that I need!");
try {
ClassPool classPool = ClassPool.getDefault();
CtClass targetClass = classPool.get("app.TargetClass");
CtMethod targetMethod = targetClass.getDeclaredMethod("importantMethod");
targetMethod.insertBefore("me.domain.agent.ui.UI.addMessage(\"Hello from Javassist!\")");
byte[] byteCode = targetClass.toBytecode();
targetClass.detach();
return byteCode;
}
catch (Exception e) {
UI.addMessage("Couldn't transform the class I needed.");
}
}
return classBuffer;
}
}
找到目标类,但字节码不编译:
ui:转换类app.targetclass失败:[源错误]没有此类类:me$domain.agent.ui.ui
但是,ui类位于代理内部:
agent.jar
├── META-INF
└── me.domain.agent
├── ui
│ └── UI.class
├── MyTransformer.class
└── Agent.class
我尝试将代理的类加载器添加到javassist的类池:
classPool.insertClassPath(new LoaderClassPath(Agent.class.getClassLoader()));
但它不起作用。如何将对代理ui的调用添加到字节码中?
1条答案
按热度按时间68de4m5k1#
我决定用asm从字节码调用我的代理ui。找班级没有问题。
以下是基于asm的类转换器的外观:
这将插入静态调用
UI.addMessage("Hello from ASM!")
第一次无标签指示前app.TargetClass#importantMethod
.