JVM中,如果把堆内存参数配置的超过了本地内存,会怎么样

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM中,如果把堆内存参数配置的超过了本地内存,会怎么样相关的知识,希望对你有一定的参考价值。

参考技术A java内存可以分为堆内存和非堆内存:
堆是给开发人员用的,是在JVM启动时创建;非堆是留给JVM自己用的,用来存放类型(类和接口)的信息。它和堆不同,运行期内GC不会释放空间。如果web app用了大量的第三方jar或者应用有太多的class文件而恰好MaxPermSize设置较小,超出了就会导致这块内存的占用过多造成溢出,或者服务器如tomcat热部署时侯不会清理前面加载的环境,只会将context更改为新部署的,非堆存的内容就会越来越多,热部署上几次就java.lang.OutOfMemoryError: PermGen space。
a) 堆内存设置:程序可以到达的,可以操作的
-Xms 初始堆内存 默认物理内存1/64,也是最小分配堆内存。当空余堆内存小于40%时,会增加到-Xms的最大限制
-Xmx 最大堆内存分配 默认物理内存1/4,当空余堆内存大于70%时,会减小到-Xms的最小限制。
一般设置 -Xms和Xms大小相等
b) 非堆内存设置
-XX:PermSize 非堆内存的初始值,默认物理内存的1/64 ,也是最小非堆内存。
-XX:MaxPermSize 非堆内存最大值,默认物理内存的1/4。

关于docker运行Java程序JVM配置参数使用jconsole的简单量化过程

1.如果服务可以本地启动那么尽量在本地进行参数预估

2.如果服务不能本地启动,可以使用远程连接方式进行预估

 

3.衡量要点:

Java程序运行大致分为三块:堆内存,非堆内存(虚拟机栈,方法区,本地方法栈,程序计数器),堆外内存.

docker容器中运行除了Java程序还需要为其余程序余力内存空间.这里假设统一预留50M空间.

3.1 堆内存的量化

堆内存主要分为几个区域,新生代,复制区,老年代.考虑GC会大量回收堆内存空间,只要不发生内存逸出和内存

泄露情况,堆内存能支持一定的并发即可.无线上数据参考情况可以,简单预估QPS为3进行测试堆内存可能大小.

这里以POIService为例子,启动项目后连接后观察情况如下.

访问接口调用时,其各项数据.

图中可以看出 堆内存最小可以到50M最大可大300M左右,堆内存主要用于实例化对象.我们这里预估下 150M就够用了.

为了线上稳定再次基础上提升10%, 可配置固定内存大小为165M即参数 -Xmx165M -Xms165M

线程没有及时进行回收,导致线程量一直在增加.需要优化相关代码.不然会导致线程占用内存持续增加,JVM会为每个线程单独

分配空间.

3.2 非堆内存量化

图中可以看出,非堆内存使用量不是很大大概65M左右.

设置参数:-XX:PermSize=65M -XX:MaxPermSize=130M (1.8以前)

-XX:MetaspaceSize = 100M (1.8以后)

这里预估为 165 + 100 + 20(对外内存) + 50 = 335M 这里直接给400M

这里要说下.因为资源有限才这么设置,如果资源足够可以进行GC时间的衡量来设置相关参数.

-Xmx180M -Xms180M -XX:MaxDirectMemorySize=20M -XX:MetaspaceSize=100M

调整后效果还可以,这里主意,GC会导致STW可能影响响应时间,要去衡量那个是当前需要的.

 

远程调试尝试

远程连接配置如下:

[program:configservice]

command=java -Xmx180M -Xms180M -XX:MaxDirectMemorySize=20M -XX:MetaspaceSize=100M -Djava.rmi.server.hostname=106.75.105.45 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=19999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -jar -Dfile.encoding=UTF-8 configservice.jar

没有限制前top观察到内存使用快到1G了,限制后如下:

一天后再次观察数据如下:

还是比较稳定的,目前使用内存 350M左右.线上给400M.

 

以上是关于JVM中,如果把堆内存参数配置的超过了本地内存,会怎么样的主要内容,如果未能解决你的问题,请参考以下文章

关于docker运行Java程序JVM配置参数使用jconsole的简单量化过程

关于docker运行Java程序JVM配置参数使用jconsole的简单量化过程

OpenJDK JVM 会把堆内存还给 Linux 吗?

第六部分:JVM内存模型与JVM参数详细配置

JVM之堆内存

JVM内存模型及配置参数