Java千百问_08JDK详解(015)_JVMTI提供哪些功能

点击进入_更多_Java千百问

1、JVMTI提供哪些功能

了解JVMTI看这里:JVMTI是什么

编写JVMTI程序看这里:如何编写JVMTI agent程序

JVMTI 的功能非常丰富,包含了虚拟机中线程、内存堆/栈、类/方法/变量、事件/定时器处理、代码调试等多种功能,这里我们介绍一些常用的功能。

调试功能

调试功能是JVMTI的基本功能之一,这主要包括了设置断点、调试等,在JVMTI里面,设置断点的API本身很简单:

jvmtiError SetBreakpoint(jvmtiEnv* env, jmethodID method, jlocation location)

jlocation这个数据结构在这里代表的是对应方法方法中一个可执行代码的行数。在断点发生的时候,虚拟机会触发一个事件,我们可以使用在上文中介绍过的方式对事件进行处理。

事件处理和回调函数

使用JVMTI一个基本的方式就是设置回调函数,在某些事件发生的时候触发并作出相应的动作。

因此这一部分的功能非常基本,回调事件包括虚拟机初始化/开始运行/结束、类的加载、方法出入、线程始末等等。如果想对某些事件进行处理,我们首为该事件写一个函数,然后在jvmtiEventCallbacks这个结构中指定相应的函数指针。

比如,我们对线程启动感兴趣,并写了一个HandleThreadStart函数,那么我们需要在Agent_OnLoad函数里加入:

jvmtiEventCallbacks eventCallBacks;
memset(&ecbs, 0, sizeof(ecbs)); // 初始化
eventCallBacks.ThreadStart = &HandleThreadStart; // 设置函数指针
jvmti->SetEventCallbacks(eventCallBacks, sizeof(eventCallBacks));

在虚拟机运行过程中,一旦有线程开始,虚拟机就会回调HandleThreadStart方法。

设置回调函数的时候,需要注意:虚拟机不保证回调函数同步,比如,好几个线程同时开始运行了,这个HandleThreadStart就会被同时调用几次.

内存控制和对象获取

内存控制是一切运行态的基本功能。 JVMTI除了提供最简单的内存申请和撤销之外(这块内存不受 Java 堆管理,需要自行进行清理工作,不然会造成内存泄漏),也提供了对Java堆的操作。众所周知,Java堆中存储了Java的对象,通过对堆的操作,可以很容易的查找任意的对象,还可以强行执行垃圾收集工作。

JVMTI中没有提供一个直接获取的方式,而是使用一个迭代器(iterater)的方式遍历,由此可见,虚拟机对对象的管理并非是哈希表,而是某种树/图方式:

jvmtiError FollowReferences(jvmtiEnv* env,
    jint heap_filter,
    jclass klass,
    jobject initial_object,// 该方式可以指定根节点
    const jvmtiHeapCallbacks* callbacks,// 设置回调函数
    const void* user_data)

或者

jvmtiError IterateThroughHeap(jvmtiEnv* env,
    jint heap_filter,
    jclass klass,
    const jvmtiHeapCallbacks* callbacks,
    const void* user_data)// 遍历整个 heap

在遍历的过程中,我们可以设定一定的条件,例如指定某一个类的对象,并设置一个回调函数,如果条件被满足,回调函数就会被执行。还可以在回调函数中对当前传回的指针进行打标记(tag)操作,在遍历中,只能对满足条件的对象进行tag,然后再使用GetObjectsWithTags函数获取需要的对象。如下:

jvmtiError GetObjectsWithTags(jvmtiEnv* env,
    jint tag_count,
    const jlong* tags, // 设定特定的 tag,即我们上面所设置的
    jint* count_ptr,
    jobject** object_result_ptr,
    jlong** tag_result_ptr)

如果你仅仅想对特定Java对象操作,应该避免设置其他类型的回调函数,否则会影响效率。多增加一个primitive的回调函数,可能会使整个操作效率下降一个数量级。

线程和锁

在JVMTI中也提供了很多API进行线程的操作,包括查询当前线程状态、暂停、恢复或者终端线程,还可以对线程锁进行操作。我们可以获得特定线程所拥有的锁:

jvmtiError GetOwnedMonitorInfo(jvmtiEnv* env,
    jthread thread,
    jint* owned_monitor_count_ptr,
    jobject** owned_monitors_ptr)

也可以获得当前线程正在等待的锁:

jvmtiError GetCurrentContendedMonitor(jvmtiEnv* env,
    jthread thread,
    jobject* monitor_ptr)

我们可以通过以上接口设计自己的算法来判断是否死锁。

JVMTI还提供了一系列的监视器(Monitor)操作,来帮助我们在native环境中实现同步,主要的操作是构建监视器(CreateRawMonitor),获取监视器(RawMonitorEnter),释放监视器(RawMonitorExit),等待和唤醒监视器 (RawMonitorWait,RawMonitorNotify) 等操作,通过这些简单锁,程序的同步操作可以得到保证。

时间: 2024-10-20 02:43:57

Java千百问_08JDK详解(015)_JVMTI提供哪些功能的相关文章

Java千百问_08JDK详解(017)_Javadoc是什么

