虚拟机-- 垃圾收集 对象 区域 时机

简介: jvm 虚拟机 对象的存活,是否可被回收,回收的区域

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

一、 GC要做的事情

  1. 哪些内存需要回收 ?
  2. 什么时候回收 ?
  3. 如何回收 ?

二、 什么时候需要GC ?

  1. 内存溢出、内存泄漏等;
  2. 垃圾收集收成系统达到更高并发量的瓶颈时。

三、 正文

1 哪些内存需要回收 ?

  1. 基本不考虑

    • 部分: 程序计数器、虚拟机栈、本地方法栈
    • 原因: 在编译期基本确定了内存大小
  2. 主要考虑

    • 部分: Java堆和方法区
    • 原因: 运行期间动态分配内存。

2 什么时候回收 ?

  • 答: 对象已死的时候
    #### 问题来了,如何判断对象已死 ?
  1. 引用计数算法

    • 定义: 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值加1;当引用失效时,计数器值就减1;
         任何时刻计数器为0的对象就是不可能再被使用的。
    • 好处: 实现简单,效率高
    • 缺陷: 很难解决对象之间互相循环引用的问题
  2. 可达性分析算法

    • 定义: 通过一系列的称为 GC Roots 的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用连,
         当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。
    • java中,GC Roots对象

      • 虚拟机栈(栈帧中的本地变量表)中引用的对象
      • 方法区中类静态属性引用的对象
      • 方法区中常量引用的对象
      • 本地方法栈中JNI(即Native方法)引用的对象
  3. 引用

    • 第一和第二种算法判定对象是否存活都与引用有关。
    • JDK 1.2 后,引用有了新的定义,以下顺序引用由强变弱

      • 强引用(Strong Reference)

      Object obj = new Object(); 程序中类似这样的就是强引用。

      • 软引用(Soft Reference)

      软引用关联的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进 回收范围之中进行第二次回收;

      • 弱引用(Weak Reference)

      弱引用关联的对象,只能生存到下一次垃圾收集发生之前。

      • 虚引用(Phantom Reference)

      虚引用存在的唯一意义: 在对象被回收的时候,收到一个系统通知;

    • 补充:

      • 强引用是普遍存在。
      • 软引用和弱引用都是用来描述非必须的对象
      • 虚引用又称为幽灵引用或者幻影引用。
  4. 生存还是死亡 ?

    • 需要注意的是,通过可达性分析算法得到的不可达的对象,也不是非死不可的。
    • 一个对象的死亡,至少经历两次标记过程:

      • 1 可达性分析不可达的对象,被第一次标记并且进行一次筛选

        • 筛选的条件:此对象是否有必要执行finalize()方法,,虚拟机将以下两种情况都视为 没有必要执行。

          • 1 对象没有覆盖finalize()方法;
          • 2 finalize()方法已经被虚拟机调用过
      • 2 筛选被判定有必要执行finalize()方法,进入 F-Queue的队列,等待被线程执行该方法。

        • 线程: 虚拟机自动创建的、优先级低的Finzlizer线程。
        • 执行:所谓的执行是指虚拟机会触发这个方法,但不会一直等待它运行结束。

          • 原因:如果对象在Finzlize()方法中执行缓慢 或 发生死循环;可能导致F-queue队列中其他对象
               永远处于等待,甚至导致整个内存回收系统崩溃。
    • finalize() 方法是对象逃脱死亡命运的最后一次机会,稍后GC将对F-Queue中的对象进行第二次小规模的标记

      • 如果对象重新与引用链上的任何一个对象建立关联,(例如: 对象把自己的值 -赋值给某个类的变量或对象的成员变量),移出即将回收的集合;
      • 如果对象没有移出回收的集合,基本上确定了被回收。
    • 任何一个对象的finalize()方法只会被系统自动调用一次。
    • finalize(): 运行代价高昂,不确定性大,无法保证各个对象的调用顺序。
    • 使用 try-finally 完全可以替代 finalize()方法。
  5. 回收方法区

    • 方法区(HotSpot虚拟机中的永久代)
    • java 虚拟机规范中,不要求在方法区进行垃圾收集。 因为收集性价比比较低。

      • 堆新生代中,一次垃圾回收可以回收 70%- 95%的空间。
      • 永久代(方法区) 收集效率远低于此。
    • 永久代的垃圾收集分为两部分:

      • 废弃常量

        • 定义: 回收废弃常量与回收Java堆中的对象类似。
        • 判断依据: 常量池中的字面量的回收为例, 一个字符串”a“在常量池中,当前系统中没有String对象是"a",也没有其他
          地方引用这个字面量,这时候如果发生内存回收,没有必要的话,这个“a”常量会被系统清理出常量池。
        • 常量池中的其他类(接口)、方法、字段的符号引用也与此类似。

      • 无用的类

        • 判断依据:

          • 该类所有的实例已经被回收,换句话说就是Java堆中不存在该类的任何实例。
          • 加载该类的ClassLoader已经回收。
          • 该类对应的java.lang.class对象没有在任务地方被引用,无法在任何地方通过反射访问该类的方法。
        • 虚拟机可以对满足上述三个条件的对象进行回收,不是必然的。
    • 大量使用反射、动态代理、CGLib 等ByteCode框架、动态生成JSP以及OSGj这类频繁自定义ClassLoader的场景都需要虚拟机具备类卸载的功能,以保证永久代不会溢出。

