您当前的位置:首页 > 互联网教程

Java中的几种引用方式

发布时间:2025-05-16 10:48:34    发布人:远客网络

Java中的几种引用方式

一、Java中的几种引用方式

Java中有几种不同的引用方式,它们分别是:强引用、软引用、弱引用和虚引用。下面,我们首先详细地了解下这几种引用方式的意义。强引用在此之前我们介绍的内容中所使用的引用都是强引用,这是使用最普遍的引用。如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。软引用(SoftReference)SoftReference类的一个典型用途就是用于内存敏感的高速缓存。SoftReference的原理是:在保持对对象的引用时保证在 JVM报告内存不足情况之前将清除所有的软引用。关键之处在于,垃圾收集器在运行时可能会(也可能不会)释放软可及对象。对象是否被释放取决于垃圾收集器的算法以及垃圾收集器运行时可用的内存数量。弱引用(WeakReference)WeakReference类的一个典型用途就是规范化映射(canonicalized mapping)。另外,对于那些生存期相对较长而且重新创建的开销也不高的对象来说,弱引用也比较有用。关键之处在于,垃圾收集器运行时如果碰到了弱可及对象,将释放 WeakReference引用的对象。然而,请注意,垃圾收集器可能要运行多次才能找到并释放弱可及对象。虚引用(PhantomReference)PhantomReference类只能用于跟踪对被引用对象即将进行的收集。同样,它还能用于执行 pre-mortem清除操作。PhantomReference必须与 ReferenceQueue类一起使用。需要 ReferenceQueue是因为它能够充当通知机制。当垃圾收集器确定了某个对象是虚可及对象时,PhantomReference对象就被放在它的 ReferenceQueue上。将 PhantomReference对象放在 ReferenceQueue上也就是一个通知,表明 PhantomReference对象引用的对象已经结束,可供收集了。这使您能够刚好在对象占用的内存被回收之前采取行动。Reference与ReferenceQueue的配合使用。 GC、Reference与ReferenceQueue的交互 A、 GC无法删除存在强引用的对象的内存。 B、 GC发现一个只有软引用的对象内存,那么:① SoftReference对象的referent域被设置为null,从而使该对象不再引用heap对象。② SoftReference引用过的heap对象被声明为finalizable。③当heap对象的 finalize()方法被运行而且该对象占用的内存被释放,SoftReference对象就被添加到它的 ReferenceQueue(如果后者存在的话)。 C、 GC发现一个只有弱引用的对象内存,那么:① WeakReference对象的referent域被设置为null,从而使该对象不再引用heap对象。② WeakReference引用过的heap对象被声明为finalizable。③当heap对象的finalize()方法被运行而且该对象占用的内存被释放时,WeakReference对象就被添加到它的ReferenceQueue(如果后者存在的话)。 D、 GC发现一个只有虚引用的对象内存,那么:① PhantomReference引用过的heap对象被声明为finalizable。② PhantomReference在堆对象被释放之前就被添加到它的ReferenceQueue。值得注意的地方有以下几点:1、GC在一般情况下不会发现软引用的内存对象,只有在内存明显不足的时候才会发现并释放软引用对象的内存。 2、GC对弱引用的发现和释放也不是立即的,有时需要重复几次GC,才会发现并释放弱引用的内存对象。 3、软引用和弱引用在添加到ReferenceQueue的时候,其指向真实内存的引用已经被置为空了,相关的内存也已经被释放掉了。而虚引用在添加到ReferenceQueue的时候,内存还没有释放,仍然可以对其进行访问。

二、java 中的引用是什么意思

1、在java实现某个功能的时候,会将类实例化成对象,然后jvm再对实例化后的对象进行操作。

2、实例化后的对象可以赋值,也可以引用。赋值时,java会开辟一个新的地址用于存放变量,而引用则不开辟地址。

3、将String类实例化成对象a与b,并赋值

4、将c指向new出来的String型对象"a"

5、由于a与b都为对象赋值,打印出来的结果应该是true

6、而c是引用对象“a”,所以打印出来的结果应该是false

7、引用:对象的别名,使用该别名可以存放该对象,编译器不会为引用分配空间,新对象与源对象共用一个存储地址空间;引用的生命周期是它所引用的对象的生命周期,函数里返回一个局部对象的引用是很危险的

8、给你推荐一种最简单的理解方式:引用就好比是给商品贴的标签,你通过标签可以拿到这个商品.......我开始就是这么理解的,后来用多了就意会啦.....

三、Java中符号引用和直接引用

类从加载到内存,到从JVM中卸载共经历7个阶段,加载、验证、准备、解析、初始化、使用和卸载。在解析阶段,符号引用会被转换为直接引用。符号引用和直接引用是Java类加载过程中的关键概念。接下来,让我们深入探讨它们各自的特点。

解析阶段是类加载过程中的重要环节。在这一阶段,JVM会将符号引用转换为直接引用。符号引用是类加载过程中的一种引用方式,它使用一组符号表示要引用的目标,这些符号可以是类名、字段名、方法名等。符号引用的目标可能位于类的代码中,也可能存在于其他资源中,如其他类、接口、方法或者字段。

在类的常量池中,常量池可以看作是.class文件的资源仓库,也是与其他项目关联最多的数据类型之一。常量池中主要存放两类常量:字面量和符号引用。字面量包括字符串、final定义的常量值等。符号引用则包含了类和接口的全限定名、字段的名称和描述符、方法的名称和描述符等信息。

符号引用与直接引用的区别在于引用的具体实现。符号引用是一组符号表示的目标引用,而直接引用则是指向实际内存地址的具体引用。在解析阶段,符号引用需要经过运行时转换,成为可以直接访问目标的具体引用。

1.类和接口的全限定名(Fully Qualified Name)

2.字段的名称和描述符(Descriptor)

由于类文件不会保存每个方法和字段的最终内存布局信息,这些符号引用需要在类加载到JVM后进行动态链接。动态链接过程会将符号引用转换为可以直接访问目标的直接引用。

为了表示类、接口、方法和字段的符号引用,常量池中包含了多种表结构。这些表结构构成了不同类型的常量,如CONSTANTUtf8_info、CONSTANT_Integer_info、CONSTANT_Class_info、CONSTANT_String_info、CONSTANT_Fieldref_info、CONSTANT_Methodref_info等。这些表结构中的数据结构复杂,因为每种常量类型都有自己的数据结构,以满足不同需求。

在这些表结构中,我们可以找到一些常用的表项,如:

- CONSTANTUtf8_info:用于表示utf8编码的字符串。

- CONSTANT_Integer_info:用于表示整型字面量。

- CONSTANT_Class_info:用于表示类或接口的符号引用。

- CONSTANT_String_info:用于表示字符串类型的字面量。

- CONSTANT_Fieldref_info:用于表示字段的符号引用。

- CONSTANT_Methodref_info:用于表示方法的符号引用。

每种表项开始都包含一个u1类型的标志位,用于表示表项的类型。接下来,根据表项的类型,会有不同的字段,如name_index、length等。name_index代表类名或接口名,length表示字符串的长度等。这些字段共同构成了常量池中不同表结构的数据。

在Java类加载过程中,符号引用起到了关键作用。通过解析阶段将符号引用转换为直接引用,JVM可以有效地定位和访问类的内部结构,进而实现类的使用和管理。这一过程是Java类加载机制中的重要组成部分,对于理解Java类的加载和运行机制至关重要。