中文
注册
我要评分
文档获取效率
文档正确性
内容完整性
文档易理解
在线提单
论坛求助
鲲鹏小智

设置JVM堆空间大小

原理

JVM在执行Java程序时会把它所管理的内存划分为若干个不同的运行时数据区域,主要包括:程序计数器、方法区、虚拟机栈、本地方法栈和堆:

  1. 程序计数器可以看作时当前线程所执行的字节码的行号指示器。
  2. 方法区用于存储被JVM加载的类信息、常量、静态变量等数据。
  3. 虚拟机栈存储的时Java方法执行的线程内存模型,每一个方法被调用到执行完毕的过程,就对应一个栈帧在虚拟机栈中从入栈到出栈的过程。
  4. 本地方法栈和虚拟机栈的功能相同,差别是本地方法栈只为本地方法调用服务。
  5. 堆是JVM管理内存中占用比例最大的一块,用于存储Java程序对象实例,几乎所有的对象实例内存都在这里分配。从内存回收角度和经典垃圾收集器分带理论上看,堆内存空间一般被分为:新生代、老年代、永久代、Eden空间、From/To Survivor等区域。各代功能和划分说明可以参考:https://www.cnblogs.com/fangfuhai/p/7206944.html

针对堆空间的优化是Java性能调优的重点之一。如果没有设置JVM堆空间大小,JVM会根据服务器物理内存大小设置默认堆大小的值。例如,在64位的服务器端,当物理内存小于192MB时,JVM堆大小默认选为物理内存的一半;当物理内存大192MB且小于128GB时,JVM堆大小默认选为物理内存的四分之一;当物理内存大于等于128GB时,都为32GB。通常情况下,Java应用程序的会通过参数指定堆大小,具体方法下文会有说明。

应用程序选用多大的堆空间大小及配比,一般要根据程序的GC情况和服务器内存资源进行综合评估,是个循序渐进不断优化的过程,如果垃圾回收(GC)频繁触发,可以尝试增加堆空间缓解。

推荐配置原则:

  1. 应用程序运行时,计算老年代存活对象的占用空间大小X。程序整个堆大小(Xmx和Xms)设置为X的3~4倍;永久代PermSize和MaxPermSize设置为X的1.2~1.5倍。年轻代Xmn的设置为X的1~1.5倍。老年代内存大小设置为X的2~3倍。
  2. JDK官方建议年轻代占整个堆大小空间的3/8左右。
  3. 完成一次Full GC后,应该释放出70%的堆空间(30%的空间仍然占用)。

修改方式

在Java应用程序启动时,添加如下参数并设置大小:

参数

说明

-Xmx

设置JVM最大可用堆内存大小。

-Xms

设置初始堆大小,一般和Xmx保持一致。

-Xmn

设置年轻代堆大小。

-Xss

设置每个线程的堆大小。JDK 1.5以后每个线程堆栈大小默认为1MB,1.5以前为256K。

-XX:NewRatio=

设置年轻代(包括Eden和两个Survivor区)与老年代的比值(不包括永久代)。如设置为4,则年轻代与老年代所占比值为1:4,年轻代占整个堆栈的1/5。

-XX:SurvivorRatio=

设置年轻代中Eden区与Survivor区的大小比值。如设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6。

-XX:MaxPermSize=

设置永久代堆大小。

举例:

java -Xmx3600m -Xms3600m -Xmn2g -Xss128k

设置最大堆空间为3600MB,初始化堆大小为3600MB,年轻代大小为2GB,线程堆大小为128KB。