点击进入_更多_Java千百问 1.Javadoc是什么 javadoc是Sun公司提供的一个技术,它从程序源代码中抽取类.方法.成员等注释,形成一个和源代码配套的API帮助文档.也就是说,只要在编写程序时以一套特定的标签作注释,在程序编写完成后,通过Javadoc就可以形成开发文档了. 了解注释看这里:注释是什么 2.如何使用Javadoc java为javadoc技术独立出了一个工具,它位于JAVA_HOME/bin/路径中,在终端中执行如下命令: javadoc 文件名.java java

Java千百问_08JDK详解(016)_AttachAPI是什么

点击进入_更多_Java千百问 1.AttachAPI是什么 Attach API是Sun公司提供的一套扩展API,它并不是Java的标准API.顾名思义,Attach,为JVM附加某些程序.简单来说,就是把一个程序连接到一个正在运行的JVM上,连接之后,这段程序就可以在JVM中运行.这段程序被称为JVMTI Agent程序. 我们使用它可以很方便地在运行过程中动态地设置加载代理类(JVMTI Agent),使我们能方便的监控一个JVM,运行一个外加的代理程序. 了解JVMTI Agent看这里

Java千百问_08JDK详解(013)_JVMTI是什么

点击进入_更多_Java千百问 1.JVMTI是什么 JVMTI(JVM Tool Interface)是JPDA体系中的最底层, 由Java虚拟机提供的native编程接口,是JVMPI(Java Virtual Machine Profiler Interface)和 JVMDI(Java Virtual Machine Debug Interface)的更新版本. 了解JPDA体系看这里:JPDA是什么 从它的发展中我们就可以知道,JVMTI提供了调试(debug)和分析(profiler

Java千百问_08JDK详解(011)_jnlp文件是什么

点击进入_更多_Java千百问 1.jnlp文件是什么 JNLP(Java Network Launching Protocol ,java网络执行协议文件)是java提供的一种可以通过浏览器直接执行java应用程序的途径,它使你可以直接通过一个网页上的url链接打开一个java应用程序. Java桌面应用程序可以通过JNLP的方式发布.如果版本升级后,不需要再向所有用户发布版本,只需要更新服务器的版本,这就相当于让java应用程序有了web应用的优点.如果你使用JNLP打包一个应用程序,那么它

Java千百问_08JDK详解(010)_java、javaw、javaws有什么区别

点击进入_更多_Java千百问 1.java.javaw.javaws有什么区别 java.javaw.javaws这三个都是jdk自带的三个工具,都在jdk/bin路径下,这三个工具都是为了启动java应用存在的,具体区别如下: java java命令即java应用的执行器,通过它执行的应用日志会再控制台console显示输出与错误信息. 了解更多java命令看这里:java程序如何运行 javaw javaw与java一样,是java应用的执行器,不同的是它不会再控制台console显示输出

Java千百问_08JDK详解(003)_java核心框架是什么样的

点击进入_更多_Java千百问 1.jdk基础扩展类库都有什么 了解java核心框架看这里:java核心框架是什么样的 jdk基础类库分为两大部分,基础库.扩展基础库,提供了相当大量的功能,扩展基础库具体如下: I/O工具(I/O) java.io和java.nio包提供了一组非常丰富的api来管理应用程序的I/O(输入/输出).包括文件和设备I/O.对象序列化.缓冲区管理.字符集支持等.此外,API还为服务端提供了包括多路复用.非阻塞I/O.内存映射和文件锁等功能. 了解更多java.io和j

Java千百问_08JDK详解(018)_JConsole是什么

点击进入_更多_Java千百问 1.JConsole是什么 JConsole是一个Java程序性能分析器,可以从命令行或在终端中运行.可以用来监控Java程序的性能以及跟踪代码. 同时在com.sun.tools.jconsole包中提供了一组接口,允许访问JConsole,对线程.内存.类.对象进行分析和统计. 2.如何使用JConsole工具 我们这里主要介绍jconsole工具的用法,在JAVA_HOME/bin路径中,我们可以直接打开他.如下图: 我们可以对正在运行的本地进程或者远程进程

Java千百问_08JDK详解(019)_jdk工具包有哪些工具

点击进入_更多_Java千百问 jdk工具包有哪些工具 JDK工具包中提供了很多工具和实用的程序.涵盖了基本工具( javac, java, javadoc, apt, appletviewer, jar, jdb, javah, javap, extcheck),安全工具,国际化工具,RMI工具,IDL, RMI-IIOP工具,部署工具,java插件工具,java Web工具,监控管理工具,故障排查工具等. 这里我们只进行以下简单说明,不一一介绍,具体参见oracle官方文档:http://d

Java千百问_08JDK详解(012)_JPDA是什么

点击进入_更多_Java千百问 1.JPDA是什么 我们可以通过常见的Java IDE提供的图形界面调试工具进行代码调试,甚至可以使用JDK自带的jdb工具,以文本命令的形式来调试Java 程序,这些形形色色的调试工具都是通过JPDA开发的. JPDA(Java Platform Debugger Architecture)是 Java平台调试体系结构的缩写,通过JPDA提供的API,开发人员可以方便灵活的搭建Java调试工具. JPDA主要由三个部分组成:Java虚拟机工具接口(JVMTI,J