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

使用JVMTI为vmtool工具添加分析占用最大堆内存的类、对象及对象间引用关系的功能 #1915

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

yuankong11
Copy link

@yuankong11 yuankong11 commented Sep 10, 2021

使用JVMTI在运行时经引用关系遍历堆内对象,统计各个类的实例占用的堆内存、各个对象占用的堆内存,从而得到占用内存最大的若干个类和对象。使用JVMTI遍历对象时所建立的引用关系图,可以回溯特定类的占用内存最大的对象的引用关系,帮助定位对象。同时,对与之相关的文档和在线教程进行补充。

运行命令和效果如下:

$ vmtool -a heapAnalyze --classNum 5 --objectNum 3

class_number: 4101
object_number: 107299

id      #bytes          class_name
----------------------------------------------------
1       209715216       byte[]
2       104857616       byte[]
3       524304          char[]

id      #instances      #bytes          class_name
----------------------------------------------------
1       7043            327124360       byte[]
2       20303           5660096         char[]
3       2936            631136          java.lang.Object[]
4       20270           486480          java.lang.String
5       4110            462904          java.lang.Class

$ vmtool -a referenceAnalyze --className ByteHolder --objectNum 2 --backtraceNum -1

id      #bytes          class_name & references
----------------------------------------------------
1       16              ByteHolder <-- root(local variable in method: main)
2       16              ByteHolder <-- root(local variable in method: sleep)

@CLAassistant
Copy link

CLAassistant commented Sep 10, 2021

CLA assistant check
All committers have signed the CLA.

@yuankong11
Copy link
Author

上面输出所使用的测试用例:

class ByteHolder {
    byte[] b;
    ByteHolder(int size) {
        b = new byte[size*1024*1024];
    }
}

public class ByteHolderTest {
    static void sleep() throws Exception {
        ByteHolder bh2 = new ByteHolder(200);
        while (true) {
            Thread.sleep(5000);
        }
    }

    public static void main(String[] args) throws Exception {
        ByteHolder bh1 = new ByteHolder(100);
        sleep();
    }
}

@loongs-zhang
Copy link
Contributor

loongs-zhang commented Sep 11, 2021 via email

@hengyunabc
Copy link
Collaborator

在 build vmtool 这个action里,可以在构建之后,找到so文件的zip包下载。

比如这个: https://github.com/alibaba/arthas/actions/runs/1212293835

image

@yuankong11
Copy link
Author

在 build vmtool 这个action里,可以在构建之后,找到so文件的zip包下载。

比如这个: https://github.com/alibaba/arthas/actions/runs/1212293835

image

@hboutemy 感谢您的帮助,已经使用github action编译得到macos下的版本并提交。

@yuankong11 yuankong11 force-pushed the master branch 5 times, most recently from bc21109 to 65ef77f Compare September 26, 2021 09:27
@daxiondi
Copy link

daxiondi commented Oct 8, 2021

@yuankong11 你好,我使用了你的仓库,进行了构建,在mac上很好,但是在Linux上,出现了问题,这个pr是否完整

[arthas@2737702]$ vmtool -a heapAnalyze --classNum 5 --objectNum 3
The value 'heapAnalyze' is not accepted by 'action'

@loongs-zhang
Copy link
Contributor

loongs-zhang commented Oct 8, 2021 via email

@yuankong11
Copy link
Author

@yuankong11 你好,我使用了你的仓库,进行了构建,在mac上很好,但是在Linux上,出现了问题,这个pr是否完整

[arthas@2737702]$ vmtool -a heapAnalyze --classNum 5 --objectNum 3
The value 'heapAnalyze' is not accepted by 'action'

如果您是使用as-package.sh进行编译后经bin/as.sh启动,那么这个问题可能是因为arthas自动下载了官方的vmtool的lib导致,您可以尝试直接在~/.arthas/lib/3.5.4.*/arthas/中使用java -jar arthas-boot.jar启动arthas,它会引用该目录自行编译下的vmtool lib文件。

@daxiondi
Copy link

daxiondi commented Oct 8, 2021

不是的,x86的。arthas是支持的,vmtool其他命令也支持的。就是他这个pr上的命令不支持,比如

