jvmti agent的加载与回调函数的执行分析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jvmti agent的加载与回调函数的执行分析相关的知识,希望对你有一定的参考价值。

参考技术A        JVM agent 的加载流程基本都一致,最近在学习java debug ,本文就结合jvmti impl的实现 jdwp agent 分析一下agent 的加载与回调函数的执行流程。

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

      在这个函数中,虚拟机传入了一个 JavaVM 指针,以及命令行的参数。通过 JavaVM,我们可以获得 JVMTI 的指针,并获得 JVMTI 函数的使用能力,所有的 JVMTI 函数都通过这个 jvmtiEnv 获取,不同的虚拟机实现提供的函数细节可能不一样,但是使用的方式是统一的。

      这里传入的版本信息参数很重要,不同的 JVMTI 环境所提供的功能以及处理方式都可能有所不同,不过它在同一个虚拟机中会保持不变。命令行参数事实上就是上面启动命令行中的 options 部分,在 Agent 实现中需要进行解析并完成后续处理工作。参数传入的字符串仅仅在 Agent_OnLoad 函数里有效。
      需要强调的是,这个时候由于虚拟机并未完成初始化工作,并不是所有的 JVMTI 函数都可以被使用。
       Agent 还可以在运行时加载。具体说来,虚拟机会在运行时监听并接受 Agent 的加载,在这个时候,它会使用 Agent 的:

      同样的在这个初始化阶段,不是所有的 JVMTI 的 Capability 参数都处于可操作状态,而且 options 这个 char 数组在这个函数运行之后就会被丢弃,如果需要,需要做好保留工作。
      Agent 的主要功能是通过一系列的在虚拟机上设置的回调(callback)函数完成的,一旦某些事件发生,Agent 所设置的回调函数就会被调用,来完成特定的需求。

      最后,Agent 完成任务,或者虚拟机关闭的时候,虚拟机都会调用一个类似于类析构函数的方法来完成最后的清理任务,注意这个函数和虚拟机自己的 VM_DEATH 事件是不同的。

LoadJavaVM -> JNI_CreateJavaVM -> Threads::create_vm

2、create_vm_init_agents() 函数主要功能是找到dll, 然后找到dll中的Agent_Onload方法,然后调用这个方法进行agent初始化

核心函数是lookup_agent_on_load。 (定义在hotspot/src/share/vm/runtime/thread.cpp)

里面的核心函数是 lookup_on_load 。主要是找到dll,然后找到里面的agent onload 方法。 定义如下:

Agent_OnLoad是一个外部的c函数,看一下。(定义位置: jdk7u/jdk/src/share/instrument/InvocationAdapter.c)

在方法Agent_OnLoad中创建一个新的 JPLISAgent(Java Programming Language Instrumentation Services Agent),初始化了类和包里的配置文件,并且同时从Vm环境中获取了 jvmtiEnv 的环境。

看一下核心 createNewJPLISAgent :

再看一下初始化JPLISAgent的函数 initializeJPLISAgent

VMInit的初始化函数 eventHandlerVMInit : (定义位置: jdk7u/jdk/src/share/instrument/InvocationAdapter.c)。callback support 分了两个阶段(主要在processJavaStart中做了):
(1)在OnLoad时, 安装VMInit handler
(2)当VMInit handler 跑起来时,移除VMInit handler 安装一个ClassFileLoadHook handler(里面有我们定义的具体执行的回调函数).

processJavaStart 里面执行了注册event的处理钩子。

setLivePhaseEventHandlers :

startJavaAgent

1、 JVMTI 和 Agent 实现

Java千百问_08JDK详解(014)_如何编写JVMTI agent程序

点击进入_更多_Java千百问

1、如何编写JVMTI agent程序

了解JPDA看这里:JPDA是什么
了解JVMTI看这里:JVMTI是什么
我们需要使用C++编写agent程序,JVM在不同时机回调下面的接口函数:

JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved)

JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved);

JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *jvm)

以上是关于jvmti agent的加载与回调函数的执行分析的主要内容,如果未能解决你的问题,请参考以下文章

JRebel-JVMTI [ERROR] You’re using an incompatible ‘jrebel.jar’ with the JRebel Agent.完美解决方案

JRebel-JVMTI [ERROR] You’re using an incompatible ‘jrebel.jar’ with the JRebel Agent.完美解决方案

android源码分析之JNI调用与回调

回调函数执行过程分析

加载loading的ajax写法

bootstrap tooltip放在table里无效