欢迎访问:

github中更多笔记

相关文章
|
4月前
|
存储 安全 Java
JavaSE高级篇:HotSpot虚拟机对象探秘
JavaSE高级篇:HotSpot虚拟机对象探秘
|
存储 算法 安全
JVM:HotSpot虚拟机----对象的创建简单介绍及对象内存布局详解
JVM:HotSpot虚拟机----对象的创建简单介绍及对象内存布局详解
146 0
JVM:HotSpot虚拟机----对象的创建简单介绍及对象内存布局详解
|
10月前
|
存储 算法 Java
HotSpot 虚拟机对象探秘
HotSpot 虚拟机对象探秘
78 0
|
11月前
|
存储 算法 Java
JVM-02内存区域与内存溢出异常(中)【hotspot虚拟机对象】
JVM-02内存区域与内存溢出异常(中)【hotspot虚拟机对象】
43 0
|
11月前
|
存储 算法 安全
深入理解JVM虚拟机 - jvm的对象分配策略
​ JVM的对象分配策略是面试的中经常会碰到的点,也是学习和了解虚拟机必须迈过的一个坎。本文并不是单纯的总结书中的内容,在个人针对书中的案例进行实验的时候,发现结果居然和书中的结果不匹配,所以抽了不少时间专门研究了一下这一块,下面根据个人的学习和总结来描述一下个人对于JVM对象分配策略的解读。
178 0
|
存储 Java
HotSpot虚拟机对象探秘
HotSpot虚拟机对象探秘
69 0
|
存储 安全 Java
Java虚拟机对象分配策略
Java虚拟机对象分配策略
|
存储 算法 Java
聊聊ART虚拟机_对象的分配问题
ART 虚拟机(下图 Runtime 层),相信各位搞 Android 开发的同学都有知道,总体的印象呢就是:ART 与 JVM 不同,其不符合 JVM 规范不属于 JVM ,且为 Dalvik 的进阶版。
聊聊ART虚拟机_对象的分配问题
|
存储 缓存 算法
聊聊ART虚拟机_对象的使用和销毁问题
在上一篇文章中,我们聊到了对象的分配问题,简单说明了何为 ART 虚拟机,以及对象中类的加载、内存布局等问题。本文继接上文,将会讲完对象的使用和销毁的问题,希望本文对你有所帮助。
聊聊ART虚拟机_对象的使用和销毁问题
|
存储 缓存 安全
探索HotSpot虚拟机对象的奥秘
之前探讨了Java虚拟机内存模型的概况,了解了内存中到底都放了些什么数据,那它们是如何创建、如何布局以及如何访问的呢,下面来探讨一下HotSpot虚拟机在Java堆中对象分配、 布局和访问的全过程。

热门文章

最新文章