我们可以尝试对JVM进行调优,主要就是堆内存那块
所有线程共享数据区大小=新生代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m。所以java堆中增大年轻代后,将会减小年老代大小(因为老年代的清理是使用fullgc,所以老年代过小的话反而是会增多fullgc的)。此值对系统性能影响较大,Sun官方推荐配置为java堆的3/8。
-Xmx –Xms:指定java堆最大值(默认值是物理内存的1/4(<1GB))和初始java堆最小值(默认值是物理内存的1/64(<1GB))
默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制.,默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制。简单点来说,你不停地往堆内存里面丢数据,等它剩余大小小于40%了,JVM就会动态申请内存空间不过会小于-Xmx,如果剩余大小大于70%,又会动态缩小不过不会小于–Xms。就这么简单
开发过程中,通常会将 -Xms 与 -Xmx两个参数配置成相同的值,其目的是为了能够在java垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小而浪费资源。
4.2 调整新生代和老年代的比值
-XX:NewRatio --- 新生代(eden+2*Survivor)和老年代(不包含永久区)的比值
例如:-XX:NewRatio=4,表示新生代:老年代=1:4,即新生代占整个堆的1/5。在Xms=Xmx并且设置了Xmn的情况下,该参数不需要进行设置
4.3 调整Survivor区和Eden区的比值
-XX:SurvivorRatio(幸存代)--- 设置两个Survivor区和eden的比值
例如:8,表示两个Survivor:eden=2:8,即一个Survivor占年轻代的1/10
根据实际事情调整新生代和幸存代的大小,官方推荐新生代占java堆的3/8,幸存代(Survivor)占新生代的1/10
在OOM时,记得Dump出堆,确保可以排查现场问题,通过下面命令你可以输出一个.dump文件,这个文件可以使用VisualVM或者Java自带的Java VisualVM工具。
-Xmx20m -Xms5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=你要输出的日志路径
永久区的设置
-XX:PermSize -XX:MaxPermSize
初始空间(默认为物理内存的1/64)和最大空间(默认为物理内存的1/4)。也就是说,jvm启动时,永久区一开始就占用了PermSize大小的空间,如果空间还不够,可以继续扩展,但是不能超过MaxPermSize,否则会OOM。
4.7 JVM的栈参数调优
4.7.1 调整每个线程栈空间的大小
可以通过-Xss:调整每个线程栈空间的大小
JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右