1、日志初步扫盲
首先在idea的Edit configurations设置:
这样在运行的时候如果出现了垃圾回收就会打印GC日志,
比如这段代码:
public class FinalizeEscapeGC {
public static FinalizeEscapeGC SAVE_HOOK = null;
public void isAlive(){
System.out.println("yes, i am still alive");
}
protected void finalize() throws Throwable {
super.finalize();
System.out.println("finalize method executed");
SAVE_HOOK = this;
}
public static void main(String[] args) throws InterruptedException {
SAVE_HOOK = new FinalizeEscapeGC();
SAVE_HOOK = null;
System.gc();
Thread.sleep(500);
if(SAVE_HOOK == null){
System.out.println(" no, i am dead");
}else{
SAVE_HOOK.isAlive();
}
SAVE_HOOK = null;
System.gc();
Thread.sleep(500);
if(SAVE_HOOK == null){
System.out.println(" no, i am dead");
}else{
SAVE_HOOK.isAlive();
}
}
}
发生了两次System.gc(),两次垃圾回收,显示日志如下:
刚开始的GC日志开头的“[GC(System.gc())“和"Full GC(System.gc())“说明了这次垃圾收集的停顿类型,而不是用来区分新生代GC还是老年代GC的,如果是"Full”,说明这次发生了Stop-The-World的停顿(停顿了所有java线程),而System.gc()表示这次垃圾收集是由于执行了System.gc()产生的
后面的”[PSYoungGen"表示GC发生的区域,YoungGen自然表示是新生代区域,这里的发生区域是和GC收集器相关的,这里是“PSYoungGen"表示是Parallel Scavenge收集器,如果是ParNew收集器,将会是"[ParNew",如果是Serial收集器绘制"[DefNew"意为”D额fault New Generation"
那自然,后面的"[ParOldGen"表示的是老年代回收
后面的那段Heap区表示的是内存空间分配情况和使用情况: ![这里写图片描述](https://img-blog.csdn.net/20180514084211725?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQ0NzMxMTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70) PSYoungGen total:表示新生代可用空间(Eden区加上一个Survivor区) from space和to space分别表示两个survivor的空间
ParOldGen自然表示的就是老年代的空间 ##**2、内存分配参数** 可以在idea的Edit Configuration的位置设置参数对对内存进行分配,举例如下(多个参数用空格分隔):
-Xms20M //堆大小20M
-Xmx20M //堆最大大小是20M(不可扩展)
-Xmn10M //新生代大小10M
-XX:SurvivorRatio=8 //Eden:Survivor1:Survivor2 = 8:1:1
内存分配遵循几条规则:
(1)对象优先在Eden区分配
(2)大对象(一般是Eden区内存的40%,由-XX:PretenureSizeThreshold参数决定,但是这个参数是不可设置的)直接进入老年代,如果Eden区剩余空无法存放当前对象,如果对象小于40%,那么会首先把Eden区存活对象复制到Survivor区(当然Survivor区如果放不下就复制到老年区),如果对象大于等于40%,那么就直接进入老年代。这样子设计的目的是为了避免因为要分配大对象而提前触发垃圾回收(明明还有很多空闲内存的,只是为了要找大的连续内存却要垃圾回收),尤其是那些朝生夕灭的大对象,使用时间不长,就会频繁触发垃圾回收
(3)长期存活的对象将进入老年代:对象有一个计数器,每一次发生了Minor GC后仍然存活并且能够被Survivor容纳的时候,对象计数器就加1,如果计数器超过了阈值,就直接被晋升到老年代。可以通过-XX:MaxTenuringThreshold设置,比如"-XX:MaxTenuringThreshold=1",表示阈值是1
(4)动态对象年龄判定(jdk7版本之后不适用)
(5)空间分配担保(jdk6 Update24之后不适用)