JVM
的内存结构中主要有 “堆”、“虚拟机栈”、“方法区”,所以 JVM
规范要求提供了这三个区域的参数设置。
堆内存设置
整个堆内存大小设置
参数名称 | 含义 | 默认值 | |
---|---|---|---|
-Xms | 初始堆大小 | 物理内存的1/64(<1GB) | 默认空余堆内存小于40%(MinHeapFreeRatio)时,JVM就会增大堆直到-Xmx的最大限制 |
-Xmx | 最大堆大小 | 物理内存的1/4(<1GB) | 默认空余堆内存大于70%(MaxHeapFreeRatio)时,JVM会减少堆直到 -Xms的最小限制 |
-XX:MaxHeapFreeRatio | 空闲堆大于该比例时堆缩小 | ||
-XX:MinHeapFreeRatio | 空闲堆小于该比例时堆增大 |
JVM
启动的时候初始堆大小通常为 -Xms
指定大小,随着程序的一直执行(产生新对象)那么堆的大小会一直增长直到达到 -Xmx
。
假设经历过一次 GC
后,堆中的空闲空间大于 -XX:MaxHeapFreeRatio
时,实际堆大小就会被回收,不低于 -Xms
指定大小;如果后续程序继续执行,堆中的剩余空间小于 -XX:MinHeapFreeRatio
时,实际堆大小就会继续增长,不超过 -Xmx
指定大小。
-Xms 等同于 -XX:InitialHeapSize; -Xmx 等同于 -XX:MaxHeapSize
新生代堆内存大小设置
新生代中会包含两个部分,分别是 Eden
区和两个 Survivor
区:
参数名称 | 含义 | 默认值 | 备注 |
---|---|---|---|
-XX:NewSize | 设置年轻代最小大小 | ||
-XX:MaxNewSize | 设置年轻待最大大小 | ||
-XX:SurvivorRatio | Eden区与Survivor区的大小比值 | 设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10 | |
-XX:NewRatio | 年轻代(Eden+2*Survivor)与老年代的比值 | -XX:NewRatio=4表示年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5 |
老年代堆内存大小设置
老年代堆大小的设置需要通过 -XX:NewRatio
来按比例划分。
比如你设置了 4GB内存
,给定的 -XX:NewRatio=3
,那么 年轻代 : 老年代 = 1 : 3
,所以老年代会占用3个G,新生代占用1个G。
非堆内存设置
永久代 (JDK7及以前)
凡是看过我《JVM运行时内存结构》的胖友们 (/偷偷看) ,都知道方法区是虚拟机规范给定的一个概念,里面会存放类信息、常量池、静态变量等内容。 Hotspot
则将方法区的内容都丢入了永久代中(方法区是概念,永久代是实现)。
参数名称 | 含义 | 默认值 |
---|---|---|
-XX:PermSize | 永久代的初始值 | 物理内存的1/64(<1GB) |
-XX:MaxPermSize | 永久代的最大值 | 物理内存的1/4(<1GB) |
元空间 (JDK8及以后)
永久代在JDK8以前存在于虚拟机管理的内存中;而元空间就是物理上也独立于堆,存在于直接内存中。
参数名称 | 含义 | 默认值 |
---|---|---|
-XX:MetaspaceSize | 元空间的初始值 | 64位JVM,20.75MB |
XX:MaxMetaspaceSize | 元空间的最大值 | 默认为0,表示无上限 |
由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生大量Full GC,通常都是由于永久代或元空间发生了大小调整,基于这种情况,一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大,对于8G物理内存的机器来说,一般我会将这两个值都设置为256M(PS:读者可以根据自己的实际情况再调整)。
虚拟机栈设置
这一块就不用多说了吧~
参数名称 | 含义 | 默认值 | |
---|---|---|---|
-Xss | 每个线程的堆栈大小 | JDK5.0以后每个线程堆栈大小为1M。在相同物理内存下,减小这个值能生成更多的线程.但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右 一般小的应用,如果栈不是很深, 应该是128k够用的 大的应用建议使用256k。这个选项对性能影响比较大,需要严格的测试。 |
-XX:ThreadStackSize 属于不稳定选项,可能随时发生变更