Home > Life > JvmTI hello world

JvmTI hello world

JvmTI (Jvm Tools Interface) 作为一个强大的jvm工具接口,提供很多很强大有用的功能。最近尝试下使用,简单记录下。

中文参考的是Ken Wu的博客,太具体的细节我就不累述了,这里直接解释我的hello world的过程吧。

首先需要准备一个jvm实例用于测试,为什么不选择已经在运行的象eclipse之类的大家伙,稍候介绍,我现在准备一个很简单的程序吧

public class TestMain {
    public static void main(String[] args) {
        System.out.println("Start to Sleep");
        try {
            Thread.sleep(1000 * 60 * 60);
        } catch (InterruptedException e) {
            //Do nothing
        }
    }
}

启动它

java TestMain

接下来需要写一个最简单的jvmti的agent:

#include
#include 

JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM *vm,
        char *options, void *reserved) {
	printf("On attach\n");
	return (jvmtiError) 0;
}

JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm) {
	printf("Unload");
}

编译成共享库

JAVA_HOME=/opt/j2sdk
gcc main.c -o agent.so -I $JAVA_HOME/headers -I $JAVA_HOME/include/linux --shared -fPIC -Wall

最后就是试下这个agent能不能用了,写一个java类来测试吧:

public class JvmHelloWorld {
    public static void main(String[] args) throws Exception {
        String pid = "1497";
        String agentPath = "/data/tmp/agent.so";
        VirtualMachine vm = VirtualMachine.attach(pid);
        vm.loadAgentPath(agentPath);
        vm.detach();
        System.out.println("done");
    }
}

这里写死了agent的地址和pid是为了尽可能的简单,pid就是刚才我们启动的jvm实例的进程号,可以通过jps命令帮助查找到;agentPath就是刚才编译好的库文件.
直接从eclipse里执行就可以了,看看结果吧。
测试程序JvmHelloWorld很快就返回了(如果没有报错的话),但是只输出了“done”,没有输出“On attach”。
切换到刚才启动TestMain的窗口,会发现在那里输出了“On attach”,也就是说其实agent是被作为参数传给另一个jvm,然后在已经运行的jvm(我们想获得信息的那个)里执行,这也就解释了为什么“On attach”不在JvmHelloWorld中输出了。
另外,一个jvm在重启前,对于相同的一个agent库文件(注意,这里以文件为标识)只会读取一次文件信息,但是可以多次执行,每次使用attach命令就会执行一次,但是如果我们重新编译了库文件,不会立即起效果,最好的方案是生成一个新的库文件,重新attach一次。

之前提到为什么要单独写一个TestMain而不直接查看eclipse的原因是,eclipse执行agent的输出很难看到,对于hello world来说太麻烦了。

  • No Related Post
Categories: Life Tags:
  1. No comments yet.
  1. No trackbacks yet.