JAVA中的GC以及年轻代,年老代,持久代的认识

java中我们常常谈论到垃圾回收机制,那么,垃圾回收机制又是什么呢?说到JVM调优,似乎很高大上,那么JVM调的都是那些数据呢?伊甸园区,幸存区,年轻代,年老代,持久代,每个词都熟悉又陌生,似乎很深奥,触不可及,那么这些区又是存放什么的呢?接下来让我们一起走进堆内存。

一:GC的方式与过程

上图即是堆内存的大致结构:

young Generation:年轻代:年轻代中包含着两个survivor幸存区和一个eden伊甸园区

old Generation:老年代

perm:持久代

那么,他们又是如何运作的呢?

按照流程,我们先说持久代。

持久代:当类加载时,我们会将.class文件中的部分信息加载到持久区中,比如类的修饰符,字段属性和方法信息等。又或者时import引入类的信息。都叫持久代了,也就说明这块区间的内存相对稳定,垃圾回收一般也就没持久代啥事儿。

伊甸园区:伊甸园区好理解,希腊神话中人类诞生的地方。因此,当我们创建对象时,比如:new String("123");即JVM在伊甸园区创建了一个对象,对象里面装的是String类型的数据123。

幸存区:当伊甸园区的内存占满了,而又需要创建对象时,JVM就会像伊甸园区还活着的(被引用的对象),拷贝到幸存区去。注意:此时其实会调用一此Minor GC操作,也可以称为迷你的垃圾回收动作,该动做就会将没有被引用的对象回收了。然后程序继续运行,当伊甸园和其中一个幸存区(幸存区1)都满了的时候,此时又会执行一次Minor GC,该次垃圾回收会将伊甸园区和幸存区1中所有还活着的对象(仍然被引用的)复制到幸存区2中,然后将没有用的对象回收。

老年代:当需要创建对象,而伊甸园区和幸存区都装满了的时候,就会将年轻代活着的的对象复制到老年代中,此时又会唤起Minor GC操作,将没有被引用的对象回收。但是我们常讨论的,其实还是Full GC,即当老年代内存占满了的时候,JVM会触发Full GC,也就是重量级的垃圾回收机制。

Full GC:Full GC会对年轻代,年老代,持久代的对象进行全面回收。但是垃圾回收线程并不会中断其他的线程,而是并发执行的。在真正回收垃圾之前,会先根据根搜索算法,找到可以回收的对象,并对其进行标记。但是如果先将对象标记了可回收,但是后面有给这个指向null的对象str指向了“123”这块内存时,这个对象就不应该被回收。那么就会出现这个对象到底应不应该回收的问题。JVM为了解决这个问题,会在一些特定的位置上设置一些“安全点”,比如容易抛异常的地方或者循环的末尾,当垃圾回收进程运行到这些安全点时,就会执行stop the word命令,暂停所有线程,只运行垃圾回收线程。这也就是内存满了容易卡的原因。

当堆内存快要用完时,就会Full GC,此时可能会出发stop the word,当GC之后,内存还是不够用,此时还会再次执行Full GC,此时还有可能会触发stop the word。因此,我们需要合理的写代码,尽量避免创建不用的对象以及避免无用对象无法回收,当然,配置好堆内存的各个区的比例,按需配置,也是必要的。也可以简单的来说,JVM调优,在一定程度上,就是配置堆内存中各个区间的大小。

二:如何判单对象是否可以回收?

早期的JDK采用的是“引用计数法”来判断对象是否可以被回收。当一个对象被创建时,其计数为0,当其被a引用时,计数+1,但是当a = null;时,计数-1,那么当计数为0时,该对象即可被回收,但是这样子的算法,有个缺陷,就是循环引用的对象无法被回收。

后来改用“根搜索算法”标记可回收对象,将根节点不可达的对象进行标记。

三:何时Full GC呢?

触发Full GC有四种情况。

1:老年代被写满了

2:持久代被写满了

3:当调用了system.gc();

4:当用命令分配堆空间的运行策略时,比如设置年轻代和老年代的比例。如果JVM发现,上次GC后,这种运行策略有了变化,就会触发GC。

 

四:平时说的JVM调优,都是调的那些参数呢?

-Xms:初始堆大小,默认是物理内存的1/64。默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到–Xmx的最大限制。例如:-Xms 500m。
-Xmx:最大堆大小。默认是物理内存的1/4 默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制。
-XX:NewSize:设置年轻代大小(初始值)。
-XX:MaxNewSize:设置年轻代最大值。
**-XX:NewRatio=n:设置年轻代和年老代的比值。一般设置为4
-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。
-XX:PermSize(1.8之后改为MetaspaceSize) 设置持久代(perm gen)初始值,默认是物理内存的1/64。
-XX:MaxPermSize=n:(1.8之后改为MaxMetaspaceSize)设置最大持久代大小。
-Xss:每个线程的堆栈大小。所有当项目经常发生栈内存溢出(stackOverflowErro)时,可以考虑增加该参数大小
 

你可能感兴趣的:(java_web,JAVA基础,java面试,JAVA基础,GC)