JVM的调优主要集中在内存上,包括内存大小和垃圾回收。因此了解JVM的内存模型是非常有必要的。

JMM由以下五个部分组成:

  1. 方法区,所有线程的共享区域,保存已加载的类,常量,静态变量,又称为永久代。这个区域内存耗尽会报java.lang.OutOfMemoryError: PermGen full
  2. 堆,所有线程的共享区域,分配对象实例,分为新生代(eden较大、survivor from、survivor to)和年老代(新生代中呆了足够长时间后移到这里)。堆中内存耗尽会报java.lang.OutOfMemoryError: Java heap space。
  3. 本地方法栈,线程私有,调用native方法时用的栈。
  4. 虚拟机栈,线程私有,保存局部变量、方法调用栈,递归过深会报StackOverflowError。如果虚拟机支持栈扩展,直到申请不到内存报OutOfMemoryError。
  5. 程序计数器,线程私有,指示下一个字节码,执行native方法时为空,不会报OutOfMemoryError。

windows vmmemWSA是什么进程_JVM

JVM启动时有一系列参数可以设置各个区域的大小:

  1. -Xmx 设置堆大小的最大值,例如-Xmx1024m表示最大为1G
  2. -Xms 设置堆大小的最小值,也就是JVM启动时的堆大小,例如-Xms1024m表示最小为1G
  3. -Xmn 设置新生代大小的最大值,例如-Xmn512m表示新生代最大为512MB
  4. -XX:NewSize 设置新生代大小的最小值,也就是JVM启动时的新生代大小,例如-XX:NewSize=512m表示新生代最小为512MB
  5. -XX:SurvivorRatio 设置新生代中eden和survivor的大小比值,默认-XX:SurvivorRatio=8表示eden:from:to=8:1:1,也就是说如果-Xmn1000m,那么eden为800M,两个survivor各占100M。
  6. -XX:NewRatio 设置年老代和新生代的比值,默认-XX:NewRatio=2表示年老代大小是新生代2倍。-Xmn的优先级高于这个设置
  7. -XX:PermSize 设置永久代大小的最小值,也就是JVM启动时永久代的大小,默认-XX:PermSize=16m
  8. -XX:MaxPermSize 设置永久代大小的最大值,默认-XX:PermSize=64m
  9. -Xss 设置虚拟机栈的大小,例如-Xss128k。在一些java虚拟机中,本地方法栈和虚拟机栈合并实现为同一个。
  10. -XX:MaxDirectMemorySize 设置本地直接内存的最大值,一般就是DirectByteBuffer使用的内存,不属于JMM,如果直接内存达到最大值会触发Full GC。默认大小与-Xmx一样

为了增加吞吐量,生产环境一般设置为:

  • -Xmx2048m -Xms2048m 两者一样避免堆大小反复震荡。jdk默认为内存大小的1/4,具体大小看情况,一般不超过可用内存的一半,如果确定程序中没有使用本地直接内存,可以设为更大。
  • -Xss128k jdk默认是1M,减小栈大小来支持更多的线程
  • -Xmn1024m 可以设大一点,避免新生代内存不够,对象直接进入年老代
  • 永久代一般不用设置,除非应用中使用的类太多或者动态生成类太多

注意 以上内容基于HotSpot jdk1.7以前版本,jdk1.7以后有了不少改变,例如永久代变为Metaspace,不再存储字符串常量。-XX:PermSize变为-XX:MetaspaceSize,-XX:MaxPermSize变为-XX:MaxMetaspaceSize