JVM垃圾回收(Hotspot)

  1. 方法区中常量引用的对象

  2. 本地方法栈中JNI(Native方法)引用的对象

  3. Java虚拟机内部的引用

  4. 同步锁持有的对象

总结一下GC Roots的特点:就是被堆外直接引用的堆内对象

跨代引用

Hotspot堆内存是分代的,所以可能出现跨代引用,被跨代引用的堆对象其实也算是一种GC Root。

比如上面A,X,Y都是堆外直接引用的堆内对象,是常规的GC Root

但是B作为新生代对象,他没有被堆外直接引用,但是却被老年代对象X引用了(跨代引用),而老年代X是GC Root,所以B不是垃圾。

但是分代垃圾回收可以只对新生代进行回收(Minor GC),而垃圾回收前,需要查找被垃圾回收内存区域的GC Root,如果只考虑堆外直接引用堆内对象为GC Root的话,那么只有A是GC Root,B是垃圾。但是实际上B不是垃圾,所以我们可以将 代外直接引用的代内对象 也当成一种“分代级别”的GC Root.

那么上面这种情况,B是否就是垃圾了?

整体来看,B确实是垃圾。但是如果只有新生代发生垃圾回收的话,B还是不会被回收,即B不会被当成垃圾。只有X被回收了,B才会被回收。所以我们可以将 代外直接引用的代内对象 也当成代GC Root.

如果存在上面这种情况,X也存在跨代引用,则X也不能被当成垃圾。

如果发生上面这种情况,整体来看B,X都是垃圾,如果只发生老年代的垃圾回收(Majar GC),则X不会被垃圾回收。这样其实就造成了空间浪费。所以在回收老年代前,通常回收一次新生代,这样B就会被回收,之后X也会被回收。

可达性分析算法

从GC Roots(根对象)开始,根据引用关系向下搜索,搜索过程所走过的路径称为”引用链“,如果某个对象到GC Roots间没有任何引用链,则该对象可以判定为垃圾。

优点:两个对象相互引用时,也能被识别为垃圾。不需要对象保存引用计数信息。

缺点:当GC Roots数量过多时,该算法耗时较长。

Java中的四种引用


强引用(Strong Reference)

当对象被一个或一个以上的引用变量引用时,它处于可达状态,不可能被垃圾回收。

软引用(Soft Reference)

软引用需要通过SoftReference类来实现,当一个对象只有软引用时,它有可能被垃圾回收机制回收。对于只有软引用的对象而言,当系统内存足够时,它不会被系统回收,程序也可使用该对象;当系统内存不足时,系统可能会回收它。软引用通常用于对内存敏感的程序中。

// java -Xmx10m Main

public class Main {

public static void main(String[] args) {

soft();

}

private static void soft(){

SoftReference<byte[]> sf = new SoftReference<>(new byte[1024 * 1024 * 6]);

System.out.println(“======”);

SoftReference<byte[]> sf1 = new SoftReference<>(new byte[1024 * 1024 * 6]);

System.out.println(“======”);

System.out.println(sf.get());//null

System.out.println(sf==null);//false

System.out.println(sf1.get());//[B@1b6d3586

}

}

当一次Full GC后,堆内存任然不足时,会再次进行一次Full GC,将new byte[1024 * 1024 * 6]对象所占内存回收。

此时只剩下软引用对象new SoftReference(),因为它被sf强引用,所以无法被垃圾回收。

此时我们可以通过以下方式回收软引用对象new SoftReference()

if(sf.get()==null){

sf = null;

}

也可以借助另一种方式,SoftReference对象本身可以绑定一个引用队列ReferenceQueue对象,当软引用指向的对象被回收了,则软引用会被自动加入绑定的引用队列中。这种情况适用于要回收的软引用对象较多时。

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 Main {

public static void main(String[] args){

soft();

}

private static void soft(){

ReferenceQueue<byte[]> queue = new ReferenceQueue<>();

List<SoftReference<byte[]>> list = new ArrayList<>();

list.add(new SoftReference<>(new byte[1024 * 1024],queue));

list.add(new SoftReference<>(new byte[1024 * 1024 * 2],queue));

list.add(new SoftReference<>(new byte[1024 * 1024 * 3],queue));

list.add(new SoftReference<>(new byte[1024 * 1024 * 6],queue));

Reference<? extends byte[]> poll = queue.poll();

while (poll!=null){

list.remove(poll);

poll = queue.poll();

}

System.out.println(list.size());// 1

list.forEach(t-> System.out.println(t.get()));// [B@404b9385

}

}

弱引用(Weak Reference)

弱引用需要通过WeakReference类来实现,弱引用和软引用很想,但弱引用级别更低。对于只有弱引用的对象而言,当系统垃圾回收机制运行时,不管系统内存是否足够,总会回收该对象所占用的内存。

弱引用具体使用和软引用差不多,只是二者引用对象的回收时机不一样,只要发生垃圾回收,无论内存是否充足,都会回收弱引用引用的对象。

虚引用(Phantom Reference)

虚引用通过PhantomReference类实现,虚引用完全类似于没有引用。虚引用对对象本身没有太大影响,对象甚至感觉不到虚引用的存在。如果一个对象只有虚引用时,那么它和没有引用的效果大致相同。虚引用主要用于跟踪对象被垃圾回收的状态,虚引用不能单独使用,虚引用必须和引用队列联合使用。

虚引用引用的对象不会因为内存不足而被垃圾回收,虚引用引用的对象和没有虚引用引用的对象效果相同。即虚引用并不是为了应对内存紧张场景。

虚引用必须配合引用队列使用,因为虚引用引用的对象无法通过get()获取,所以无法判断虚引用引用的对象是否已经被回收。只能通过检查是否虚引用本身是否入队,若入队,则说明虚引用引用的对象已经被回收。

由于虚引用引用的对象被回收后,会自动入队,所以只要检查队中是否有虚引用就可以跟踪对象被垃圾回收的状态。

public class Main {

public static class Test{

@Override

protected void finalize() throws Throwable {

System.out.println(“finalize方法被调用”);

super.finalize();

}

}

public static void main(String[] args){

phantom();

}

private static void phantom(){

ReferenceQueue queue = new ReferenceQueue<>();

Test test = new Test();

PhantomReference pr = new PhantomReference<>(test, queue);

test = null;

while (true){

Reference<? extends Test> poll = queue.poll();

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
1715549110971)]

[外链图片转存中…(img-UcPbjlsP-1715549110971)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值