深入理解java虚拟机第二章

时间:2023-01-01 23:54:16

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

表示对非堆区分配的内存的最大上限