vmtool -a heapAnalyze --classNum 5 --objectNum 3

而在mac上是好的,所以想问下是不是仅支持mac?

@daxiondi
Copy link

daxiondi commented Oct 8, 2021

@yuankong11 你好,我使用了你的仓库,进行了构建,在mac上很好,但是在Linux上,出现了问题,这个pr是否完整

[arthas@2737702]$ vmtool -a heapAnalyze --classNum 5 --objectNum 3
The value 'heapAnalyze' is not accepted by 'action'

如果您是使用as-package.sh进行编译后经bin/as.sh启动,那么这个问题可能是因为arthas自动下载了官方的vmtool的lib导致,您可以尝试直接在~/.arthas/lib/3.5.4.*/arthas/中使用java -jar arthas-boot.jar启动arthas,它会引用该目录自行编译下的vmtool lib文件。

我试过了,还是一样的,mac上是可以的。

@yuankong11
Copy link
Author

不是的,x86的。arthas是支持的,vmtool其他命令也支持的。就是他这个pr上的命令不支持,比如

vmtool -a heapAnalyze --classNum 5 --objectNum 3

而在mac上是好的,所以想问下是不是仅支持mac?

我主要的开发平台是WSL1下的Ubuntu 20,mac平台反而是借助github action编译的。另一方面,github action在linux平台上也会执行test部分,是可以通过的,暂时不清楚什么原因。我到完整的linux平台上试验一下,稍后给您回复。

@yuankong11
Copy link
Author

yuankong11 commented Oct 8, 2021

不是的,x86的。arthas是支持的,vmtool其他命令也支持的。就是他这个pr上的命令不支持,比如

vmtool -a heapAnalyze --classNum 5 --objectNum 3

而在mac上是好的,所以想问下是不是仅支持mac?

我主要的开发平台是WSL1下的Ubuntu 20,mac平台反而是借助github action编译的。另一方面,github action在linux平台上也会执行test部分,是可以通过的,暂时不清楚什么原因。我到完整的linux平台上试验一下,稍后给您回复。

已经在linux服务器的centos8系统上进行测试,是没有问题的。该问题可能是因为加载了错误的JniLibrary。您可以在arthas-vmtool文件夹中执行mvn test,它应该有如下类似输出,这是test中对heapAnalyze的测试。

class_number: 1275
object_number: 16543

id      #bytes          class_name
----------------------------------------------------
1       51312           byte[]
2       36856           byte[]
3       35136           byte[]
4       31960           byte[]
5       26368           byte[]
...

id      #instances      #bytes          class_name
----------------------------------------------------
1       370             734112          byte[]
2       3236            298880          char[]
3       1284            146040          java.lang.Class
4       3228            77472           java.lang.String
5       1279            40928           java.util.concurrent.ConcurrentHashMap$Node
...

@daxiondi
Copy link

daxiondi commented Oct 8, 2021

不是的,x86的。arthas是支持的,vmtool其他命令也支持的。就是他这个pr上的命令不支持,比如

vmtool -a heapAnalyze --classNum 5 --objectNum 3

而在mac上是好的,所以想问下是不是仅支持mac?

我主要的开发平台是WSL1下的Ubuntu 20,mac平台反而是借助github action编译的。另一方面,github action在linux平台上也会执行test部分,是可以通过的,暂时不清楚什么原因。我到完整的linux平台上试验一下,稍后给您回复。

已经在linux服务器的centos8系统上进行测试,是没有问题的。该问题应该是因为加载了错误的JniLibrary。您可以在arthas-vmtool文件夹中执行mvn test,它应该有如下类似输出,这是test中对heapAnalyze的测试。如果没有,可以检查一下仓库地址是否正确。

class_number: 1275
object_number: 16543

id      #bytes          class_name
----------------------------------------------------
1       51312           byte[]
2       36856           byte[]
3       35136           byte[]
4       31960           byte[]
5       26368           byte[]
...

id      #instances      #bytes          class_name
----------------------------------------------------
1       370             734112          byte[]
2       3236            298880          char[]
3       1284            146040          java.lang.Class
4       3228            77472           java.lang.String
5       1279            40928           java.util.concurrent.ConcurrentHashMap$Node
...

