JPDA 架构研究2 - JVMTI代理

引入:java

咱们先从JVMTI讲起。JVMTI的主要做用是提供一组接口来检测VM的状态和控制VM中运行的JAVA程序。JVMTI是个双向接口:jvm

JVMTI的客户端叫Agent,它会在VM发生变化时经过事件机制被通知到变化。ide

JVMTI的服务端是许多函数,它们会和VM实际打交道并把结果告知Agent.
函数


实践:spa

咱们这里先来看下Agent.
3d


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软件打开查看内容:

wKiom1SFSz7xFsInAAJpNug-rho655.jpg

显然,它是Oracle的Sun的JDK提供的Agent ,它提供了2个方法,一个是_Agent_OnLoad(),一个是_Agent_OnUnload()

wKiom1SFS37Ty0DhAAEzsbfIxTM606.jpg

和咱们设想的一致。





总结:

从上过程咱们彷佛能够总结一些结论:

1. Agent 是在虚拟机启动之时加载的,这个加载处于虚拟机初始化的早期.在这个时间点上:

  全部的 Java 类都未被初始化;全部的对象实例都未被建立; 于是,没有任何 Java 代码被执行; 

(从这点上说,最明显的好处就是它能完成早期调试中用System.out.println()没法解决的问题,由于System.out.println()前提是代码行所在的类已经被初始化过了)

2.但在这个时候,咱们已经能够:

操做 JVMTI 的 Capability 参数; 使用系统参数; 动态库被加载以后,虚拟机会先寻找一个 Agent 入口函数.

相关文章
相关标签/搜索