4种GC方法+分代回收+触发GC情况+内存申请过程

①引用计数

对象增加一个引用时,引用数+1。减少一个时,引用数-1。当进行垃圾回收时,只回收引用数为0的对象。面对互相引用无解,方法比较老,基本弃用


②标记+清除

从根节点遍历标记对象,然后遍历整个堆,清除没有标记的对象。

缺点:运行效率不高,产生了内存碎片,运行时需要暂停应用


③复制

将内存分为2个区域(区域a和区域b),一个区域空着(区域a),另一个区域(区域b)放对象。垃圾回收时,将区域b还在引用的对象复制到空着的区域(区域a)中去,并且当前区域(区域b)清空。如此反复

缺点:复制到a区域的时候,同时进行了内存整理,没有内存碎片。但是需要2倍的内存


④标记+整理

从根节点遍历标记对象,然后遍历整个堆,清除没有标记的对象,并且将有标记的对象压缩到一块的区域内
特点:没有内存碎片,也不需要2倍内存



分代回收中将内存分成了3代

①年轻代。

年轻代内分为eden区和两个survivor区。eden区存储刚刚建立的新对象。eden区满后,将还存活的对象复制到一个survivor区中,然后这个survivor区满了以后,将还存活的对象复制到第二个survivor区中去,同时清空第一个survivor区。第二个区满了以后,将第一个survivor区中的存活的对象复制到年老代(可能要多次GC以后还存活的对象才能复制到年老代),剩下的活的引用 对象复制到第一个survivor区,清空第二个survivor区。
没错,两个survivor区用的就是GC中的复制方法,oh yeah。

年轻代区域一般比较小。可以有多个survivor区,不一定非要2个。


②年老代。

年老代存储的是生命周期比较长的对象,年老代用标记+清理的方法进行GC


③持久代。

持久代一般存放静态对象,class,方法等。持久代对垃圾回收没有影响,但是有些应用可能动态生成火这调用一些class,例如hibernate等,这时需要设置一个比较大的持久代来存放这些运行中新增的类。通过-XX:MaxPermSize=设置


摘抄:

什么情况下触发垃圾回收 

由于对象进行了分代处理,因此垃圾回收区域、时间也不一样。GC有两种类型:Scavenge GCFull GC

 

Scavenge GC

    一般情况下,当新对象生成,并且在Eden申请空间失败时,就会触发Scavenge GC,对Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。这种方式的GC是对年轻代的Eden区进行,不会影响到年老代。因为大部分对象都是从Eden区开始的,同时Eden区不会分配的很大,所以Eden区的GC会频繁进行。因而,一般在这里需要使用速度快、效率高的算法,使Eden去能尽快空闲出来。

 

Full GC

    对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个对进行回收,所以比Scavenge GC要慢,因此应该尽可能减少Full GC的次数。在对JVM调优的过程中,很大一部分工作就是对于FullGC的调节。有如下原因可能导致Full GC:

· 年老代(Tenured)被写满

· 持久代(Perm)被写满 

· System.gc()被显示调用 

·上一次GC之后Heap的各域分配策略动态变化



当一个URL被访问时,内存申请过程如下:

A. JVM会试图为相关Java对象在Eden中初始化一块内存区域
B. 当Eden空间足够时,内存申请结束。否则到下一步
C. JVM试图释放在Eden中所有不活跃的对象(这属于1或更高级的垃圾回收), 释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区
D. Survivor区被用来作为Eden及OLD的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区
E. 当OLD区空间不够时,JVM会在OLD区进行完全的垃圾收集(0级)
F. 完全垃圾收集后,若Survivor及OLD区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现”out of memory错误”

JVM调优建议:

ms/mx:定义YOUNG+OLD段的总尺寸,ms为JVM启动时YOUNG+OLD的内存大小;mx为最大可占用的YOUNG+OLD内存大小。在用户生产环境上一般将这两个值设为相同,以减少运行期间系统在内存申请上所花的开销。
NewSize/MaxNewSize:定义YOUNG段的尺寸,NewSize为JVM启动时YOUNG的内存大小;MaxNewSize为最大可占用的YOUNG内存大小。在用户生产环境上一般将这两个值设为相同,以减少运行期间系统在内存申请上所花的开销。
PermSize/MaxPermSize:定义Perm段的尺寸,PermSize为JVM启动时Perm的内存大小;MaxPermSize为最大可占用的Perm内存大小。在用户生产环境上一般将这两个值设为相同,以减少运行期间系统在内存申请上所花的开销。
SurvivorRatio:设置Survivor空间和Eden空间的比例

 
 

你可能感兴趣的:(基础)