我是ubuntu18,mvn test是有如下输出的,只是使用 java -jar arthas-boot.jar 启动arthas,在执行
vmtool -a heapAnalyze --classNum 5 --objectNum 3的时候有问题

@daxiondi
Copy link

daxiondi commented Oct 8, 2021

我把arthas的进程换成了你的示例程序,可以使用命令,但是错误如下

vmtool -a heapAnalyze --classNum 5 --objectNum 3
vmtool error: arthas.VmTool.heapAnalyze0(II)Ljava/lang/String;

vmtool -a referenceAnalyze --className ByteHolder --objectNum 2 --backtraceNum -1
vmtool error: arthas.VmTool.referenceAnalyze0(Ljava/lang/Class;II)Ljava/lang/String;

@daxiondi
Copy link

daxiondi commented Oct 8, 2021

这是否和JDK的版本有关系

openjdk version "1.8.0_272"
OpenJDK Runtime Environment (build 1.8.0_272-8u272-b10-0ubuntu1~18.04-b10)
OpenJDK 64-Bit Server VM (build 25.272-b10, mixed mode)

@yuankong11
Copy link
Author

这是否和JDK的版本有关系

openjdk version "1.8.0_272"
OpenJDK Runtime Environment (build 1.8.0_272-8u272-b10-0ubuntu1~18.04-b10)
OpenJDK 64-Bit Server VM (build 25.272-b10, mixed mode)

我使用open JDK 1.8.0_251并没有复现这一问题,稍后我邮件联系您进一步讨论。

@loongs-zhang
Copy link
Contributor

跟JDK版本没有关系,JDK里的头文件都放到arthas/arthas-vmtool/src/main/native/head里了。@daxiondi @yuankong11

@yuankong11
Copy link
Author

使用智能指针对裸指针进行封装,减少内存管理的负担和内存泄漏的可能性。

@fan0916
Copy link

fan0916 commented Nov 30, 2021

heapAnalyze的功能和jmap histo比较重合;referenceAnalyze只是分析有某个类对象的引用,并不会对引用的数量、占用的字节数进行排序,这个有可能根据引用数量倒排序吗?

@yuankong11
Copy link
Author

heapAnalyze的功能和jmap histo比较重合;referenceAnalyze只是分析有某个类对象的引用,并不会对引用的数量、占用的字节数进行排序,这个有可能根据引用数量倒排序吗?

@fan0916 heapAnalyze跟histo功能比较重合,只是实现方式不同,这里基于JVMTI的方式。referenceAnalyze最初引入的目的是使用heapAnalyze后能够帮助定位到占用大内存的对象的来源,并不会进行排序,但是这部分功能是可以实现的,只需要建立完整的引用关系图,在图上进行统计就行。

@yuankong11
Copy link
Author

heapAnalyze的功能和jmap histo比较重合;referenceAnalyze只是分析有某个类对象的引用,并不会对引用的数量、占用的字节数进行排序,这个有可能根据引用数量倒排序吗?

@fan0916 heapAnalyze跟histo功能比较重合,只是实现方式不同,这里基于JVMTI的方式。referenceAnalyze最初引入的目的是使用heapAnalyze后能够帮助定位到占用大内存的对象的来源,并不会进行排序,但是这部分功能是可以实现的,只需要建立完整的引用关系图,在图上进行统计就行。

使用JVMTI实现histo相对有下面两个好处:1)有高度灵活的可定制性,可以实现如引用关系分析的功能。 2)jmap的histo功能基于迭代堆内对象实现,这里基于引用关系遍历实现,不能由GC root可达的对象事实上不太需要关心。

@yanghaisheng-github
Copy link

$ vmtool -a heapAnalyze --classNum 5 --objectNum 3
The value 'heapAnalyze' is not accepted by 'action'
为啥我的arthas中没有这个命令参数,需要怎么引用,谢谢!

@yuankong11
Copy link
Author

$ vmtool -a heapAnalyze --classNum 5 --objectNum 3 The value 'heapAnalyze' is not accepted by 'action' 为啥我的arthas中没有这个命令参数,需要怎么引用,谢谢!

这个PR还没有合并到主分支,您可以参考这个fork(https://github.com/yuankong11/arthas)编译使用

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.

7 participants