查看Java Agent修改的Java类的源代码

2024-05-14

我需要了解 Java 代理如何修改我的初始类,以便我能够理解代码的作用。

build.gradle

configurations {
    jar.archiveName = 'agent2.jar'
}

jar {
    manifest {
        attributes(
                "Premain-Class": "com.training.agentexample.Agent",
                "Can-Redefine-Classes": false,
                "Can-Set-Native-Method-Prefix": false
        )
    }

    //Fat jar with all dependencies.
    from {
        (configurations.runtime).collect {
            it.isDirectory() ? it : zipTree(it)
        }
    }
}

dependencies {
    compile group: 'org.javassist', name: 'javassist', version: '3.22.0-GA'
}

Main.java

public class Main {

    public static void main(String[] args) {
        System.currentTimeMillis();
        App app = new App();
        app.execute("John");
        Scanner in = new Scanner(System.in);
        System.out.println("Enter text to exit");
        in.next();   //Wait until the user clicks to proceed.
    }
}

App.java

public class App {

    public void execute(String param) {
        String message = "Hello World";
        System.out.println(message + " " + param);
    }
}

Agent.java

public class Agent {

    public static void premain(final String agentArgs, final Instrumentation inst) {
        System.out.println("Hey, look: I'm instrumenting a freshly started JVM!");
        inst.addTransformer(new RuntimeTimerTransformer());
    }
}

RuntimeTimerTransformer.java

public class RuntimeTimerTransformer implements ClassFileTransformer {

    public byte[] transform(ClassLoader loader, String className, Class redefiningClass, ProtectionDomain domain, byte[] bytes) {
        return transformClass(redefiningClass, bytes);
    }

    private byte[] transformClass(Class classToTransform, byte[] b) {
        ClassPool pool = ClassPool.getDefault();
        CtClass cl = null;
        try {
            cl = pool.makeClass(new java.io.ByteArrayInputStream(b));
            CtBehavior[] methods = cl.getDeclaredBehaviors();
            for (CtBehavior method : methods) {
                if (!method.isEmpty()) {
                    changeMethod(method);
                }
            }
            b = cl.toBytecode();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cl != null) {
                cl.detach();
            }
        }
        return b;
    }

    private void changeMethod(CtBehavior method) throws CannotCompileException {
        String name = method.getName();
        if (name.equals("execute")) {
            addElapsedTime(method);
        }
    }

    private void addElapsedTime(CtBehavior method) throws CannotCompileException {
        method.addLocalVariable("$_start", CtClass.longType);
        method.addLocalVariable("$_end", CtClass.longType);
        method.addLocalVariable("$_total", CtClass.longType);
        method.insertBefore("{ $_start = System.nanoTime();\nSystem.out.println($0);\n$1 = \"Robert\"; }");
        method.insertAfter("{ $_end = System.nanoTime();\n$_total = $_end - $_start;\nSystem.out.println($_total);\nthrow new RuntimeException(\"Break!\"); }");
    }
}

我从 Intellij Idea 调试它。我设置JAVA_TOOL_OPTIONS=-javaagent:"C:\Development\agent-example\build-gradle\libs\agent2.jar"=name=agentExample

Output

Hey, look: I'm instrumenting a freshly started JVM!
Connected to the target VM, address: '127.0.0.1:64486', transport: 'socket'
Exception in thread "main" java.lang.RuntimeException: Break!
    at app.App.execute(App.java:10)
    at app.app.Main.main(Main.java:12)
app.app.App@3e6fa38a
Hello World !Robert
736583
Picked up JAVA_TOOL_OPTIONS: -javaagent:"C:\Development\agent-example\java-assist-agent\build\libs\agent2.jar"=name=agentExample
Disconnected from the target VM, address: '127.0.0.1:64486', transport: 'socket'

Process finished with exit code 1

我可以设置断点。我的问题。如何查看正在执行的真实源代码?顺便说一句,您可以使用此代码作为示例来开始使用 Java Agent。


这不是我一直在寻找的答案,但这就是我能得到的答案。 我仍然需要更好的解决方案,特别是如果我无法访问代理代码怎么办。欢迎您的想法!

1)修改transform method.

private byte[] transformClass(Class classToTransform, byte[] b) {
    ClassPool pool = ClassPool.getDefault();
    CtClass cl = null;
    try {
        cl = pool.makeClass(new java.io.ByteArrayInputStream(b));
        CtBehavior[] methods = cl.getDeclaredBehaviors();
        for (CtBehavior method : methods) {
            if (!method.isEmpty()) {
                changeMethod(method);
            }
        }
        b = cl.toBytecode();

        OutputStream os = new FileOutputStream(CLASS_OUTPUT_DIR + cl.getName() + CLASS_EXTENSION);
        BufferedOutputStream bos = new BufferedOutputStream(os);
        bos.write(b);
        bos.close();

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (cl != null) {
            cl.detach();
        }
    }
    return b;
}

