【转】Java高级进阶学习-Java的内存回收(3)

本文详细介绍了Java中垃圾回收机制与弱引用、软引用、虚引用的区别及使用方式,通过实例展示了如何利用这些引用类型进行内存管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(3)弱引用
  弱引用与软引用有点相似,区别在于弱引用所引用对象的生存期更短。弱引用通过WeakReference类实现,弱引用和软引用很像,但弱引用的引用级别更低。对于只有弱引用的对象而言,当系统垃圾回收机制运行时,不管系统内存是否足够,总会回收该对象所占用的内存。当然,并不是说当一个对象只有弱引用时,它就会立即被回收,正如那些失去引用的对象一样,必须等到系统垃圾回收机制运行时才会被回收.

下面程序示范了弱引用所引用对象也会被系统垃圾回收的过程.
import java.lang.ref.*;
import java.util.*;
public class WeakReferenceTest
{
public static void main(String[] args) throws Exception
{
//创建一个字符串对象
String str = new String("网络时空");
//创建一个弱引用,让此弱引用引用到"网络时空"字符串
WeakReference<String> wr = new WeakReference<String>(str); //①
//切断str引用和"网络时空"字符串之间的引用
str = null; //②
//取出弱引用所引用的对象
System.out.println(wr.get()); //③

List<String> list=new ArrayList<String>();
list.add(wr.get());

//强制垃圾回收
System.gc();
System.runFinalization();
//再次取出弱引用所引用的对象
System.out.println(wr.get()); //④
}
}

运行结果如下

Java高级进阶学习-Java的内存回收(3)

 

说明如下
上面程序创建了一个“网络时空”的字符串对象,并让str引用变量引用它。执行①行处代码时,系统创建了一个弱引用对象,并让该对象和str引用同一个对象。当程序执行到②行代码时,切断了str和"网络时空"字符串对象之间的引用关系,此时系统图如下所示
内存中分布效果图如下

Java高级进阶学习-Java的内存回收(3)


  从此内存中图示可以看出,此时“网络时空”字符串对象只有一个弱引用对象引用它,程序依然可以通过这个弱引用对象来访问字符串常量,程序中③行代码依然输出“网络时空”,接下来程序强制垃圾回收,如果系统垃圾回收机制启动,只有弱引用的对象就会被清理掉。当程序执行④行代码时,通常就会看到输出null,这表明该对象已经被清理掉了

总结说明:

1.弱引用具有很大的不确定性,因为每次垃圾回收机制执行时都会回收弱引用所引用的对象,而垃圾回收机制的运行又不受程序员的控制,因此程序获取弱引用所引用的java对象时必须小心空指针异常,通过弱引用所获取的java对象可能是null

2.由于垃圾回收的不确定性,当程序希望从弱引用中取出被引用对象时,可能这个被引用对象已经被释放了。如果程序需要使用被引用的对象,则必须重新创建该对象,这个可能可以采用如下风格的代码完成。

伪码形式表示如下

//取出弱引用所引用的对象

obj=wr.get();

//如果取出的对象为null

if(obj==null)

{

  //重新创建一个新的对象,将其使用强引用来引用它

obj=recreateIt();

//取出弱引用所引用的对象,将其赋给wr变量

wr=new WeakReference(obj);

}

...//操作obj对象

//再次切断obj和对象之间的关联

obj=null;

 

 

(4)虚引用
  软引用和弱引用可以单独使用,但虚引用不能单独使用,单独使用虚引用没有太大的意义。虚引用的主要作用就是跟踪对象被垃圾回收的状态,程序可以通过检查虚引用关联的引用队列中是否包含指定的虚引用,从而了解虚引用所引用的对象是否将被回收.
  引用队列由java.lang.ref.ReferenceQueue类表示,它用于保存被回收对象的引用。当把软引用,弱引用和引用队列联合使用时,系统回收被
引用的对象之后,将会把被回收对象对应的引用添加到关联的引用队列中。与软引用和弱引用不同的是,虚引用在对象被释放之前,将把它对应的虚引用添加到关联的队列中,这使得可以在对象被回收之前采取行动。
虚引用通过PhantomReference类实现,它完全类似于没有引用。虚引用对对象本身没有大的影响,对象甚至感觉不到虚引用的存在。如果一个
对象只有一个虚引用,那它和没有引用的效果大致相同。虚引用主要用于跟踪对象被垃圾回收的状态,虚引用不能单独使用,虚引用必须和队列ReferenceQueue联合使用.

  下面程序与上面程序基本类似,只是使用了虚引用来引用字符串对象,虚引用无法获取它引用的对象,下面程序还将和引用队列结合使用,可以看到,被虚引用所引用对象被垃圾回收后,虚引用将被添加到引用队列中。

import java.lang.ref.*;
public class PhantomReferenceTest
{
public static void main(String[] args)
throws Exception
{
//创建一个字符串对象
String str = new String("网络时空");
//创建一个引用队列
ReferenceQueue<String> rq = new ReferenceQueue<String>();
//创建一个虚引用,让此虚引用引用到"网络时空"字符串
PhantomReference<String> pr =
new PhantomReference<String>(str , rq);
//切断str引用和"网络时空"字符串之间的引用
str = null;
//试图取出虚引用所引用的对象,
//程序并不能通过虚引用访问被引用的对象,所以此处输出null
System.out.println(pr.get()); //①
//强制垃圾回收
System.gc();
System.runFinalization();
//取出引用队列中最先进入队列中引用与pr进行比较
System.out.println(rq.poll() == pr); //②
}
}

Java高级进阶学习-Java的内存回收(3)

 

  因为系统无法通过虚引用来获得被引用的对象,所以执行①处的输出语句,程序将输出null(即使此时未进行强制垃圾回收)。当程序强制垃圾回收后,只有虚引用引用的字符串对象将会被垃圾回收,当被引用的对象被回收后,对应引用将被添加到关联的引用队列中,因而将在②处代码处看到输出true.

 

基于Spring Boot搭建的一个多功能在线学习系统的实现细节。系统分为管理员和用户两个主要模块。管理员负责视频、文件和文章资料的管理以及系统运营维护;用户则可以进行视频播放、资料下载、参与学习论坛并享受个性化学习服务。文中重点探讨了文件下载的安全性和性能优化(如使用Resource对象避免内存溢出),积分排行榜的高效实现(采用Redis Sorted Set结构),敏感词过滤机制(利用DFA算法构建内存过滤树)以及视频播放的浏览器兼容性解决方案(通过FFmpeg调整MOOV原子位置)。此外,还提到了权限管理方面自定义动态加载器的应用,提高了系统的灵活性和易用性。 适合人群:对Spring Boot有一定了解,希望深入理解其实际应用的技术人员,尤其是从事在线教育平台开发的相关从业者。 使用场景及目标:适用于需要快速搭建稳定高效的在线学习平台的企业或团队。目标在于提供一套完整的解决方案,涵盖从资源管理到用户体验优化等多个方面,帮助开发者更好地理解和掌握Spring Boot框架的实际运用技巧。 其他说明:文中不仅提供了具体的代码示例和技术思路,还分享了许多实践经验教训,对于提高项目质量有着重要的指导意义。同时强调了安全性、性能优化等方面的重要性,确保系统能够应对大规模用户的并发访问需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值