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)

其中第一个是jvm启动时调用,第二个是jvm运行时发出attach时调用,第三个是jvm卸载时调用。

其中*jvm参数传入JavaVM指针,可以用来操作JVM;*options参数是命令行传入的参数;*reserved是一个预留参数。

给出运行加载模式实现的一个简单功能:打印jvm内所有已经装载成功的class。具体如下:

/*
*  JVMTI agent
*
*  Created on: 2016-07-02
*      Author: sunjie
*/
#include <jvmti.h>
#include <string>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <set>
#include <stdlib.h>
#include <jni_md.h>

JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options,
                void *reserved) {
        jvmtiEnv *jvmti;
        jint result = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1);
        if (result != JNI_OK) {
                printf("ERROR: Unable to access JVMTI!\n");
        }
        jvmtiError err = (jvmtiError) 0;
        jclass *classes;
        jint count;

        err = jvmti->GetLoadedClasses(&count, &classes);//获取class
        if (err) {
                printf("ERROR: JVMTI GetLoadedClasses failed!\n");
        }
        for (int i = 0; i < count; i++) {
                char *sig;
                jvmti->GetClassSignature(classes[i], &sig, NULL);//获取并打印class签名
                printf("cls sig=%s\n", sig);
        }
        return err;
}

JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm) {
        // nothing to do
}

我们将它命名为agent.cpp,下一步就是将它编译为动态链接库,不同操作系统的命令并不相同,这里以mac系统为例,具体如下:

g++ -I${JAVA_HOME}/include/ -I${JAVA_HOME}/include/darwin Agent.cpp -fPIC -shared -o libagent.so

由于是mac系统,所以引入了${JAVA_HOME}/include/darwin,linux和windows对应的应该是/include/linux、\include\win32。

执行后,我们会看到生成了了libagent.so文件。

2、如何测试agent程序

我们已经有了agent,下面我们测试一下。测试需要有一个目标JVM,所以我们简单模拟一个,具体如下:

public class TestMain {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("JVMTI agent Test start");
        int i = 0;
        while (true) {
            Thread.sleep(1000);
            i++;
        }
    }
}

死循环的目的在于不能让它结束,方便我们使用JVMTI agent进行操作。运行后结果如下:

JVMTI agent Test start

这时我们需要通过AttachAPI为运行中的JVM加载我们的agent,我们首先获取到目标JVM的pid(通过进程监控获取),然后指定agent动态资源库的路径,具体如下:

了解更多 AttachAPI看这里:[AttachAPI是什么][4]

public class TestAgent {
    public static void main(String[] args) throws AttachNotSupportedException, IOException, AgentLoadException,
            AgentInitializationException {
        String pid = "831"; // java进程pid
        String agentPath = "/Users/sunjie/Desktop/libagent.so"; // agent.so的路径
        String options = null;// 传入agent的参数
        VirtualMachine virtualMachine = com.sun.tools.attach.VirtualMachine.attach(pid);
        virtualMachine.loadAgentPath(agentPath, options);
        virtualMachine.detach();
    }
}

这里我们需要引入${JAVA_HOME}/lib/tools.jar包,引入com.sun.tools.attach包。运行后,在目标JVM的Console中出现如下结果:

JVMTI agent Test start

cls sig=Ljava/lang/ClassLoader$NativeLibrary;

cls sig=Ljava/util/concurrent/ConcurrentMap;

cls sig=Ljava/lang/Error;

cls sig=[Ljava/lang/Error;

cls sig=Ljava/util/Set;

cls sig=Ljava/util/WeakHashMap;

cls sig=Ljava/lang/ref/Reference;

cls sig=[Ljava/lang/ref/Reference;

cls sig=Ljava/lang/StackOverflowError;

cls sig=Ljava/io/Serializable;

….

成功打印出了所有已经装载成功的class。

顺便提一句,如果采用启动加载模式,则需要在运行TestMain时加上如下参数:

java -agentlib:Agent=opt1 TestMain

注意,这里传入了*options参数:opt1,不过,我们的agent并没有使用他。

了解更多JVMTI的功能看这里:[JVMTI提供哪些功能][5]

时间: 2024-10-28 20:36:07

Java千百问_08JDK详解(014)_如何编写JVMTI agent程序的相关文章

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详解(015)_JVMTI提供哪些功能

点击进入_更多_Java千百问 1.JVMTI提供哪些功能 了解JVMTI看这里:JVMTI是什么 编写JVMTI程序看这里:如何编写JVMTI agent程序 JVMTI 的功能非常丰富,包含了虚拟机中线程.内存堆/栈.类/方法/变量.事件/定时器处理.代码调试等多种功能,这里我们介绍一些常用的功能. 调试功能 调试功能是JVMTI的基本功能之一,这主要包括了设置断点.调试等,在JVMTI里面,设置断点的API本身很简单: jvmtiError SetBreakpoint(jvmtiEnv*

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

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

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