Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

提供JvmUtils #1698

Closed
wants to merge 18 commits into from
Closed

提供JvmUtils #1698

wants to merge 18 commits into from

Conversation

loongs-zhang
Copy link
Contributor

@loongs-zhang loongs-zhang commented Feb 12, 2021

JvmUtils能够在不dump的前提下,获取:

  • 1.某个class在jvm中当前所有存活实例;
  • 2.某个class在jvm中当前所有存活实例的总占用内存;
  • 3.某个实例的占用内存;
  • 4.某个class在jvm中当前所有存活实例的总个数;
  • 5.所有已加载的类(不包括void、int、boolean、float等小类型).

具体使用可参考测试用例com.vdian.vclub.JvmUtilsTest;

@CLAassistant
Copy link

CLAassistant commented Feb 12, 2021

CLA assistant check
All committers have signed the CLA.

@loongs-zhang
Copy link
Contributor Author

loongs-zhang commented Feb 12, 2021

懂c++的大佬可以再优化下jni-library.cpp的实现,使得java层能够支持并发调用。

@loongs-zhang
Copy link
Contributor Author

loongs-zhang commented Feb 23, 2021

在我的macos上使用mvn clean compile package -DskipTests=true打包之后,添加以下依赖:

<profiles>
    <!-- macos -->
    <profile>
        <id>macos</id>
        <activation>
            <os>
                <family>mac</family>
            </os>
        </activation>
        <properties>
            <os_family>macos</os_family>
        </properties>
    </profile>

    <!-- linux -->
    <profile>
        <id>linux</id>
        <activation>
            <os>
                <name>linux</name>
            </os>
        </activation>
        <properties>
            <os_family>linux</os_family>
        </properties>
    </profile>

    <!-- windows -->
    <profile>
        <id>windows</id>
        <activation>
            <os>
                <family>windows</family>
            </os>
        </activation>
        <properties>
            <os_family>windows</os_family>
        </properties>
    </profile>
</profiles>

<dependencies>
    <dependency>
        <groupId>com.taobao.arthas</groupId>
        <artifactId>arthas-beans</artifactId>
        <version>3.4.7-SNAPSHOT</version>
        <classifier>${os_family}-${os.arch}</classifier>
    </dependency>
</dependencies>

JvmUtils可以正常使用,可以把代码 拉下来,并在com.example.JvmUtilsTest查看运行结果。

@loongs-zhang
Copy link
Contributor Author

loongs-zhang commented Feb 25, 2021

之前构建不通过是因为后面构建的机器上的JDK,是OpenJDK,OpenJDK没有include文件夹,改成使用本地的头文件,就没问题了。另外,由于使用的是本地的头文件,所以目前仅仅支持linux、mac和windows(三种)的64位的操作系统,后续再支持32位操作系统。

@hengyunabc
Copy link
Collaborator

API返回的对象是 LinkedList ,感觉这个直接用 ArrayList更合理?并且创建 ArrayList 时可以指定 size。

@hengyunabc
Copy link
Collaborator

native-lib-loader 这个能否去掉?看了下它的代码,主要是判断不同的os,然后从ClassLoader找到对应的动态库文件,再解压到临时目录,再调用 java.lang.System.load(String) 加载。

或者可以把arthas里已有的 ProfilerCommand里加载的流程抽取出来,共用一份逻辑。

@loongs-zhang
Copy link
Contributor Author

loongs-zhang commented Apr 22, 2021

API返回的对象是 LinkedList ,感觉这个直接用 ArrayList更合理?并且创建 ArrayList 时可以指定 size。

最开始想的是,获取系统中的所有Object对象,但实际不会有这种场景,因此Integer.MAX_VALUE - 8(数组的最大长度)想必是够用的,我将尽快修改。

@loongs-zhang
Copy link
Contributor Author

native-lib-loader 这个能否去掉?看了下它的代码,主要是判断不同的os,然后从ClassLoader找到对应的动态库文件,再解压到临时目录,再调用 java.lang.System.load(String) 加载。

或者可以把arthas里已有的 ProfilerCommand里加载的流程抽取出来,共用一份逻辑。

使用java.lang.System.load(String),web环境下无法直接定位到so文件,因为so文件在arthas-beans-xxxx.jar里。如果去掉native-lib-loader的话,需要把so文件提取出来,再调用java.lang.System.load(String),我想引入arthas中已有的org.zeroturnaround.zt-zip.1.14来把文件提取出来,或者直接使用文件流来提取?您建议怎么做?

@hengyunabc
Copy link
Collaborator

native-lib-loader 这个能否去掉?看了下它的代码,主要是判断不同的os,然后从ClassLoader找到对应的动态库文件,再解压到临时目录,再调用 java.lang.System.load(String) 加载。
或者可以把arthas里已有的 ProfilerCommand里加载的流程抽取出来,共用一份逻辑。

