`
hongwei3344661
  • 浏览: 29689 次
  • 性别: Icon_minigender_1
文章分类
社区版块
存档分类
最新评论

JAVA垃圾回收

 
阅读更多

GC

gc:java的垃圾回收机制

在java中,内存的分配是由程序完成的,而内存的释放是由GC完成

调用System类的静态方法gc()可以进行垃圾回收,但它只是向JVM发出一个申请,到底是否真正执行垃圾收集,一切都是个未知数

垃圾回收的三种算法

  • 标记清除算法:

    • 标记阶段:先通过根节点,标记所有从根节点开始的对象,未标记的未垃圾对象
    • 清除阶段:清除所有未标记的对象

    缺点:标记和清除的效率都不高

    ​ 清除之后会产生大量不连续的内存碎片,不连续的内存空间使用效率比较低

  • 复制算法:(新生代使用的算法)

    • 将原有的内存空间分为两块,每次只使用其中的一块,在垃圾回收时,将正在使用的内存块中的存活的对象复制到未使用的内存块中,然后清除正在使用的内存块中的所有对象
  • 标记整理算法:(老年代使用的算法)

    • 标记阶段:先通过根节点,标记所有从根节点开始的可达对象,未被标记的为垃圾对象
    • 整理阶段:将所有存活的对象压缩到内存的一段,之后清理边界所有的空间

此外还有个古老的算法:引用计算法,其核心是对象在被引用时引用计数+1,而当引用不再使用时引用计数-1,当一个对象的引用计数为0时,则说明它将来不再被引用,因此可以释放对应的内存空间

三种算法比较

  • 效率:复制算法>标记整理>标记清除(只是简单比较时间复杂度,实际情况不一定如此)

  • 内存整齐度:复制算法=标记整理>标记清除

  • 内存利用率:标记整理=标记清除>复制算法

GC引用可达性分析算法中,可作为GC Roots的对象

  • java虚拟机栈中的对象
  • 方法区中的静态成员
  • 方法区中的常量引用对象
  • 本地方法区中的JNI(Native方法)引用对象

GC的分代回收

  • 新生代:(复制算法 GC:minor gc)

    在方法中new一个对象,在这个方法调用完毕后,对象就会被回收,这就是一个典型的新生代对象。

    新生代存放生命周期很短的对象,这部分对象在GC的时候很多已经是非活动对象,因此采用复制算法,只需将少量的存活对象copy到to space,存活越少,效率越高

    新生代又分为:

    • eden:每当对象创建的时候,总陪分配到这个区域
    • survivor1:复制算法中的from space
    • survivor2:复制算法中的to space

    Hotspot默认将Eden区和两个survivor区按照8:2的比例划分

  • 老年代:(标记整理算法 GC:major gc也叫full gc)

    生命周期长,在新生代中经过多次minor gc依旧存活的对象。survivor空间不够用时,需要依赖老年代进行分配担保,所有大对象直接进入老年代。老年代区域比较大,需要时间长

  • 永久代:(即方法区)

    存放class信息,方法信息,常量池,静态变量

    也会发生gc,这里的gc主要是对常量池的回收和对类的卸载

minor gc 与full gc

  • minor gc是新生代的垃圾回收机制,复制算法,调用频繁,回收速度快
  • full gc是老年代的垃圾回收机制,标记整理算法,调用不频繁,回收速度慢
  • full gc发生的次数不会有minor gc那么频繁,但Time(full gc)>Time(minor gc)
  • 当eden满了,就minor gc
  • 当Eden+from space空间大于老年代剩余空间时,就会full gc

垃圾收集器

  • Serial收集器:单线程独占 
    • 单线程收集器,不是只能使用一个CPU。在进行垃圾收集时,必须暂停其他所有的工作线程,直到收集结束
    • 新生代–复制算法,老年代–标记整理算法
    • 简单高效,client模式下默认的新生代收集器
  • ParNew收集器:多线程独占 
    • ParNew收集器是Serial收集器的多线程版本
    • 新生代–复制算法,老年代–标记整理算法
    • server模式下首选新生代收集器
  • ParNew Scanvenge收集器: 
    • 类似ParNew,但更加关注吞吐量
  • G1收集器: 
    • 当今收集器发展的最前沿成果之一。对垃圾回收进行了划分优先级的操作,优先级的回收方式保证了他的高效率
    • 最大的优点是结合了空间整合,不会产生大量的碎片,也降低了进行gc的频率
  • CMS收集器: 多线程非独占 
    • 使用的是标记清除算法
    • 一种以获得最短回收停顿时间为目标的收集器,适用于互联网站和B/S系统的服务器上

java中的内存泄漏

在Java中,内存泄漏就是存在一些被分配的对象,这些对象不会被GC回收,但它们却占用内存

这些对象有两个特点:

  1. 对象是可达的
  2. 对象是无用的

    • 例子:循环申请Object对象并放入一个Vector中。如果仅仅释放引用本身,那么Vector仍然引用该对象,这个对象对于GC来说是不可回收的。如果对象加入到Vector后还要将其删除,最简单的办法就是将Vector对象置为null
        Vector v = new Vector();
        for (int i = 0; i < 100; i++) {
            Object o = new Object();
            v.add(o);
            o = null;
        }

        v = null;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 物理连接:例如数据库和网络连接,除非显示的关闭了连接,否则不会自动被GC回收。数据库的Connection这些连接是独立于JVM的,对于ResultSet 和Statement对象可以不进行显示回收,但Connection一定要显示回收,因为Connection在任何时候都无法自动回收,而Connection一旦回收,ResultSet和Statement就会立即为null。但是如果使用的是连接池的情况就不一样,处了要显示关闭连接,还要显示关闭ResultSet和Statement对象

  • 单例模式:因为单例对象初始化后将在JVM的整个生命周期内存在,如果它持有一个外部对象的引用,那么这个外部对象就不能被回收,从而导致内存泄漏。如果这个外部对象还持有其他对象的引用,那么泄露更严重

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics