美文网首页JVM
JVMTI基本介绍

JVMTI基本介绍

作者: Alen_ab56 | 来源:发表于2021-11-28 22:25 被阅读0次

    在研究JVM-Sandbox时接触到了JVMTI这个底层工具,整理下

    1. JVMTI是什么
      说到JVMTI,必须说一下JPDA,因为JVMTI是JPDA中的一环
      JPDA叫做Java 平台调试架构(Java Platform Debugger Architecture)
      JVMTI(JVM tool interface)位于jpda最底层


      JPDA.png

      这三个规范把调试过程分解成几个概念:调试者(debugger)、被调试者(debuggee)、以及它们中间的通信器

    2. JVMTI能干什么
      JVMTI(Java Virtual Machine Tool Interface)即指 Java 虚拟机工具接口,它是一套由虚拟机直接提供的 native 接口,它处于整个 JPDA 体系的最底层,所有调试功能本质上都需要通过 JVMTI 来提供。
      通过这些接口,开发人员不仅调试在该虚拟机上运行的 Java 程序,还能查看它们运行的状态,设置回调函数,控制某些环境变量,从而优化程序性能。
      JVMTI 本质上是在 JVM 内部的许多事件进行了埋点。通过这些埋点可以给外部提供当前上下文的一些信息。甚至可以接受外部的命令来改变下一步的动作。
      外部程序一般利用C/C++实现一个JVMTIAgent,在Agent里面注册一些JVM事件的回调。当事件发生时JVMTI调用这些回调方法。Agent可以在回调方法里面实现自己的逻辑。JVMTIAgent是以动态链接库的形式被虚拟机加载的。

    3. JVMTI的历史
      JVMTI 的前身是 JVMDI(Java Virtual Machine Profiler Interface) 和 JVMPI(Java Virtual Machine Debug Interface),它们原来分别被用于提供调试 Java 程序以及 Java 程序调节性能的功能。
      在 J2SE 5.0 之后 JDK 取代了JVMDI 和 JVMPI 这两套接口,JVMDI 在最新的 Java SE 6 中已经不提供支持,而 JVMPI 也计划在 Java SE 7 后被彻底取代。

    1. JVMTI的功能
      JVMTI 处于整个 JPDA 体系的最底层,所有调试功能本质上都需要通过 JVMTI 来提供。

    从大的方面来说,JVMTI 提供了可用于 debug 和 profiler 的接口;同时,在 Java 5/6 中,虚拟机接口也增加了监听(Monitoring),线程分析(Thread analysis)以及覆盖率分析(Coverage Analysis)等功能。

    从小的方面来说包含了虚拟机中线程、内存、堆、栈、类、方法、变量,事件、定时器处理等等诸多功能。具体可以参考 oracle 的文档

    通过这些接口,开发人员不仅可以调试在该虚拟机上运行的 Java 程序,还能查看它们运行的状态,设置回调函数,控制某些环境变量,从而优化程序性能

    1. 如何使用
      那么,开发者是如何来使用JVMTI所提供的接口呢?事实上,一般采用建立一个 Agent 的方式来使用 JVMTI,这个Agent的表现形式是一个以c/c++语言编写的动态链接库。

    把 Agent 编译成一个动态链接库,Java启动或运行时,动态加载一个外部基于JVMTI 编写的dynamic module到Java进程内,然后触发 JVM源生线程Attach Listener来执行这个dynamic module的回调函数 。
    在回调函数体内,可以 获取各种各样的VM级信息,注册感兴趣的VM事件,甚至控制VM行为。

    1. 细节分析
      6.1 Agent 工作过程
      6.2 . 启动
      JVMTI有两种启动方式,第一种是随Java进程启动时,自动载入共享库,下文简称 启动时载入。另一种方式是,Java运行时,通过attach api动态载入,下文简称 运行时载入。

    java -agentlib:= Sample
    注意,这里的共享库路径是环境变量路径,例如 java -agentlib:foo=opt1,opt2,java启动时会从linux的LD_LIBRARY_PATH或windows的PATH环境变量定义的路径处装载foo.so或foo.dll,找不到则抛异常
    java -agentpath:= Sample
    这是 以绝对路径的方式装载共享库,例如 java -agentpath:/home/admin/agentlib/foo.so=opt1,opt2
    比如一些第三方jar包如alibaba ttl threadlocal

    运行时载入,通过attach api,这是一套纯Java的API,它负责动态地将dynamic module attach到指定进程id的Java进程内并触发回调。例子如下:
    import java.io.IOException;
    import com.sun.tools.attach.VirtualMachine;

    public class VMAttacher {
    public static void main(String[] args) throws Exception {
    // args[0]为java进程id
    VirtualMachine virtualMachine = com.sun.tools.attach.VirtualMachine.attach(args[0]);
    // args[1]为共享库路径,args[2]为传递给agent的参数
    virtualMachine.loadAgentPath(args[1], args[2]);
    virtualMachine.detach();
    }
    }

    运行时载入,虚拟机会在运行时监听并接受 Agent 的加载,在这个时候,它会使用 Agent 的:
    JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM* vm, char *options, void *reserved);

    参考:
    https://docs.oracle.com/javase/1.5.0/docs/guide/jvmti/jvmti.html#whatIs
    https://www.jianshu.com/p/8775c1542b52
    https://docs.oracle.com/javase/8/docs/technotes/guides/jpda/

    相关文章

      网友评论

        本文标题:JVMTI基本介绍

        本文链接:https://www.haomeiwen.com/subject/kznhxrtx.html