JAVA垃圾回收算法及原理

本文详细介绍了JAVA垃圾回收的原理,包括引用计数法和可达性分析算法,以及四种引用类型:强引用、软引用、弱引用和虚引用。讨论了垃圾回收算法,如标记清除、标记整理、标记复制和堆区垃圾回收流程。还涵盖了不同的垃圾回收器,如串行、吞吐量优先、响应时间和G1垃圾回收器的工作方式及其特点。最后,文章提及了巨型对象的处理和TLAB策略。
摘要由CSDN通过智能技术生成

如何判断垃圾是否可以回收?

1、引用计数法(早期的Python)

原理:

只要该对象被其他的对象所引用,对象就计数加一,若被引用两次,就计数加二,当引用该对象的变量不再引用该对象的时候,计数减一。当计数为零的时候,代表没有变量对该对象进行引用,最后就会作为垃圾回收。

缺点:

当发生循环引用的时候,当A,B都不再使用的时候,计数仍为一,不会被垃圾回收。

public void buidDog(){
         Dog newDog = new Dog()
         Tail newTail = new Tail();
         newDog.tail = newTail;
         newTail.dog = newDog;
        }

在代码中,newTail中拿着对newDog的引用,newDog中拿着对newTail的引用。若使用引用计数法,则其对象基数都为一,而运行buidDog后,无法进行垃圾回收(引用计数不为零)

 2、可达性分析算法(java)

原理:通过一系列的称为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连(用图论的话说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。

注:GC根本身不是对象,而是对对象的引用。GC根引用的任何对象都将在下一个垃圾收集中自动生存

可以作为GC 根对象的对象

JAVA中有四种主要的根:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象当前正在运行的方法中的局部变量被视为GC根。这些变量引用的对象始终可以通过在声明的方法中立即访问,因此必须保留它们。这些根的生命周期取决于程序的构建方式。在调试生成中,只要方法在堆栈上,局部变量就一直存在。
  • 方法区中的类静态属性引用的对象:它们引用的对象可以由声明它们的类随时访问(如果它们是公共的,则可以由程序的其他部分访问)
  • 方法区中的常量引用的对象
  • 本地方法栈JNI(即一般说的Native方法)中的引用的对象:包括系统的核心进程,同步锁机制(正在加锁的对象)等等

 

 

java的四种引用

1、强引用

沿着根节点GC链可以直接找到。都是强引用。

强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。如下:

 Object o = new Object(); // 强引用 

当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。如果不使用时,要通过如下方式来弱化引用,如下:

 o = null; // 帮助垃圾收集器回收此对象 

显式地设置o为null,或超出对象的生命周期范围,则gc认为该对象不存在引用,这时就可以回收这个对象。具体什么时候收集这要取决于gc的算法。

2、软引用

没有被直接的强引用所引用,在垃圾回收后,内存依然不足,则软引用会被当做垃圾全部回收。如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。

应用:软引用可用来实现内存敏感的高速缓存。比如说图片,视频缓存,浏览器的前进按钮等的

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;

/**
 * 演示软引用, 配合引用队列
 */
public class Demo2_4 {
    private static final int _4MB = 4 * 1024 * 1024;

    public static void main(String[] args) {
        List<SoftReference<byte[]>> list = new ArrayList<>();

        // 引用队列
        ReferenceQueue<byte[]> queue = new ReferenceQueue<>();

        for (int i = 0; i < 5; i++) {
            // 关联了引用队列, 当软引用所关联的 byte[]被回收时,软引用自己会加入到 queue 中去
            SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB], queue);
            System.out.println(ref.get());
            list.add(ref);
            System.out.println(list.size());
        }

        // 从队列中获取无用的 软引用对象,并移除
        Reference<? extends byte
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值