JVM内存区域和垃圾回收思想

2018-09-03  本文已影响0人  RealityVibe

前言:

参考:

运行时数据区

谈到JVM的内存管理就必须了解它的运行时数据区,了解下图中各区域的功能和数据存储的类别十分必要。

运行时内存区域

程序计数器

一块较小的内存空间,可以看做当前线程执行的字节码的行号指示器。

Java虚拟机栈

我们常说的将Java内存区理解为“堆”和“栈”,其中所说的栈就是Java虚拟机栈中的局部变量表部分

本地方法区

使用Native方法服务,可以由虚拟机自由实现

Java堆

Java虚拟机中所管理的内存最大的一块,几乎所有的对象实例以及数组都在这里分配内存

方法区

(Non-Heap,非堆)

各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、变量、静态变量、即时编译后的代码等数据

对象存活判断法

如何判断对象已死?

引用计数法

​ 给对象添加一个引用计数器,每个地方引用它时,计数器就加1;当引用失效时,计数器就减1;任何时刻计数器为0的对象视为不能被使用;

public class Ref{
    private Object instance;
    ...
}

public static void main(){
    Ref a = new Ref();
    Ref b = new Ref();
    
    a.instance = b;
    b.instance = a;
    
    a = null; // a引用失效,但是堆中的“a实例”仍然在引用b
    b = null; // b引用失效,但是堆中的“b实例”仍然在引用a
    
    /** 
    * 此时执行GC,虽然a、b引用都已经失效;
    * 但是却在互相引用,无法完成回收
    */
    System.gc(); 
}

可达性分析算法

可达性分析示意图

引用的类型

常见的垃圾回收算法思想

标记—清除算法

标记—清除算法是最基本的收集算法,分为“标记”、“清除”两个阶段。首先,会标记所有需要回收的对象,在标记完成后统一回收所有被标记的对象。

示意图 // TODO
缺陷:

复制算法

复制算法的核心在于将内存分成了容量大小相等的两块,每次只使用其中的一块,当这一块的内存用完时,触发回收,将该半区还存活的对象复制到另一半区,并对它进行整理,不会出现大量不连续的内存碎片;

标记—整理算法

正如标记—清除算法,标记—整理算法也分为对应的两个阶段——“标记”和“整理”;

分代收集算法

目前商业虚拟机的主流收集算法

基于不同的对象的生命周期是不一样的事实,根据对象的存活周期不同,把堆分为新生代和老年代,并根据特点采用不同的收集算法,避免每次回收都会遍历所有存活对象,而导致时间的浪费;

如何触发垃圾回收

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

上一篇 下一篇

猜你喜欢

热点阅读