欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

GC垃圾回收

程序员文章站 2022-06-15 15:33:28
...

GC主要分为 7大区进行垃圾回收

GC垃圾回收

下面我来介绍下这几个区 以及这几个区的工作:

首先是 年轻区(young区) :此区主要负责接收新的对象(也就是说新来一个对象先到young区报道)

年轻区 又包括  Eden区 和 Survivor区 

新对象其实是先到Eden区报道, 然后不断增加 如果Eden区满了 会将区中数据复制到Survivor区中,同时清空Eden区(第一次GC完成,也就是清空Eden区)

Survivor区又包括 from区和To区

这时Survivor区是便会不断增加 如果Survivor区也满了,将会复制数据到 Old区同时清空Survivor区(这里要说明 其实Survivor区是多个 通常是两个, 当数据同步到Old区时 先清空Survivor1区 同时将留下的 年轻周期数据同步到 Survivor2区中)

然后Old区也是在不断增加 如果Old区也满了  报错内存溢出 full GC

 

解决垃圾回收处理方法 这里提供一种:

JVM调优建议:

Ms(young和old区使用大小)

Mx(young和old区最大承受大小)

newSize(young区使用大小)

MaxSize(young区最大承受大小)

permSize(持久区使用大小)

MaxPermSize(持久区最大使用大小)

suivivorRatio(设置Eden和survivor比例  最好是8:1)

其他的都调试为相同

持久区最好给个256M

基本解决基本问题

 

别人家的 分代算法 详解:

年轻代(Young Generation)

  1.所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。

  2.新生代内存按照8:1:1的比例分为一个eden区和两个survivor(survivor0,survivor1)区。一个Eden区,两个 Survivor区(一般而言)。大部分对象在Eden区中生成。回收时先将eden区存活对象复制到一个survivor0区,然后清空eden区,当这个survivor0区也存放满了时,则将eden区和survivor0区存活对象复制到另一个survivor1区,然后清空eden和这个survivor0区,此时survivor0区是空的,然后将survivor0区和survivor1区交换,即保持survivor1区为空, 如此往复。

  3.当survivor1区不足以存放 eden和survivor0的存活对象时,就将存活对象直接存放到老年代。若是老年代也满了就会触发一次Full GC,也就是新生代、老年代都进行回收

  4.新生代发生的GC也叫做Minor GC,MinorGC发生频率比较高(不一定等Eden区满了才触发)

年老代(Old Generation)

  1.在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。

  2.内存比新生代也大很多(大概比例是1:2),当老年代内存满时触发Major GC即Full GC,Full GC发生频率比较低,老年代对象存活时间比较长,存活率标记高。

持久代(Permanent Generation)

  用于存放静态文件,如Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate 等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。

 

这里提供一种实例:

Static Vector v = new Vector(); 
for (int i = 1; i<100; i++) 
{ 
    Object o = new Object(); 
    v.add(o); 
    o = null; 
}
复制代码

  在这个例子中,代码栈中存在Vector 对象的引用 v 和 Object 对象的引用 o 。在 For 循环中,我们不断的生成新的对象,然后将其添加到 Vector 对象中,之后将 o 引用置空。问题是当 o 引用被置空后,如果发生 GC,我们创建的 Object 对象是否能够被 GC 回收呢?答案是否定的。因为, GC 在跟踪代码栈中的引用时,会发现 v 引用,而继续往下跟踪,就会发现 v 引用指向的内存空间中又存在指向 Object 对象的引用。也就是说尽管o 引用已经被置空,但是 Object 对象仍然存在其他的引用,是可以被访问到的,所以 GC 无法将其释放掉。如果在此循环之后, Object 对象对程序已经没有任何作用,那么我们就认为此 Java 程序发生了内存泄漏。

2.各种连接,数据库连接,网络连接,IO连接等没有显示调用close关闭,不被GC回收导致内存泄露。

3.监听器的使用,在释放对象的同时没有相应删除监听器的时候也可能导致内存泄露。

相关标签: 面试积累