【问题标题】:Try to use Agent in Webapplication for bytecode Manupulation尝试在 Web 应用程序中使用代理进行字节码操作
【发布时间】:2015-07-23 12:47:55
【问题描述】:

我的 Java 不太好,但我的 webApplication 在 Wildfly 上运行。 我有 3 个线程,他们只调用一个插入日志的函数,该函数将日志保存到数据库中,然后每个线程发送一个时间,执行此操作需要多长时间。 他们将数据发送到我编写的另一个程序,它有 3 个线程来调用 3 个服务器线程之一。

所以现在我尝试对服务器上的每个线程进行一些字节码操作,保存日期时间调用,日志函数等待 1 秒,然后返回他们需要的时间。

1 线程在等待 1 秒之前或之后在日志文件中写入内容。 但是这部分他们等待一秒钟并调用日志函数,我希望它通过字节码操作注入每 3 个线程。

public class MyTransformer implements ClassFileTransformer {


@Override
public byte[] transform(ClassLoader loader, String className, Class redefiningClass, ProtectionDomain protectionDomain, byte[] bytes) throws IllegalClassFormatException {

    return transformClass(redefiningClass, bytes);
}

private byte[] transformClass(Class classToTransform, byte[] b) {
    ClassPool pool = ClassPool.getDefault();
    CtClass cl = null;
    try {
        cl = pool.get("de.soptim.ws.MyApplication");
    } catch (javassist.NotFoundException e) {
        e.printStackTrace();
    }
    try {

        assert cl != null;
        CtMethod[] methods = cl.getMethods();
        for (int i = 0; i < methods.length; i++) {
            if (methods[i].isEmpty() == false) {
                changeMethod(methods[i]);
            }
        }
        b = cl.toBytecode();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (cl != null) {
            cl.detach();
        }
    }
    return b;
}

private void changeMethod(CtMethod method) throws NotFoundException, CannotCompileException {

    if (method.hasAnnotation(Loggable.class)) {
        method.insertBefore("threadLogger.info(\"ADDED THIS FROM BYTECODE !!!\");");
        method.insertAfter("threadLogger.info(\"ADDED THIS FROM BYTECODE !!!\");");
    }
}}

那是我的转换器类,它应该增加我的方法需要的代码它检查哪个方法具有@Loggable 注释,然后将代码添加到其中(“目前它只是一些用于检查它是否有效的日志语句”)

我现在最大的问题是我不知道如何调用我的代理...我用 Google 搜索了 hwo 以在运行时使用 agentmain() 调用代理,但我想我并没有真正理解它是如何工作的。

代理类

public class LogAgent  {

public static void agentmain(String agentArgs, Instrumentation inst) {
    System.out.println("Starting the agent");
    inst.addTransformer(new MyTransformer());
}}

希望你能理解我的问题 :) 如果你回答我,请尽量保持对菜鸟友好 :D。

【问题讨论】:

    标签: java web-applications javassist bytecode-manipulation javaagents


    【解决方案1】:

    你没有显式调用你的代理,你应该为你的 JVM 指定额外的参数:

    java -javaagent:jarpath[=options]

    jarpath 是包含您的代理的 jar 的路径。 JVM会在java程序的main方法之前调用premain方法。

    并且transform方法将在JVM加载类之前被调用(你没有显式调用它)。

    最后一句话:你应该实现premain方法,而不是agentmainagentmain 用于附加到正在运行的 vm,而premain 用于通过-javaagent 方法启动 JVM。

    并确保您的 jar 具有有效的清单,如所述:https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/package-summary.html

    我没有使用 javaassit,所以我不能说你的代码是有效的,但是像 Wildfly 这样检测 webapp 服务器比普通的 java 应用程序要困难得多(主要是由于类加载器的可见性和层次结构)。

    另见:

    http://www.tomsquest.com/blog/2014/01/intro-java-agent-and-bytecode-manipulation/ Tutorials about javaagents

    【讨论】:

    • 首先感谢您的回答:D 但是“java -javaagent:jarpath[=options]”我只知道这是 CMD 的命令,我不能使用这个 o: 或者我可以添加它其他地方?
    • 我使用了 premain,因为我试图在它运行时更改代码,但也没有用...
    • 修改服务器启动脚本和这个到 JVM 参数。我就是这样做的,效果很好。
    猜你喜欢
    • 1970-01-01
    • 2019-07-22
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-30
    • 1970-01-01
    相关资源
    最近更新 更多