我有以下 Javassist 代码来修改日志记录方法,使其仅记录某些情况(以尝试检测黑客在游戏中转移大笔资金,以供引用):
CtClass ctClass = ClassPool.getDefault().getCtClass(Trade.class.getName());
CtMethod commandMethod = ctClass.getDeclaredMethod("log");
commandMethod.setBody("if (/* conditions */) {"
+ " fw.write(sender + \" [\" + senderUser.getMoney() + \"/\" + senderOldBal + \"] sent \" + pay.getMoney() + \" to \" + receiver + \"[\" + receiverOldBal + \"/\" + receiverUser.getMoney() + \"]\");"
+ "}");
据我了解,只需调用 ctClass.toClass()
不会替换当前加载的类,为了实现这一点,我需要使用 Java 中的 Instrumentation API。然而,我还没有找到太多关于如何使用 Instrumentation API 的解释。
任何有关如何执行此操作的建议将不胜感激。
最佳答案
示例 javaagent 项目:java-agent-asm-javassist-sample (在谷歌中找到,不是我的代码)。
为了从 Instrumentation API 中受益,您需要构建自己的 javaagent:
public class Agent {
public static void premain(String agentArgs, Instrumentation inst) {
inst.addTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader classLoader, String s, Class<?> aClass, ProtectionDomain protectionDomain, byte[] bytes) throws IllegalClassFormatException {
if ("your/package/Trade".equals(s)) {
try {
ClassPool cp = ClassPool.getDefault();
CtClass ctClass = cp.get("your.package.Trade");
CtMethod commandMethod = ctClass.getDeclaredMethod("log");
commandMethod.setBody("if (/* conditions */) {"
+ " fw.write(sender + \" [\" + senderUser.getMoney() + \"/\" + senderOldBal + \"] sent \" + pay.getMoney() + \" to \" + receiver + \"[\" + receiverOldBal + \"/\" + receiverUser.getMoney() + \"]\");"
+ "}");
byte[] byteCode = ctClass.toBytecode();
ctClass.detach();
return byteCode;
} catch (Exception ex) {
ex.printStackTrace();
}
}
return null;
}
});
}
}
编译并打包到agent.jar中, list 中包含“Premain-Class”。
通过 JVM 参数传递 javagent:java -javaagent:some/path/agent.jar -jar your-main-app.jar
关于java - 使用 Javassist 修改后检测加载的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58026958/