JPDA 架构研究2 - JVMTI代理
2014-12-08 15:06
218 查看
引入:
我们先从JVMTI讲起。JVMTI的主要作用是提供一组接口来检测VM的状态和控制VM中运行的JAVA程序。JVMTI是个双向接口:
JVMTI的客户端叫Agent,它会在VM发生变化时通过事件机制被通知到变化。
JVMTI的服务端是许多函数,它们会和VM实际打交道并把结果告知Agent.
实践:
我们这里先来看下Agent.
Agent的方法定义在哪里呢?它们定义在$JAVA_HOME/include/jvmti.h文件中。
Agent_OnLoad方法:
当代理被VM加载时,会由VM调用Agent_Onload方法。此时VM有如下能力:
(1)VM的System Property已经被设置完毕。
(2)VM的Capabilities已经被设置完毕。
(3)任何字节码都没被执行。
(4)任何类都没有被加载。
(5)任何对象都没有被创建。
Agent_OnLoad实现过程中,最重要的事情之一就是调用GetEnv方法来获取JVMTI环境的指针。
Agent_OnUnload方法:
当代理被VM卸载时,会由VM调用Agent_OnUnload方法。一般发生在终止VM的时候,它一般可以用来清理在Agent_OnLoad阶段创建的资源。
因为我们在远程调试时候启动JVM时候加了代理参数:
java -agentlib:<agentLibName> ,而agentLibName我们配置的是jdwp, 所以它就对应上jdwp.dll.
也就是远程调试时候自动会在启动target VM时候启用jdwp这个代理库.
当明白了代理的作用后,我们来找其的实现。在Sun的JDK中,我们找到了jdwp.dll (Linux环境则是jdwp.so) . 它位于 $JAVA_HOME/jre/bin目录下。我们用exeScope软件打开查看内容:
显然,它是Oracle的Sun的JDK提供的Agent ,它提供了2个方法,一个是_Agent_OnLoad(),一个是_Agent_OnUnload()
和我们设想的一致。
总结:
从上过程我们似乎可以总结一些结论:
1. Agent 是在虚拟机启动之时加载的,这个加载处于虚拟机初始化的早期.在这个时间点上:
所有的 Java 类都未被初始化;所有的对象实例都未被创建; 因而,没有任何 Java 代码被执行;
(从这点上说,最明显的好处就是它能完成早期调试中用System.out.println()无法解决的问题,因为System.out.println()前提是代码行所在的类已经被初始化过了)
2.但在这个时候,我们已经可以:
操作 JVMTI 的 Capability 参数; 使用系统参数; 动态库被加载之后,虚拟机会先寻找一个 Agent 入口函数.
我们先从JVMTI讲起。JVMTI的主要作用是提供一组接口来检测VM的状态和控制VM中运行的JAVA程序。JVMTI是个双向接口:
JVMTI的客户端叫Agent,它会在VM发生变化时通过事件机制被通知到变化。
JVMTI的服务端是许多函数,它们会和VM实际打交道并把结果告知Agent.
实践:
我们这里先来看下Agent.
Agent的方法定义在哪里呢?它们定义在$JAVA_HOME/include/jvmti.h文件中。
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved); JNIEXPORT void JNICAL。 Agent_OnUnload(JavaVM *vm);
Agent_OnLoad方法:
当代理被VM加载时,会由VM调用Agent_Onload方法。此时VM有如下能力:
(1)VM的System Property已经被设置完毕。
(2)VM的Capabilities已经被设置完毕。
(3)任何字节码都没被执行。
(4)任何类都没有被加载。
(5)任何对象都没有被创建。
Agent_OnLoad实现过程中,最重要的事情之一就是调用GetEnv方法来获取JVMTI环境的指针。
jint GetEnv(JavaVM *vm, void **env, jint version);这样,这个代理就可以知道被代理的环境的全部信息。
Agent_OnUnload方法:
当代理被VM卸载时,会由VM调用Agent_OnUnload方法。一般发生在终止VM的时候,它一般可以用来清理在Agent_OnLoad阶段创建的资源。
因为我们在远程调试时候启动JVM时候加了代理参数:
java -agentlib:<agentLibName> ,而agentLibName我们配置的是jdwp, 所以它就对应上jdwp.dll.
也就是远程调试时候自动会在启动target VM时候启用jdwp这个代理库.
当明白了代理的作用后,我们来找其的实现。在Sun的JDK中,我们找到了jdwp.dll (Linux环境则是jdwp.so) . 它位于 $JAVA_HOME/jre/bin目录下。我们用exeScope软件打开查看内容:
显然,它是Oracle的Sun的JDK提供的Agent ,它提供了2个方法,一个是_Agent_OnLoad(),一个是_Agent_OnUnload()
和我们设想的一致。
总结:
从上过程我们似乎可以总结一些结论:
1. Agent 是在虚拟机启动之时加载的,这个加载处于虚拟机初始化的早期.在这个时间点上:
所有的 Java 类都未被初始化;所有的对象实例都未被创建; 因而,没有任何 Java 代码被执行;
(从这点上说,最明显的好处就是它能完成早期调试中用System.out.println()无法解决的问题,因为System.out.println()前提是代码行所在的类已经被初始化过了)
2.但在这个时候,我们已经可以:
操作 JVMTI 的 Capability 参数; 使用系统参数; 动态库被加载之后,虚拟机会先寻找一个 Agent 入口函数.
相关文章推荐
- JPDA 架构研究16 - Agent利用环境指针访问VM(方法访问篇)
- JPDA 架构研究10 - Agent利用环境指针访问VM(局部变量管理篇)
- JPDA 架构研究11 - Agent利用环境指针访问VM(断点操作篇)
- JPDA 架构研究17 - JDI概览
- JPDA 架构研究22 - 总结
- JPDA 架构研究5 - Agent利用环境指针访问VM (内存管理篇)
- JPDA 架构研究18 - JDI的Mirror机制
- JPDA 架构研究6 - Agent利用环境指针访问VM (线程管理篇)
- JPDA 架构研究12 - Agent利用环境指针访问VM(观察字段篇)
- JPDA 架构研究1- 整体架构
- JPDA 架构研究7 - Agent利用环境指针访问VM(线程组管理篇)
- JPDA 架构研究8 - Agent利用环境指针访问VM(堆栈管理篇)
- JPDA 架构研究9 - Agent利用环境指针访问VM (堆管理篇)
- JPDA 架构研究13 - Agent利用环境指针访问VM(类管理篇)
- JPDA 架构研究19 - JDI的连接模块
- JPDA 架构研究14 - Agent利用环境指针访问VM(对象管理篇)
- 系统架构技能之设计模式“.NET研究”—代理模式
- JPDA 架构研究3 - JDWP层的数据包
- JPDA 架构研究20 - JDI的事件请求和处理模块 推荐
- JPDA 架构研究4 - JDWP的传输器