精华内容
下载资源
问答
  • 一、Java 虚拟机内存分区、 二、垃圾回收机制、 三、引用计数器算法 ( 无法解决循环引用问题 )、





    一、Java 虚拟机内存分区



    Java 虚拟机内存分区 :

    • 所有线程共有的内存区域 : 堆 , 方法区 ( 元空间 ) ;

      • 方法区 : 存放 静态变量 , 常量 , class 编译后的代码数据 , 永久代对象数据 ( 很少 GC , 永久代的 GC 就是卸载常量池及类型 ) ;
      • 堆 : 存放 创建的 对象实例 , 所有线程共享这个区域 , 堆是 垃圾回收的重点管理区域 ; 有 年轻代 , 老年代 空间 ;
        • 年轻代 : 占整个 堆内存的 1 3 \cfrac{1}{3} 31 的空间 ;
          • Eden 区 : 占 年轻代的 80 % 80\% 80% 空间 ;
          • Survivor 区 : 占年轻代的 20 % 20\% 20% 空间 ;
            • From : 占 年轻代的 10 % 10\% 10% 空间 ;
            • To : 占 年轻代的 10 % 10\% 10% 空间 ;
        • 老年代 : 占整个 堆内存的 2 3 \cfrac{2}{3} 32 空间 ; 老年代又称为永生代 , 只要程序没有 OOM 崩溃 , 这些 对象都是永生的 ; 比较大的对象直接放入老年代 ;
    • 线程私有的内存区域 : 线程栈 , 本地方法栈 , 程序计数器 ; 每个线程都会分配上述 3 个内存区域 ;

      • 虚拟机栈 ( 线程栈 ) : 主要管理 " 栈帧 " , 栈帧 在 线程栈 中也是 后入先出 的 ; 每个栈帧都包含 局部变量表 , 操作数栈 , 动态链接 , 方法出口 , 这四个数据 ;
        • 动态链接 : 每个 " 栈帧 " 都包含一个引用 , 是该引用指向 运行时 , 该 栈帧 对应方法 的引用 ;
        • 局部变量表 : 存放 方法中的 局部变量 ;
        • 操作数栈 : 存放方法执行中的 操作数 , 一般是 0 , 1 , 2 0,1 , 2 0,1,2 个数值 , 很少有其它情况 ;
        • 方法出口 : 记录本方法执行完毕后该执行的下一行 JVM 指令 ;
      • 本地方法栈 : 记录 JNI 执行的栈 ;
      • 程序计数器 : 记录线程执行到哪一行的 JVM 指令 ;




    二、垃圾回收机制



    Java 中 不需要 手动回收 对象内存 , 由 Java 虚拟机 自动执行 ;

    • 好处 : 开发相对简单 ;
    • 坏处 : 不能直接操作内存 ;

    C 语言中 , 自己 malloc 手动申请了内存 , 必须使用 free 手动释放内存 ;


    垃圾回收 的目标 是 垃圾对象 , 主要针对 堆内存 中的空间进行 ;

    垃圾对象 的判断标准 : 没有任何作用的 被废弃的 对象 , 一个对象 没有任何引用 指向它 ;





    三、引用计数器算法 ( 无法解决循环引用问题 )



    引用计数器算法 判定 垃圾对象 : 使用引用计数算法 , 判定一个对象是否是垃圾对象 ;

    为 对象 分配 引用计数器 , 当 有一个引用指向它时 , 引用计数器 + 1 + 1 +1 , 如果有 3 3 3 个引用指向该对象时 , 引用计数器值为 3 3 3 , 如果某个引用失效 , 则 引用计数器 − 1 - 1 1 , 如果对象的全部引用失效 , 则对象的引用计数器值为 0 0 0 , 此时该对象就是 垃圾对象 , 需要被回收 ;

    目前成熟的 Java 虚拟机 没有使用 引用计数器 算法 , 因为 如果 两个对象 仅仅是 互相引用 , 这两个对象的引用计数器 都是 1 1 1 , 但是这两个对象与其余对象没有任何联系 , 这样就导致了 这两个对象所占用的内存 , 永久泄漏了 ;

    引用计数器算法 无解解决 循环引用的问题 , 如果有 2 2 2 个及以上的对象循环引用 , 与程序隔绝 , 造成内存泄漏 , 无法解决 ;

    展开全文
  • 1.垃圾标记阶段算法–引用计数器算法: 2.垃圾标记阶段算法–可达性分析算法: 3.对象的finalization机制: 具体过程:

    1.垃圾标记阶段算法–引用计数器算法:

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述


    2.垃圾标记阶段算法–可达性分析算法:

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述


    3.对象的finalization机制:

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    • 具体过程
      在这里插入图片描述
    展开全文
  • 引用计数器算法:在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻计数器为零的对象就是不可用对象额外占用空间,高效;可达性分析算法:从gc roots ...

    dd8e9b61328b0fb3926c20c6c17f4e9b.png

    一对象回收算法

    JavaGC时判断对象是否存活有两种方式;第一种是引用计数方式,第二种是可达性分析算法

    引用计数器算法

    在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻计数器为零的对象就是不可用对象

    额外占用空间,高效;

    可达性分析算法

    从gc roots 往下搜索,走过的路径称为引用链,如果引用链断开说明对象不可达标记为可回收对象;如果引用链连续说明此对象可达标记为不可回收对象。如图所示,object4,object5,object7都是被标记为可回收对象。

    37fefffb70ea63430182d6061a86f242.png

    jdk1.2版本之前 如果一个对象没有被引用,则无法使用这个对象;jdk1.2版本之后对象被分为4个引用级别,由高到低依次为:强引用软引用弱引用虚引用;开发人员可以利用对象的引用级别灵活控制对象的生命周期。

    d8c8086cf060a3ced239456f446bd74c.png

    二强引用(StrongReference)

    强引用是指引用赋值,即Objecto bj = new Object()。无论任何情况下,只要强引用关系还存在,垃圾收集器就永远不会回收掉被引用的对象。

    如下方式都是强引用

    Object obj = new Object();
    String str = "zszxz";

    如果一个对象具有强引用,不会被垃圾回收器回收。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不回收对象,故通常如果对象不用的时候就需要手动赋值为 null, 方便垃圾回收器回收

    示例

    String str = null;

    当然 通常对象不会手动赋值为null, 只有比较大的对象集合时就需要手动赋值,比如 ArrayList 里面的 clear() 方法。

    public void clear() {
            modCount++;
    ​
            // clear to let GC do its work
            for (int i = 0; i < size; i++)
                elementData[i] = null;
    ​
            size = 0;
        }
    注:养成手动释放内存能提示程序性能

    三软引用(SoftReference)

    软引用是用来描述一些还有用,但非必须的对象。只被软引用关联着的对象,在系统将要发生内存溢出异常前,会把这些对象列进回收范围之中进行第二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常;

    源码:

        // 时间戳,右垃圾回收器更新
        static private long clock;
    ​
        // 时间戳,通过get方法调用更新,选择软引用时将被清除,VM可以使用这个字段,并非必须
        private long timestamp;
    ​
    ​
        public SoftReference(T referent) {// 构造器,给对象注入一个软引用
            super(referent);
            this.timestamp = clock;
        }
    ​
        // 给对象注入一个软引用,并且注入队列
        public SoftReference(T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
            this.timestamp = clock;
        }
    ​
        // 返回对象的引用,如果引用对象已经被清除或者垃圾回收,则返回Null
        public T get() {
            T o = super.get();
            if (o != null && this.timestamp != clock)
                this.timestamp = clock;
            return o;
        }

    如下方式,即使发生gc,只要内存没有溢出就不会回收软引用

    public static void main(String[] args) throws InterruptedException {
            // 给对象注入软引用
            SoftReference<String> reference = new SoftReference<>(new String("zszxz"));
            // zszxz
            System.out.println(reference.get());
            // 调用GC
            System.gc();
            TimeUnit.SECONDS.sleep(5);
            // zszxz
            System.out.println(reference.get());
        }
    适用于缓存场景

    四弱引用(WeakReference)

    当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉被弱引用关联的对象;

    源码:

    public class WeakReference<T> extends Reference<T> {
        
        // 给对象注入弱引用
        public WeakReference(T referent) {
            super(referent);
        }
    ​
        // 给对象注入一个弱引用并注入引用队列
        public WeakReference(T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
        }
    ​
    }

    如下方式,一旦GC调用则会回收对象。

     public static void main(String[] args) throws InterruptedException {
            WeakReference<String> weakReference = new WeakReference<>(new String("zszxz"));
            // zszxz
            System.out.println(weakReference.get());
            // 调用GC
            System.gc();
            TimeUnit.SECONDS.sleep(5);
            // zszxz
            System.out.println(weakReference.get());
        }

    五虚引用(PhantomReference)

    为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知,除此之外没有任何作用,不决定对象的生命周期;

    源码

    public class PhantomReference<T> extends Reference<T> {
    ​
        // 获得引用
        public T get() {
            return null;
        }
    ​
        // 创建虚引用
        public PhantomReference(T referent, ReferenceQueue<? super T> q) {
            super(referent, q);
        }
    ​
    }

    如下示例,即使不调用GC,引用也是为null。

    public static void main(String[] args) throws InterruptedException {
            // 引用队列
            ReferenceQueue queue = new ReferenceQueue();
            PhantomReference reference = new PhantomReference(new String("zszxz"),queue);
            // null
            System.out.println(reference.get());
        }

    六总结

    • 强引用:从来不会被回收
    • 软引用:当内存不足时会被回收
    • 弱引用:正常垃圾回收时回收
    • 虚引用:任何时刻都会被垃圾回收器回收

    关注公众号:知识追寻者 获取原创PDF,面试题

    展开全文
  • 引用计数算法

    2017-10-18 22:43:14
    引用计数算法很多教科书判断对象是否存活的算法是这样的,给对象中添加一个引用计数器,每当有一个地方引用他时,计数器的只就+1;每当引用失效时,计数器的致就-1;任何时刻计数器为0 的对象就是不可能再被使用的。...

    #我的读书笔记
    #####引用计数算法


    很多教科书判断对象是否存活的算法是这样的,给对象中添加一个引用计数器,每当有一个地方引用他时,计数器的只就+1;每当引用失效时,计数器的致就-1;任何时刻计数器为0 的对象就是不可能再被使用的。
    客观的说,引用计数算法的实现简单,判定的效率也很高,在大部分的情况下都是一个不错的算法,但是主流的Java虚拟机中没有选用应用计数法来管理内存,起主要原因是他很难解决对象之间相互引用的问题


    参考 《深入理解Java虚拟机P62》

    展开全文
  • jvm学习一 引用计数器

    2020-04-27 19:17:16
    引用计数器算法算是一种古老的java垃圾回收算法,目前很多版本的java已经废弃掉这种算法了。不过多了解历史解决方案也是很有好处的,通过总结它的优缺点,再与新算法比较,可以帮助更好的理解新算法。 2.算法描述 ...
  • 对象引用计数器

    千次阅读 2017-06-25 20:10:29
    引用计数算法作为垃圾收集器最早的算法,有其优势,也有其劣势,虽然现在的JVM都不再采用引用计数算法...说明该算法】什么是引用计数算法直白一点,就是对于创建的每一个对象都有一个与之关联的计数器,这个计数器记录
  • 31.1.引用计数器算法 引用计数器算法是给每个对象设置一个计数器,当有地方引用这个对象的时候,计数器+1,当引用失效的时候,计数器-1,当计数器为0的时候,JVM就认为对象不再被使用,是“垃圾”了。 引用计数器...
  • java垃圾回收算法之-引用计数器

    千次阅读 2016-05-23 13:55:57
    引用计数器算法算是一种古老的java垃圾回收算法,目前很多版本的java已经废弃掉这种算法了。不过多了解历史解决方案也是很有好处的,通过总结它的优缺点,再与新算法比较,可以帮助更好的理解新算法。 引用计数器...
  • 垃圾回收器算法引用计数器法 微软将运行在公共语言运行时里的代码成为托管代码;但是从更广泛的意义上来说,只要语言提供了自动内存管理功能,我们使用其开发的代码都可以称为托管代码;自动内存管理即我们...
  • 引用计数器

    2017-02-24 21:32:56
    引用计数器概念: 为每个内存对象分配一个...PHP5.2中使用的内存回收算法是 ‘引用计数器算法,当垃圾回收机制运作的时候,将所有计数器为0的内存对象销毁并回收其占用的内存。 在PHP5.3中使用 引用计数系统中的同
  • 前几篇博客我们一起认识了JVM的内存模型(程序计数器、虚拟机栈、本地方法栈、方法区与堆),了解了它们的内存结构与分配,同时也略带提到关于内存的回收。 JVM——内存模型(一):程序计数器 JVM——内存模型...
  • 很多教科书判断对象是否存活的算法是这样的:给对象中添加一个引用计数器,每当有—个地方引用它时,计数器值就加1 ; 当引用失效时,计数器值就减1 ; 任何时刻计数器为0的对象就是不可能再被使用的。 客观地说,引用计数...
  • 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。 引用计数算法(ReferenceCounting)的实现简单,判定效率也很...
  • 引用计数法的思路是,在对象中添加一个引用计数器,当有地方引用这个对象的时候,这个引用计数器的值就加1,当引用失效的时候,这个引用计数器的值就减一。 那么,什么时候是引用失效呢?比如说把那个对象的值...
  • 一、引用计数算法的概述 引用计数算法的实现很简单,其...但是在Java语言中并没有使用引用计数器算法来管理内存,其主要原因是:它很难解决对象之间相互循环引用的问题。 举个简单的例子,请看代码中的testGC方法 :...
  • JVM 知识点整理:GC垃圾收集器判断哪些对象需要回收引用计数器算法可达性分析算法引用还有分类(了解)“缓刑” finalize(了解)开始垃圾收集标记 – 清除算法复制算法标记 – 整理算法分代收集算法HotSpot 算法...
  • 引自知乎 垃圾回收机制中,引用计数法是如何维护所有对象引用的? @Gityuan 的回答 如何区分垃圾。 从一段代码来分析整个过程,并结合模型图来简易讲解,希望能让大家对彻底明白。 先简单说说 Java运行时内存区...
  • 引用计数法的循环引用问题

    千次阅读 2018-10-15 17:13:20
    关于引用计数法,我们可以先看一段wiki上的描述:   As a collection algorithm, reference counting tracks, for each object, a count of the number of references to it held by other objects. If an object...
  • 每当一个地方应用,计数器值就加一,当引用失效的时候,计数器就减一。 优缺点: 效率很高,但是无法解决对象之间互相引用的问题,两个对象互相引用,这样这两个对象就不会消失,这样就导致不能回收了。 2.可达性...
  • 你未必出类拔萃,但一定与众不同 垃圾收集器 垃圾回收需要思考的三件事情: 哪些内存需要回收 什么时候回收 如何回收 首先先判断对象是否死亡 ...给对象添加一个引用计数器,每当有一个地方引用它时,计数.
  • 已知系统为一进程分配的物理块数,进程运行过程中引用的页面号,编程使用LRU算法输出置换的页号、缺页中断次数及缺页率。 2.算法描述 从内存调出一页程序或数据到磁盘的对换区,把选择换出的页面的算法称为页面置换...
  • 引用计数算法在每个对象都维护着一个内存字段来统计它被多少”部分”使用—引用计数器,每当有一个新的引用指向该对象时,引用计数器就+1 ,每当指向该引用对象失效时该计数器就-1 ,当引用数量为0的时候,则说明对象没有...
  • 在对象中加入一个引用计数器,每当有一个地方引用时,计数器值就加1; 当引用计数失效时,计数器值就减1;任何时刻,对象的引用计数未0时, 对象将被回收。 现状 引用计数算法(referenc counting)实现简单,...
  •  对象一旦被使用,计数器会进行+1操作,当对象取消引用计数器-1操作,当为0时被标示为垃圾。此种标示方法的弊端在于已经死亡的对象如果存在相互引用,则会一直占用内存空间,不被回收。此时会导致内存泄漏。为了...
  • 很多教科书判断对象是否存活的算法是这样的:给对象中添加一个引用计数器,每当有一个地方引用他时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。 客观的说,引用...
  • 引用计数算法解析

    2019-12-20 20:40:09
    引用计数算法导语 导语

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 62,170
精华内容 24,868
关键字:

引用计数器算法