---
title: 设置JVM堆空间大小
description: "JVM在执行Java程序时会把它所管理的内存划分为若干个不同的运行时数据区域，主要包括：程序计数器、方法区、虚拟机栈、本地方法栈和堆："
url: https://www.hikunpeng.com/document/detail/zh/perftuning/tuningtip/kunpengtuning_12_0063.html
sourcePath: /source/zh/perftuning/tuningtip/kunpengtuning_12_0063.html
indexId: aee01064b3bc906c5e2327269261bba2e61c61b277e27b10866ee1ddf476506358
---
# 设置JVM堆空间大小

#### 原理

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


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