首先我们写一个报oom错误的代码
public class demo01 {
public static void main(String[] args) {
byte[] array=new byte[1*1024*1024];//1m 1兆
ArrayList<demo01> list=new ArrayList<demo01>();
int count=0;//计数
try{
while(true){
list.add(new demo01());//无限的向list中添加数据,new新的对象。注意:次方法会导致oom
count=count++;
}
}catch(Error e){
System.out.println("count:"+count);
e.printStackTrace();
}
//Throwable
//error
//Exception
}
}
设置堆内存大小
如果不设置堆内存,堆的默认内存应该是1GB,会占用很多资源 解释一下-XX:+HeapDumpOnOutOfMemoryError
heap表示堆,on表示条件
让堆进行Dump,条件是OutOfMemoryError。意思就是说只要报出OOM这个异常,就会被Dump
如果要dump其他异常只需要将OutOfMemoryError这个异常改成你想要的dump的异常就可以了
Jprofiler查看内存使用情况
上一步我们设置完堆内存大小后,在运行一下程序,如下:会创建一个文件Dumping heap to java_pid47550.hprof …。
此时我们找到这个文件:
依次点击:对着demo01类右击>open in>finder>在文件根目录下就可以找到Dumping heap to java_pid47550.hprof这个文件,然后双击打开(前提是下载了jprofiler这个软件)
如上图我们可以在最大对象这里看出是那个部分出错,如果具体要看是哪一行有问题,我们需要点击堆遍历器下的线程转储,这样就可以看出问题所在了
JVM常见调优
堆设置
-Xms:初始堆大小
-Xmx:最大堆大小
-XX:NewSize=n:设置年轻代大小
-XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
-XX:MaxPermSize=n:设置持久代大小
收集器设置
-XX:+UseSerialGC:设置串行收集器
-XX:+UseParallelGC:设置并行收集器
-XX:+UseParalledlOldGC:设置并行年老代收集器
-XX:+UseConcMarkSweepGC:设置并发收集器
垃圾回收统计信息
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename
并行收集器设置
-XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数。并行收集线程数。
-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间
-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
-XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。
-XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。