Java虚拟机相关的问题一般多是下面几种问题:gc时间过长、OOM、死锁、线程block、线程数暴涨等问题
按照内存区域一般有以下的异常:
(1)java堆:
常见异常:java.lang.OutOfMemory Error:Java heap space
控制参数:-Xms(初始化堆)-Xmx(最大堆)-Xmn(新生代)
解决思路:
1、先查看是不是内存泄漏(内存中的对象是不是必须的),如果是泄漏,则找到与GC root 的路径解决泄漏
2、看物理内存是否允许加大-Xms,-Xmx
3、检查堆中是不是有对象实例一直在内存中没有释放
4、技巧让-Xms = -Xmx,减少内存扩展的开销
(2)虚拟机栈和本地方法栈:
常见异常:java.lang.StackOverflow Error,线程请求的栈深度大于虚拟机所允许的最大深度;java.lang.OUtOfMemory Error在扩展栈时无法申请到足够的内存空间。
控制参数:-Xss
解决思路:
1、加大-Xss参数
2、减少线程
3、更换64位虚拟机
4、减少最大堆(Xmx)
(3)方法区:
常见异常:java.OutOfMemory Error:PermGen space
控制参数:-XX:PermSize -XX:MaxPermSize
解决思路:
1、加大参数
2、增加参数:-XX:PrintGCDetails,-XX:+PrintGCTimeStamps和-XX:+PrintGCDateStamps,还可以指定日志输出到文件:-Xloggc:。通过查看GC日志来查看新生代GC(Minor GC)和老年代GC(Full GC或MajorGC)的回收效率和回收频率。通常Minor GC会很频繁,回收效率高才是对
3、稍微的加大Survivor1 Survivor2的空间
(4)本机直接内存
常见异常:java.lang.OutOfMemory Error,有allocate、Native字样
控制参数:-MaxDirectMemorySize如不指定则与-Xmx一致
解决思路:
合理规划服务器内存,预留足够的内存给本地内存。加大参数。
通常我们会根据实际情况(服务器内存大小)对堆内存大小进行调优,内存参数含义及大小分配建议如下:
-Xmx:java虚拟机堆区内存可被分配的最大上限,通常为操作系统可用内存的1/4;
-Xms:java虚拟机堆区内存初始内存分配的大小,通常为操作系统可用内存的1/64;
开发过程中,通常会将-Xms 与-Xmx两个参数的配置相同的值,其目的是为了能够在java垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小而浪费资源。
-XX:NewSize:新生代初始内存的大小,应该小于-Xms的值;
-XX:NewRatio:Yong 和 Old的比例,比如值为2,则Old是Yong的2倍,即Yong Generation占据内存的1/3;
-XX:Maxnewsize:Yong的最大值大小;
-Xmn:对 -XX:newSize、-XX:MaxnewSize两个参数的同时配置,也就是说如果通过-Xmn来配置新生代的内存大小,那么-XX:newSize = -XX:MaxnewSize = -Xmn;
-XX:Surviorratio:Eden和一个Suivior的比例,比如值为5,即Eden是To(S2)的比例是5,(From和To是一样大的),此时Eden占据Yong Generation的5/7