Update

See update bellow. I used Intellij Idea to open bytecode classes.

2)然后打开字节码。我用了jd-gui-1.4.0.jar。这就是我得到的。

已编译App.class

public class App
{
  /* Error */
  public void execute(String param)
  {
    // Byte code:
    //   0: invokestatic 55 java/lang/System:nanoTime   ()J
    //   3: lstore 4
    //   5: getstatic 4 java/lang/System:out    Ljava/io/PrintStream;
    //   8: aload_0
    //   9: invokevirtual 58    java/io/PrintStream:println (Ljava/lang/Object;)V
    //   12: ldc 60
    //   14: astore_1
    //   15: ldc 2
    //   17: astore_2
    //   18: ldc 3
    //   20: astore_3
    //   21: getstatic 4    java/lang/System:out    Ljava/io/PrintStream;
    //   24: aload_2
    //   25: invokevirtual 5    java/io/PrintStream:println (Ljava/lang/String;)V
    //   28: getstatic 4    java/lang/System:out    Ljava/io/PrintStream;
    //   31: new 6  java/lang/StringBuilder
    //   34: dup
    //   35: invokespecial 7    java/lang/StringBuilder:<init>  ()V
    //   38: aload_2
    //   39: invokevirtual 8    java/lang/StringBuilder:append  (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   42: aload_3
    //   43: invokevirtual 8    java/lang/StringBuilder:append  (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   46: aload_1
    //   47: invokevirtual 8    java/lang/StringBuilder:append  (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   50: invokevirtual 9    java/lang/StringBuilder:toString    ()Ljava/lang/String;
    //   53: invokevirtual 5    java/io/PrintStream:println (Ljava/lang/String;)V
    //   56: goto +3 -> 59
    //   59: aconst_null
    //   60: astore 11
    //   62: invokestatic 55    java/lang/System:nanoTime   ()J
    //   65: lstore 6
    //   67: lload 6
    //   69: lload 4
    //   71: lsub
    //   72: lstore 8
    //   74: getstatic 4    java/lang/System:out    Ljava/io/PrintStream;
    //   77: lload 8
    //   79: invokevirtual 63   java/io/PrintStream:println (J)V
    //   82: new 65 java/lang/RuntimeException
    //   85: dup
    //   86: ldc 67
    //   88: invokespecial 69   java/lang/RuntimeException:<init>   (Ljava/lang/String;)V
    //   91: athrow
    //   92: athrow
    // Line number table:
    //   Java source line #6    -> byte code offset #15
    //   Java source line #7    -> byte code offset #18
    //   Java source line #8    -> byte code offset #21
    //   Java source line #9    -> byte code offset #28
    //   Java source line #10   -> byte code offset #56
    // Local variable table:
    //   start  length  slot    name    signature
    //   0  59  0   this    App
    //   0  59  1   param   String
    //   18 41  2   message String
    //   21 38  3   appender    String
    //   0  59  4   $_start long
    //   0  59  6   $_end   long
    //   0  59  8   $_total long
  }
}

And in Idea enter image description here

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

