【JVM】垃圾收集器

程序计数器、Java虚拟机栈、本地方法栈分配的内存是确定的,生命周期与线程同样。所以不须要过多考虑回收问题。

而Java堆和方法区仅仅有运行时才知道有哪些对象被创建,须要多少内存,这部分的内存分配和回收是动态的。

1. 检測垃圾内存的方法

1) 引用计数器

给对象加入引用计数器,有地方引用时+1,引用失效时-1。不论什么时刻计数器为0的对象就是不可能在被使用的。可是!

不能解决对象间互相引用的问题,所以主流虚拟机不用这种方法。

2) 可达性分析算法

通过一系列称为”GCRoots”的对象作为起始点,開始向下搜索,走过的路径称为引用链,当一个对象到GCRoots没有不论什么引用链相连时,则该对象不可用。
可作为GCRoots的对象包含:

  • 虚拟机栈中引用的对象
  • 方法区中类静态属性应用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI引用的对象

2. 对象死亡过程

至少要经历两次标记过程:

  • 可达性分析后不可达的对象被第一次标记而且进行一次筛选,筛选条件是对象是否有必要运行finalize()方法。当对象没有覆盖finalize()方法或者已经调用过,则没有必要运行。对象会被放进”即将回收”集合;有必要运行的对象会被放在一个叫F-Queue的队列中,会由自己主动建立的低优先级的Finalizer线程去触发,但不保证能运行结束。
  • 在finalize()方法中对象将自己与引用链上的不论什么一个对象关联起来,则GC在F-Queue中进行第二次小规模标记时,这些对象会被移出回收集合。所以运行finalize()的对象不一定会被回收。 不论什么对象的finalize()方法仅仅能被调用一次,所以第一次逃脱后第二次将无法逃脱。

3. 回收方法区

主要回收废弃常量和没用的类。

  • 废弃常量:没有其它地方被引用到的常量。
  • 没用的类:满足3个条件即能够回收而并不一定:

  • 该类的全部实例都被回收

  • 载入该类的ClassLoader已经被回收
  • 该类相应的Class对象没有在不论什么地方被引用

4. 垃圾收集算法

1) “标记-清除”算法:

【JVM】垃圾收集器
不足:
  • 效率问题。标记和清除过程的效率都不高。
  • 空间问题。产生大量不连续的碎片,导致载入较大对象时要提前出发下一次垃圾收集过程。
    [En]

    Space problems. Produce a large number of discontinuous fragments, resulting in the loading of larger objects to start the next garbage collection process in advance.*

2) 复制算法

将内存分为相等大小的两块。每次仅仅使用当中一块。当一块用完时将活着的对象拷贝到还有一块上面。然后一次清除使用过的那块内存。

[En]

Divide the memory into two blocks of equal size. Use only one piece at a time. Copy the living object to the other piece when one piece is used up. Then clear the used piece of memory at once.

【JVM】垃圾收集器
长处:仅仅要移动堆顶指针。按顺序分配内存就可以。实现简单。运行高效。
[En]

Strength: just move the top pointer. Just allocate memory sequentially. It is easy to implement. It runs efficiently.

缺点:内存缩小为原来的一半。在对象存活率高的时候不适用,适合新生代。

[En]

Cons: the memory has been reduced to half of its original size. It is not applicable when the survival rate of the object is high, so it is suitable for the new generation.

IBM策略:採用一个较大的Eden空间(80%)和两个较小的Survivor空间(10%),每次使用Eden和一个Survivor。

3) “标记-整理”算法:

适用于老年代,标记后让全部存活的对象都向一端移动。然后直接清理掉端边界以外的内存。

[En]

Suitable for the old days, marking allows all living objects to move to one end. Then clean up the memory outside the end boundary directly.

【JVM】垃圾收集器

4) 分代收集算法:

将Java堆分为新生代和老年代。依据各个年代的特点採用最适合的收集算法。

5. 内存分配与回收策略

  • 对象优先在新生代的Eden分配
  • 大对象直接进入老年代(非常长的字符串、数组….)
  • 长期存活的对象进入老年代。每一个对象都有一个年龄计数器。在Eden中出生并经历第一次GC,存活后能被Survivor容纳,则年龄置为1,每在Survivor中熬过一次GC,年龄+1。年龄增大到一定程度(默认15)则会被晋升到老年代。

Original: https://www.cnblogs.com/mfmdaoyou/p/7400971.html
Author: mfmdaoyou
Title: 【JVM】垃圾收集器

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/81676/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

最近整理资源【免费获取】:   👉 程序员最新必读书单  | 👏 互联网各方向面试题下载 | ✌️计算机核心资源汇总