【JVM】如何理解强引用、软引用、弱引用、虚引用?
【JVM】如何理解强引用、软引用、弱引用、虚引用?
整体架构
强引用
强引用是默认支持,当内存不足的时候,JVM开始垃圾回收,对于强引用的对象,就算是出现了OOM也不会回收对象。
强引用是最常见的普通对象引用,只要还有强引用指向对象,对象就存活,垃圾回收器不会处理存活对象。一般把一个对象赋给一个引用变量,这个引用变量就是强引用。当一个对象被强引用变量所引用,它就处于可达状态,是不会被垃圾回收的,即使之后都不会再用到了,也不会回收。因此强引用是造成Java内存泄漏的主要原因之一。
关于Java内存泄漏的详细内容,可以参考这篇博客:https://blog.csdn.net/m0_38110132/article/details/81986334。
对于一个普通对象,如果没有其他引用关系,只要超过了引用的作用域或者显式地将相应的强引用赋值为null,一般认为就是可以被垃圾回收了。(具体的回收时机看垃圾回收策略)
下例中,b就是强引用。
1 public static void main(String[] args) {
2 Object a = new Object();
3 Object b = a;
4 a = null;
5 System.out.println(b);//java.lang.Object@4554617c
6 }
软引用
软引用是一种相对强引用弱化了一些的引用,用java.lang.ref.SoftReference实现,可以让对象豁免一些垃圾收集。当系统内存充足的时候,不会被回收;当系统内存不足的时候,会被回收。
软引用一般用于对内存敏感的程序中,比如高速缓存。
1 import java.lang.ref.SoftReference;
2
3 public class SoftReferenceDemo {
4 public static void main(String[] args) {
5 Object a = new Object();
6 SoftReference
使用场景
一个应用需要读取大量的本地图片,如果每次读取都从硬盘读取会严重影响性能,如果一次性全部加载到内存,内存可能会溢出。
可以使用软引用解决这个问题,使用一个HashMap来保存图片路径和图片对象管理的软引用之间的映射关系,内存不足时,JVM会自动回收缓存图片对象的占用空间,有效地避免了OOM(Out Of Memory)问题。
Map> imageCache = new HashMap>
弱引用
弱引用需要用java.lang.ref.WeakReference实现,它比软引用的生存期更短,对于弱引用的对象来说,只要垃圾回收机制一运行,不管JVM的内存空间是否够,都会回收该对象的占用内存。
1 import java.lang.ref.WeakReference;
2
3 public class SoftReferenceDemo {
4 public static void main(String[] args) {
5 Object a = new Object();
6 WeakReference
关于WeakHashMap
1 public static void weakHashMapTest() {
2 Integer key = new Integer(1);
3 String value = "李四";
4 Map weakHashMap = new WeakHashMap();
5 weakHashMap.put(key, value);
6 System.out.println(weakHashMap);//{1=李四}
7 key = null;
8 System.gc();
9 System.out.println(weakHashMap);//{}
10 }
11
12 public static void hashMapTest() {
13 HashMap map = new HashMap<>();
14 Integer key = 1;
15 String value = "张三";
16 map.put(key,value);
17 System.out.println(map);//{1=张三}
18 key = null;
19 System.gc();
20 System.out.println(map);//{1=张三}
21 }
在HashMap中,键被置为null,唤醒gc后,不会垃圾回收键为null的键值对。但是在WeakHashMap中,键被置为null,唤醒gc后,键为null的键值对会被回收。
虚引用
虚引用要通过java.lang.ref.PhantomReference类来实现,虚引用不会决定对象的生命周期,如果一个对象只有虚引用,就相当于没有引用,在任何时候都可能会被垃圾回收器回收。它不能单独使用也不能访问对象,虚引用必须和引用队列联合使用。
虚引用的主要作用是跟踪对象被垃圾回收的状态,仅仅是提供一种确保对象被finalize以后,做某些事情的机制。
PhantomReference的get方法总是返回null,因此无法访问对应的引用对象,设置虚引用关联唯一的目的是在对象被收集器回收的时候收到一个系统通知,或者后续添加进一步的处理。Java允许使用finalize()方法在垃圾回收器将对象从内存中清理出去之前做一些必要的清理工作。【例如实现一个监控对象的通知机制】
引用队列
WeakReference和ReferenceQueue的联合使用效果:
1 public static void weakReferenceTest() {
2 Object a = new Object();
3 ReferenceQueue
PhantomReference和ReferenceQueue的联合使用效果:
1 public static void phantomReferenceTest() {
2 Object a = new Object();
3 ReferenceQueue
总结
强引用:不回收。
软引用:内存不够就回收。
弱引用:一定回收。
虚引用:一定回收,get出来就是null,引用形同虚设,主要和引用队列联合使用,在finalize之前会被放到引用队列中。
与根对象没有引用关系的:引用不可达,一定回收。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Python 四舍五入函数 round
小数位的四舍五入在项目中经常用到。 你可能有注意到 round 函数不能真正做到四舍五入。 round() 函数作用就是,返回浮点数x的四舍五入值。 round( x [, n] ) 简单来说就是在浮点运算的时候丢精度。 这个与计算机系统的设计是有关系的,计算机是使用 2 进制进行计算的的,如果我们常用的数学计算或者科学计算,计算机是会丢精度的。 因此我们的解决方案其实非常简单就是使用 Decimal 来进行数学计算。 浮点计算丢精度的问题不仅仅是 Python 会遇到的问题,Java 、 C/C++ 都会遇到这个问题。 可以考察下面的代码: print(round(2.3, 2))print(round(2.45, 1))print(round(2.675, 2)) print(Decimal(1.325)) print(Context(prec=3, rounding=ROUND_HALF_UP).create_decimal('2.675')) 上面程序的输出为: 2.32.52.671.3249999999999999555910790149937383830547332763...
- 下一篇
谈反应式编程在服务端中的应用,数据库操作优化,从20秒到0.5秒
反应式编程在客户端编程当中的应用相当广泛,而当前在服务端中的应用相对被提及较少。本篇将介绍如何在服务端编程中应用响应时编程来改进数据库操作的性能。 开篇就是结论 利用 System.Reactive 配合 TaskCompelteSource ,可以将分散的单次数据库插入请求合并会一个批量插入的请求。在确保正确性的前提下,实现数据库插入性能的优化。 如果读者已经了解了如何操作,那么剩下的内容就不需要再看了。 预设条件 现在,我们假设存在这样一个 Repository 接口来表示一次数据库的插入操作。 csharp namespace Newbe.RxWorld.DatabaseRepository { public interface IDatabaseRepository { /// <summary> /// Insert one item and return total count of data in database /// </summary> /// <param name="item"></param> ...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS8编译安装MySQL8.0.19
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS关闭SELinux安全模块
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题