2.4实战OutOfMemoryError异常
2.4.1 trace跟踪参数
1) 打印GC的详细信息:
-XX:PrintGCDetails
2) 打印GC发生的时间戳:
-XX:PrintGCTimeStamps
3) 每一次GC前和GC后都打印堆的信息
-XX:PrintHeapAtGC
4) 监控类的加载
-XX:TraceClassLoading
5) -XX:+PrintClassHistogram
按下Ctrl+Break后,打印类的信息。
2.4.2 堆的分配参数
[GC[DefNew: 4416K->0K(4928K), 0.0001897 secs]4790K->374K(15872K), 0.0002232 secs] [Times: user=0.00 sys=0.00, real=0.00secs]
上方日志的意思是说:这是一个新生代的GC。方括号内部的“4416K->0K(4928K)”含义是:“GC前该内存区域已使用容量->GC后该内存区域已使用容量(该内存区域总容量)”。而在方括号之外的“4790K->374K(15872K)”表示“GC前Java堆已使用容量->GC后Java堆已使用容量(Java堆总容量)”。
再往后看,“0.0001897 secs”表示该内存区域GC所占用的时间,单位是秒。
所谓的新生代和老年代是针对于分代收集算法来定义的,新生代又分为Eden和Survivor两个区。加上老年代就这三个区。数据会首先分配到 Eden区当中(当然也有特殊情况,如果是大对象那么会直接放入到老年代(大对象是指需要大量连续内存空间的java对象)。),当Eden没有足够空间的时候就会 触发jvm发起一次Minor GC。如果对象经过一次Minor GC还存活,并且又能被Survivor空间接受,那么将被移动到Survivor空 间当中。并将其年龄设为1,对象在Survivor每熬过一次MinorGC,年龄就加1,当年龄达到一定的程度(默认为15)时,就会被晋升到老年代中了,当然晋升老年代的年龄是可以设置的。
其实新生代和老年代就是针对于对象做分区存储,更便于回收等等
a) -Xmx –Xms:指定最大堆和最小堆
b) -Xmn:设置新生代大小
c) -XX:NewRatio:新生代(eden+2*s)和老年代(不包含永久区)的比值,老年代有两个。
d) -XX:SurvivorRatio(幸存代):设置两个Survivor区和eden的比值
e) -XX:+HeapDumpOnOutOfMemoryError:
OOM时导出堆到文件,根据这个文件,我们可以看到系统dump时发生了什么。
f) -XX:+HeapDumpPath
导出OOM的路径
g) -XX:PermSize
表示非堆区初始内存分配大小,其缩写为permanent size(持久化内存
h) -XX:MaxPermSize
表示对非堆区分配的内存的最大上限