深入Java调试体系,第2部分: JVMTI和Agent实现 - 编程入门网
I,它使用 JVMTI 函数,设置一些回调函数,并从 Java 虚拟机中得到当前的运行态信息,并作出自己的判断,最后还可能操作虚拟机的运行态。把 Agent 编译成一个动态链接库之后,我们就可以在 Java 程序启动的时候来加载它(启动加载模式),也可以在 Java 5 之后使用运行时加载(活动加载模式)。
-agentlib:agent-lib-name=options -agentpath:path-to-agent=options Agent 的工作过程 启动 Agent 是在 Java 虚拟机启动之时加载的,这个加载处于虚拟机初始化的早期,在这个时间点上: 所有的 Java 类都未被初始化; 所有的对象实例都未被创建; 因而,没有任何 Java 代码被执行; 但在这个时候,我们已经可以: 操作 JVMTI 的 Capability 参数; 深入Java调试体系,第2部分: JVMTI和Agent实现(2)时间:2011-02-14 IBM 吕晶 邱小侠使用系统参数; 动态库被加载之后,虚拟机会先寻找一个 Agent 入口函数:
在这个函数中,虚拟机传入了一个 JavaVM 指针,以及命令行的参数。通过 JavaVM,我们可以获得 JVMTI 的指针,并获得 JVMTI 函数的使用能力,所有的 JVMTI 函数都通过这个 jvmtiEnv 获取,不同的虚拟机实现提供的函数细节可能不一样,但是使用的方式是统一的。
这里传入的版本信息参数很重要,不同的 JVMTI 环境所提供的功能以及处理方式都可能有所不同,不过它在同一个虚拟机中会保持不变(有心的读者可以去比较一下 JNI 环境)。命令行参数事实上就是上面启动命令行中的 options 部分,在 Agent 实现中需要进行解析并完成后续处理工作。参数传入的字符串仅仅在 Agent_OnLoad 函数里有效,如果需要长期使用,开发者需要做内存的复制工作,同时在最后还要释放这块存储。另外,有些 JDK 的实现会使用 JAVA_TOOL_OPTIONS 所提供的参数,这个常见于一些嵌入式的 Java 虚拟机(不使用命令行)。需要强调的是,这个时候由于虚拟机并未完成初始化工作,并不是所有的 JVMTI 函数都可以被使用。 Agent 还可以在运行时加载,如果您了解 Java Instrument 模块(可以参考这篇文章),您一定对它的运行态加载有印象,这个新功能事实上也是 Java Agent 的一个实现。具体说来,虚拟机会在运行时监听并接受 Agent 的加载,在这个时候,它会使用 Agent 的:
同样的在这个初始化阶段,不是所有的 JVMTI 的 Capability 参数都处于可操作状态,而且 options 这个 char 数组在这个函数运行之后就会被丢弃,如果需要,需要做好保留工作。 Agent 的主要功能是通过一系列的在虚拟机上设置的回调(callback)函数完成的,一旦某些事件发生,Agent 所设置的回调函数就会被调用,来完成特定的需求。 卸载 最后,Agent 完成任务,或者虚拟机关闭的时候,虚拟机都会调用一个类似于类析构函数的方法来完成最后的清理任务,注意这个函数和虚拟机自己的 VM_DEATH 事件是不同的。
JVMTI 的环境和错误处理 我们使用 JVMTI 的过程,主要是设置 JVMTI 环境,监听虚拟机所产生的事件,以及在某些事件上加上我们所希望的回调函数。 JVMTI 环境 我们可以通过操作 jvmtiCapabilities 来查询、增加、修改 JVMTI 的环境参数。当然,对于每一个不同的虚拟机来说,基于他们的实现不尽相同,导致了 JVMTI 的环境也不一定一致。标准的 jvmtiCapabilities 定义了一系列虚拟机的功能,比如 can_redefine_any_class 定义了虚拟机是否 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |