0%

垃圾收集器与内存分配策略(1)

垃圾收集器与内存分配策略(1)


序言

Java和C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人想出来

GC(Garbage Collection)

学习目的

  • 解决问题

    • 内存溢出、泄漏
    • GC成了性能瓶颈

GC区域

无关紧要的

  • 与线程同生共死

    分配内存时大致内存是确定的,方法或线程结束,内存自动回收,所以整个生命周期内存是比较确定的,没什么好说的。GC主要关注java堆(又称gc堆)

    • 程序计数器
    • 虚拟机栈
    • 本地方法栈

至关重要的

  • Java堆

    主要存放对象的 实例。

    • 内存动态分配
    • 内存动态回收

找垃圾算法

回收之前要确定对象是死是活(未来还会用到吗)

引用计数算法

有一个人引用计数就加1,少一个人引用计数就减1

  • 优点

    • 立即执行

      计数为0就可以立即回收了

    • 自我诊断

      没必要再去new一个线程,是否可以回收自己就可以判断。

  • 缺点

    因为致命缺陷jvm不用这个

    • 计数本身有一定的工作量

    • 循环引用,形成永动

      两个变量互相引用是无解(无法回收)的

根搜索算法

有一些特殊的对象可以作为gc root,从gc root出发,能到达之处就不是垃圾,不能到达之处就是垃圾

引用

上古时代的定义

  • 存储着另一块内存的起始地址的变量

分类

  • 强引用

    Strong

    • Object obj = new Object()
    • 只要引用存在,就不会被回收
  • 软引用

    Soft

    • 内存溢出之前会把软引用的对象回收,如果没用就报错了
    • 通过SoftReference实现软引用
  • 弱引用

    Weak

    • 比软引用更容易被回收
    • 朝生暮死(下次回收开始弱引用必死)
    • 通过WeakReference实现弱引用
  • 虚引用

    Phatom

    • 唯一用处是对象被回收时能收到一个系统通知
    • 通过PhatomReference实现虚引用

生存还是死亡

根搜索算法之后并未宣判死刑,对象仍有一线生机

两次标记

  • 第一次标记

    • finalize方法

      这个方法时java对c\c++程序员作出的妥协,这方法已经不适合这个版本了,应该被gc

      • 对象自我救赎的最后一次机会

        这个方法只可能被调用一次

  • 第二次标记

    • 如果对象救赎成功,就不会被标记,否则只有死路一条

回收方法区

回收废弃常量和无用的类

性价比低,可以不gc

垃圾收集算法

标记-清除算法

  • 过程

    • 标记

      • 找垃圾算法
    • 清除

  • 缺点

    • 效率不行
    • 碎片太多,可能找不到大的连续的内存空间
  • 地位

    • 基石

      • 之后的算法都是改进版

复制算法

  • 过程

    • 设置保留区,内存不够用时将所有活着的移到保留区,再清除

      50%-50%会减少一半的可用内存,代价太大,而且也不需要如此。90%-10%又没法交换,所以一般是三部分:80%-10%-10%,只有一个10%是闲置的

    • 分配担保

  • 优势

    • 简单易行
  • 缺点

    • 牺牲部分内存
    • 对象比较多时复制操作会比较多

标记-整理算法

  • 过程

    • 标记

    • 整理

      • 把活着的拼接到一起
    • 清除

分代收集算法

  • 内存划分

    • 新生代

      • 新生代每次存活数量少,选复制算法
    • 老生代

      • 存活率高,使用标记-整理