使用java.lang.System.load(String),web环境下无法直接定位到so文件,因为so文件在arthas-beans-xxxx.jar里。如果去掉native-lib-loader的话,需要把so文件提取出来,再调用java.lang.System.load(String),我想引入arthas中已有的org.zeroturnaround.zt-zip.1.14来把文件提取出来,或者直接使用文件流来提取?您建议怎么做?

计划用 github ci构建好不同环境的so,然后下载放到目录下。和现在的代码里的async-profiler/目录一样。

https://github.com/hengyunabc/test/blob/master/.github/workflows/test.yml#L18

@loongs-zhang
Copy link
Contributor Author

native-lib-loader 这个能否去掉?看了下它的代码,主要是判断不同的os,然后从ClassLoader找到对应的动态库文件,再解压到临时目录,再调用 java.lang.System.load(String) 加载。
或者可以把arthas里已有的 ProfilerCommand里加载的流程抽取出来,共用一份逻辑。

使用java.lang.System.load(String),web环境下无法直接定位到so文件,因为so文件在arthas-beans-xxxx.jar里。如果去掉native-lib-loader的话,需要把so文件提取出来,再调用java.lang.System.load(String),我想引入arthas中已有的org.zeroturnaround.zt-zip.1.14来把文件提取出来,或者直接使用文件流来提取?您建议怎么做?

计划用 github ci构建好不同环境的so,然后下载放到目录下。和现在的代码里的async-profiler/目录一样。

https://github.com/hengyunabc/test/blob/master/.github/workflows/test.yml#L18

放到目录里的话,so文件会被打到arthas-beans-xxxx.jar吗?换句话说,arthas-beans-xxxx.jar还能单独使用吗?

@loongs-zhang
Copy link
Contributor Author

loongs-zhang commented Apr 22, 2021

native-lib-loader 这个能否去掉?看了下它的代码,主要是判断不同的os,然后从ClassLoader找到对应的动态库文件,再解压到临时目录,再调用 java.lang.System.load(String) 加载。
或者可以把arthas里已有的 ProfilerCommand里加载的流程抽取出来,共用一份逻辑。

使用java.lang.System.load(String),web环境下无法直接定位到so文件,因为so文件在arthas-beans-xxxx.jar里。如果去掉native-lib-loader的话,需要把so文件提取出来,再调用java.lang.System.load(String),我想引入arthas中已有的org.zeroturnaround.zt-zip.1.14来把文件提取出来,或者直接使用文件流来提取?您建议怎么做?

计划用 github ci构建好不同环境的so,然后下载放到目录下。和现在的代码里的async-profiler/目录一样。
https://github.com/hengyunabc/test/blob/master/.github/workflows/test.yml#L18

放到目录里的话,so文件会被打到arthas-beans-xxxx.jar吗?换句话说,arthas-beans-xxxx.jar还能单独使用吗?
额,说错,我去学习下ci/cd的配置,之前没有接触过ci/cd。

@kylixs
Copy link
Contributor

kylixs commented Apr 27, 2021

建议写一个测试用例,反复调用10w+次,检查是否存在JNI内存泄漏(Native Memory)。

Copy link
Contributor

@kylixs kylixs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#Deallocate

Deallocate
jvmtiError
Deallocate(jvmtiEnv* env,
unsigned char* mem)
Deallocate mem using the JVM TI allocator. This function should be used to deallocate any memory allocated and returned by a JVM TI function (including memory allocated with Allocate). All allocated memory must be deallocated or the memory cannot be reclaimed.

要检查每个方法的参数说明,根据需要调用Deallocate释放内存。


jint count = 0;
jobject *instances;
error = jvmti->GetObjectsWithTags(1, &tag, &count, &instances, NULL);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jobject *instances; 可能存在内存泄漏问题


jint count = 0;
jobject *instances;
error = jvmti->GetObjectsWithTags(1, &tag, &count, &instances, NULL);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jobject *instances; 可能存在内存泄漏问题

jclass *classes;
jint count = 0;

jvmtiError error = jvmti->GetLoadedClasses(&count, &classes);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jclass *classes; 这个数组是JVM申请的内存空间,好像需要使用完之后主动释放吧?

https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#GetLoadedClasses

Name Type Description
class_count_ptr jint* On return, points to the number of classes.Agent passes a pointer to a jint. On return, the jint has been set.
classes_ptr jclass** On return, points to an array of references, one for each class.Agent passes a pointer to a jclass*. On return, the jclass* points to a newly allocated array of size *class_count_ptr. The array should be freed with Deallocate. The objects returned by classes_ptr are JNI local references and must be managed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

收到,感谢您的宝贵建议,我将尽快处理。

hengyunabc pushed a commit to hengyunabc/arthas that referenced this pull request Apr 27, 2021
@hengyunabc
Copy link
Collaborator

代码在这个commit里合并了: hengyunabc@59f4d10

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants