当前位置: 首页 > 知识库问答 >
问题:

JVM进程如何分配其内存?

董元徽
2023-03-14

我在理解JVM进程如何分配自己的内存方面有一点差距。据我所知

RSS = Heap size + MetaSpace + OffHeap size

其中堆外由线程堆栈、直接缓冲区、映射文件(库和JAR)和JVM代码本身组成;

目前,我正在尝试分析我的Java应用程序(Spring Boot Infinispan),RSS779M(它在docker容器中运行,所以pid 1是可以的):

[ root@daf5a5ae9bb7:/data ]$ ps -o rss,vsz,sz 1
RSS    VSZ    SZ
798324 6242160 1560540

换句话说,我想解释799M-(374M 89M)=316M堆外内存。

这些线程中的每一个都消耗1M:

[ root@fac6d0dfbbb4:/data ]$ java -XX:+PrintFlagsFinal -vershtml" target="_blank">ion |grep ThreadStackSize    
intx CompilerThreadStackSize                   = 0
intx ThreadStackSize                           = 1024
intx VMThreadStackSize                         = 1024

所以,这里我们可以增加3600万。

最后一步是映射libs和jar。但是根据pmap(完整输出)

[ root@daf5a5ae9bb7:/data ]$ pmap -x 1 | grep ".so.*" | awk '{ sum+=$3} END {print sum}'

12896K

root@daf5a5ae9bb7:/data ]$ pmap -x 1 | grep “.jar" | awk '{ sum+=$3} END {print sum}'

9720K

我们这里只有2000米。

因此,我们仍然需要解释316M-(36M 20M)=260M:(

有人知道我错过了什么吗?

共有1个答案

姜乐语
2023-03-14

方法:

您可能希望使用JavaHotSpot本机内存跟踪(NMT)。

这可能会为您提供JVM分配的内存的确切列表,分为不同的区域堆、类、线程、代码GC、编译器、内部、符号、内存跟踪、池化空闲块和未知。

用法:

>

可以使用jcmd观察当前堆

在哪里可以找到jcmd/pid:

在Ubuntu上的默认OpedJDK安装中,可以在usr/bin/jcmd上找到。

只需在没有任何参数的情况下运行jcmd,就可以得到一个正在运行的Java应用程序列表。

user@pc:~$ /usr/bin/jcmd
5169 Main                       <-- 5169 is the pid

输出:

然后,您将收到堆的完整概述,如下所示:

总计:保留=664192KB,已提交=253120KB

>

  • Java堆(保留=516096KB,提交=204800KB)

    (mmap:保留=516096KB,提交=204800KB)

    类(保留=6568KB,已提交=4140KB)

    (课程#665)

    (malloc=424KB,#1000)

    (mmap:保留=6144KB,提交=3716KB)

    线程(保留=6868KB,提交=6868KB)(线程#15)

    (堆栈:保留=6780KB,提交=6780KB)

    (malloc=27KB,#66)

    (竞技场=61KB,#30)

    代码(保留=102414KB,已提交=6314KB)

    (malloc=2574KB,#74316)

    (mmap:保留=99840KB,提交=3740KB)

    GC(保留=26154KB,提交=24938KB)

    (malloc=486KB,#110)

    (mmap:保留=25668KB,提交=24452KB)

    编译器(保留=106KB,提交=106KB)

    (malloc=7KB,#90)

    (竞技场=99KB,#3)

    内部(保留=586KB,已提交=554KB)

    (malloc=554KB,#1677)

    (mmap:保留=32KB,提交=0KB)

    符号(保留=906KB,已提交=906KB)

    (malloc=514KB,#2736)

    (竞技场=392KB,#1)

    内存跟踪(保留=3184KB,已提交=3184KB)

    (malloc=3184KB,#300)

    池化空闲块(保留=1276KB,提交=1276KB)

    (malloc=1276KB)

    未知(保留=33KB,提交=33KB)

    (竞技场=33KB,#1)

    这详细概述了JVM使用的不同内存区域,并显示了保留内存和提交内存。

    我不知道有什么技术可以给你更详细的内存消耗列表。

    进一步阅读:

    您还可以结合其他jcmd命令使用-XX:NativeMemoryTracking=detail。更详细的解释可以在Java平台的标准版故障排除指南2.6 jcmd实用程序中找到。您可以通过jcmd检查可能的命令

  •  类似资料:
    • 我的问题是,谁分配和管理这些内存段?操作系统不知道java程序正在运行,并认为它是JVM的一部分,作为计算机上的常规程序运行,JIT编译、java堆栈的使用,这些操作需要运行时内存分配,我不明白的是JVM如何将其内存划分为这些内存段。这肯定不是由操作系统来完成的,这些内存段(例如java堆栈)必须是连续的才能工作,所以如果JVM程序只是使用malloc命令来接收堆内存的最大大小并将这些内存划分为多

    • 我有一个非常消耗内存的程序,想使用-Xmx2048m为java jvm分配更多的最大内存。但在启动时,我得到一个“无法为对象堆保留足够的空间”错误。 当尝试多个值并发现我的最大值是时,它就开始了。但我喜欢分配2GB。在使用-Xmx1560m启动java进程后,我有6GB的物理内存,Taskmanager显示3400MB可用。 有人知道我为什么不能分配2GB吗?

    • 问题内容: 我们在 Tomcat 服务器上部署了一个Web应用程序。我们运行某些计划的作业,然后堆内存达到峰值并稳定下来,一切似乎都很好。但是,系统管理员抱怨内存使用率(Linux上的“ top”)随着计划的作业的增加而不断增加。堆内存和CPU内存之间有什么关联?可以通过任何JVM设置来控制它吗?我使用 JConsole 监视系统。 我通过JConsole强制进行垃圾收集,并且堆使用率下降了,但是

    • 我想了解为什么多次动态分配调用的数据比直接在代码中指定的或通过的单个调用分配的数据使用如此多的内存。 例如,我用C编写了以下两个代码: 测试1.c:int x用malloc分配 我在这里没有使用free来保持简单。当程序等待交互时,我查看另一个终端中的顶级功能,它向我显示了以下内容: test2. c: int x不是动态分配的 顶部显示: 我还编写了第三个代码,其结果与test2相同,我在tes

    • 本文向大家介绍IDEA设置JVM可分配内存大小和其他参数的教程,包括了IDEA设置JVM可分配内存大小和其他参数的教程的使用技巧和注意事项,需要的朋友参考一下 有时我们会遇到 java.lang.OutOfMemoryError 的问题,可能会需要设置jvm运行参数 作用 该参数通常用于设置系统级全局变量值,如配置文件路径,保证该属性在程序中任何地方都可访问。当然,也可以通过在程序中使用Syste

    • 对此有什么建议吗?