33 | Java Agent与字节码注入
郑雨迪
该思维导图由 AI 生成,仅供参考
关于 Java agent,大家可能都听过大名鼎鼎的premain方法。顾名思义,这个方法指的就是在main方法之前执行的方法。
我在上面这段代码中定义了一个premain方法。这里需要注意的是,Java 虚拟机所能识别的premain方法接收的是字符串类型的参数,而并非类似于main方法的字符串数组。
为了能够以 Java agent 的方式运行该premain方法,我们需要将其打包成 jar 包,并在其中的 MANIFEST.MF 配置文件中,指定所谓的Premain-class。具体的命令如下所示:
除了在命令行中指定 Java agent 之外,我们还可以通过 Attach API 远程加载。具体用法如下面的代码所示:
使用 Attach API 远程加载的 Java agent 不会再先于main方法执行,这取决于另一虚拟机调用 Attach API 的时机。并且,它运行的也不再是premain方法,而是名为agentmain的方法。
相应的,我们需要更新 jar 包中的 manifest 文件,使其包含Agent-Class的配置,例如Agent-Class: org.example.MyAgent。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文介绍了Java Agent与字节码注入的高级技术手段。首先介绍了Java agent的基本概念和使用方法,包括premain方法和Attach API远程加载的方式。然后详细介绍了Java agent的instrumentation机制,通过该机制可以拦截类加载事件并修改类的字节码,实现字节码注入。通过示例代码演示了如何使用ASM框架进行字节码注入,以及如何使用redefine和retransform功能对已加载的类进行修改。文章还提到了Java agent的功能是通过JVMTI agent实现的,通过注册钩子方法来实现对Java虚拟机事件的拦截和处理。另外,还介绍了基于字节码注入的profiler和面向方面编程(AOP)的相关概念。最后,提到了基于字节码注入的profiler所收集到的数据并不能反映程序的真实运行状态,而是程序在被注入的情况下的执行状态。整篇文章内容涵盖了Java agent的基本概念、使用方法和高级功能,对于想要深入了解Java agent和字节码注入的读者来说,是一篇非常有价值的文章。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《深入拆解 Java 虚拟机》,新⼈⾸单¥59
《深入拆解 Java 虚拟机》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(12)
- 最新
- 精选
- 蚂蚁内推+v用attach的方式注入字节码的时候遇到了99线升高的性能问题,看一些资料说 class redefinition 的时候会阻塞线程。请问能详细讲下吗?
作者回复: 你是在做redefine时出问题,还是没触发时便已出问题? class redefinition需要爬每个线程的Java栈,检查有没有用到被redefine的类的方法,因此会stop-the-world。另外,redefine后,JIT’ed代码会被抛弃,重新解释执行
2018-11-1912 - Scott我看到了jvmti可以回调异常事件,但是java.lang.instrument包下没有处理这个事件的,只能在load时回调,处理异常究竟是怎么做的?
作者回复: Instrumentation包并没有所有JVMTI功能
2018-10-064 - Scott出方法时需要注入的字节码除了返回,还有几种情况,如果没有catch块,就拦截throw,如果有,但是catch块里面可能有很多层,只是遍历inst应该是不可以的
作者回复: 其实不用管有没有catch块,有没有throw,直接给所有代码罩一个catch any的异常处理就行了
2018-10-064 - 钱阅过留痕 1:Java agent 是啥玩意? 这个概念老师没有详细讲解,我的理解是Java语言的一个特性,这个特性能够实现Java字节码的注入 2:Java字节码的注入有什么用处呢? 在平时编程几乎没有使用到这方面的功能,应该是在一些框架的设计的时候才使用吧!比如:专栏中提到的面相切面编程。 3:Java agent 本质上是通过 c agent 来实现的,那 c agent 本质上是怎么实现的呢? C agent是一个事件驱动的工具实现接口,通常我们会在 C agent 加载后的入口方案 Agent_OnLoad处注册各个事件的钩子方法。当Java虚拟机触发了这些事件时,便会调用对应的钩子方法 4:留个话头 写代码实现某些功能,我的理解有三个时间段 第一个:源码阶段,最常用的,也是编程的主要活动时间 第二个:字节码阶段,有些功能可能会在加载字节码时修改或者添加某些字节码,某些框架做的事情 第三个:运行阶段,某些工具,在程序运行时修改代码,实现运行时功能分支的控制2018-10-13128
- feng第一个实验做的不严谨,第一,木有定义HelloWord类,第二,没有执行编译操作,不知道是有意为之,还是不小心把步骤漏掉了2018-10-07110
- the geek大概说一下我自己的理解(望老师指正): 1. Agent就是一个调用JVMTI函数的一个程序。 2. JVMTI能够提供的函数能够获得JVM的运行信息,还可以修改JVM的运行态。 3. JVMTI能够修改JVM运行态是因为JVM已经在运行流程中埋下了钩子函数,JVMTI中的函数可以传递具体逻辑给钩子函数。 4. JVMTI函数是C语言实现的JNI方法。 5. 通过Instrumentation我们可以用Java语言调用大部分JVMTI函数。 6. JVM在启动时会加载Agent 入口函数Agent_OnLoad,我们可以在此函数中注册Agent。 7. JVM在运行中可以通过Agent_OnAttach函数来加载Agent,我们可以在此函数中注册Agent。 8. B虚拟机调用attach方法attach到A虚拟机后,可以将Agent程序作为参数调用A虚拟机的Agent_OnAttach函数。 9. premain方法中的程序逻辑会被注册到Agent_OnLoad函数中。 10. agentmain方法中的程序逻辑会被注册到Agent_OnAttach函数中。 11. 在premain或agentmain方法中的拿到的Instrumentation引用,可以理解成拿到了JVMTI的引用(大部分函数)。 以上全是个人抽象理解,不是具体实现。2020-02-126
- 随心而至把老师给的程序都跑了一篇,发现想要彻底搞懂,还需要多学习,C/C++的知识不能丢了,因为HotSpot JVM 的源码基本上都是用它来实现的。 不过跑了一下代码,最起码可以表面上搞懂了像Lombok,AOP这些都是如何实现的。2019-11-013
- 饭粒profiler 示例,文中省略了 HelloWorld.java 和编译提及下更好。 # cat HelloWorld.java public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); HelloWorld w = new HelloWorld(); } } # java -javaagent:myagent.jar -cp $CLASS_PATH:./asm-7.0-beta.jar:./asm-tree-7.0-beta.jar HelloWorld Hello World! HelloWorld: 12019-12-281
- 一缕阳光实习的时候有幸做过一个利用Instrumentation实现自动打点和性能监控的项目。受益匪浅啊 哈哈哈哈 ,不得不说里面坑还是挺多的2019-07-071
- 奇奇ASM7 GETSTATIC这些常量是哪里来的?2019-04-2911
收起评论