使用 Javassist 修改后检测加载 类

Instrumenting loaded classes after modification with Javassist

我有以下 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() 不会替换当前加载的 class,为了实现这一点,我需要使用 [=] 中的 Instrumentation API 19=]。但是,我没能找到太多关于如何使用 Instrumentation 的解释 API。

任何有关如何执行此操作的建议将不胜感激。

示例 javaagent 项目:java-agent-asm-javassist-sample(在 google 中找到,不是我的代码)。

为了从 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,清单中 'Premain-Class'。

通过 JVM 参数传递您的 javagent:java -javaagent:some/path/agent.jar -jar your-main-app.jar