查看Java Agent修改的Java类的源代码 的相关文章

  • 如何将jscrollpane添加到jframe?

    我有以下源代码 有人可以给我建议如何将 jscrollpane 添加到 jframe 上吗 我尝试了几次将其添加到 jframe 但没有任何进展 它甚至没有显示 public class Form3 JFrame jframe new JF
  • 将SQL数据引入jquery availabletag

    我正在尝试制作自动完成文本框 但如何将 SQL 数据包含到 jquery 可用标记并循环它 我无法根据以下代码执行该功能 任何帮助 将不胜感激 谢谢 这是我的预期输出 预期结果演示 http jsfiddle net VvETA 71 jq
  • 删除优先级队列的尾部元素

    如何删除优先级队列的尾部元素 我正在尝试使用优先级队列实现波束搜索 一旦优先级队列已满 我想删除最后一个元素 优先级最低的元素 Thanks 没有简单的方法 将元素从原始元素复制到新元素 最后一个除外 PriorityQueue remov
  • Logback:SizeAndTimeBasedRollingPolicy 不遵守totalSizeCap

    我正在尝试以一种方式管理我的日志记录 一旦达到总累积大小限制或达到最大历史记录限制 我最旧的存档日志文件就会被删除 当使用SizeAndTimeBasedRollingPolicy在 Logback 1 1 7 中 滚动文件追加器将继续创建
  • 您建议使用哪种压缩(GZIP 是最流行的)servlet 过滤器?

    我正在寻找一个用于大容量网络应用程序的 GZIP servlet 过滤器 我不想使用容器特定的选项 要求 能够压缩响应负载 XML Faster 已在大批量应用的生产中得到验证 应适当设置适当内容编码 跨容器移植 可选择解压缩请求 谢谢 我
  • tomcat 7.0.50 java websocket 实现给出 404 错误

    我正在尝试使用 Java Websocket API 1 0 JSR 356 中指定的带注释端点在 tomcat 7 0 50 上实现 websocket 以下是我如何对其进行编码的简要步骤 1 使用 ServerEndpoint注解编写w
  • 为自定义驱动程序创建 GraphicsDevice

    我正在开发一个在嵌入式系统中使用 Java 的项目 我有用于屏幕和触摸输入的驱动程序 以及用于文本输入的虚拟键盘 我的屏幕驱动程序有一个Graphics2D您可以绘制的对象和repaint Rectangle 更新方法 类似地 触摸驱动器能
  • Spring数据中的本机查询连接

    我有课 Entity public class User Id Long id String name ManyToMany List
  • 为什么Iterator接口没有add方法

    In IteratorSun 添加了remove 方法来删 除集合中最后访问的元素 为什么没有add方法来向集合中添加新元素 它可能对集合或迭代器产生什么样的副作用 好的 我们开始吧 设计常见问题解答中明确给出了答案 为什么不提供 Iter
  • 如何通过注解用try-catch包装方法?

    如果应该在方法调用中忽略异常 则可以编写以下内容 public void addEntryIfPresent String key Dto dto try Map
  • 当 minifyEnabled 为 true 时 Android 应用程序崩溃

    我正在使用多模块应用程序 并且该应用程序崩溃时minifyEnabled true in the installed模块的build gradle 以下是从游戏控制台检索到的反混淆堆栈跟踪 FATAL EXCEPTION Controlle
  • 在 Java 中通过 XSLT 分解 XML

    我需要转换具有嵌套 分层 表单结构的大型 XML 文件
  • 寻找局部最小值

    下面的代码正确地找到了数组的局部最大值 但未能找到局部最小值 我已经进行了网络搜索 以找到找到最小值的最佳方法 并且根据这些搜索 我认为我正在使用下面的正确方法 但是 在几天的时间里多次检查每一行之后 下面的代码中有一些我仍然没有看到的错误
  • 无需登录即可直接从 Alfresco 访问文件/内容

    我的场景是这样的 我有一个使用 ALFRESCO CMS 来显示文件或图像的 Web 应用程序 我正在做的是在 Java servlet 中使用用户名和密码登录 alfresco 并且我可以获得该登录的票证 但我无法使用该票证直接从浏览器访
  • 如何让 Emma 或 Cobertura 与 Maven 一起报告其他模块中源代码的覆盖率?

    我有一个带有 Java 代码的多模块 Maven 设置 我的单元测试在其中一个模块中测试多个模块中的代码 当然 这些模块具有相互依赖性 并且在测试执行之前根据需要编译所有相关模块中的代码 那么 如何获得整个代码库覆盖率的报告 注意 我不是问
  • Hadoop NoSuchMethodError apache.commons.cli

    我在用着hadoop 2 7 2我用 IntelliJ 做了一个 MapReduce 工作 在我的工作中 我正在使用apache commons cli 1 3 1我把库放在罐子里 当我在 Hadoop 集群上使用 MapReduceJob
  • 使用 Java https 上传到 Imgur v3 错误

    我目前正在尝试使用他们当前的 API v3 上传到 imgur 但是我不断收到错误 错误 javax net ssl SSLException 证书中的主机名不匹配 api imgur com imgur com OR imgur com
  • 将对象从手机共享到 Android Wear

    我创建了一个应用程序 在此应用程序中 您拥有包含 2 个字符串 姓名和年龄 和一个位图 头像 的对象 所有内容都保存到 sqlite 数据库中 现在我希望可以在我的智能手表上访问这些对象 所以我想实现的是你可以去启动 启动应用程序并向左和向
  • 如何使用通配符模拟泛型方法的行为

    我正在使用 EasyMock 3 2 我想基于 Spring Security 为我的部分安全系统编写一个测试 我想嘲笑Authentication http docs spring io autorepo docs spring secu
  • 是否可以在Java中检查CPU是否是超线程的?

    我想知道可以运行的最佳线程数 通常 这等于Runtime getRuntime availableProcessors 但是 在支持超线程的 CPU 上 返回的数字是其两倍 现在 对于某些任务来说 超线程是好的 但对于其他任务来说 它没有任

随机推荐