Java编程开发之浅析Java引用机制原创
对于一个Java的对象而言,存储主要分为两种,一种是内存堆(Heap),内存堆是无序的,主要用来存放创建的Java对象;一种是内存栈(Stack),主要用来存放Java引用,然后在管理过程使用Java引用指向Java对象。
随着黄金梅丽号在大海之上的飘荡,一切看着是那么的风平浪静,但是每个人似乎都在忙着自己手里的那些事情…突然韦柏向萨博提出了一个问题:都知道JVM调优是当下从事Java开发必须要去具备甚至要去提升自己的一个重要环节,那你知道堆与栈,各自存放机制是什么?也就针对于这个问题,就像当初去探索世界尽头的梦想一样,萨博这样回答韦柏:对于一个Java的对象而言,存储主要分为两种,一种是内存堆(Heap),内存堆是无序的,主要用来存放创建的Java对象;一种是内存栈(Stack),主要用来存放Java引用,然后在管理过程使用Java引用指向Java对象。
听完萨博的回答,韦柏靠在甲板上,点燃了一支猩红的香烟,抽了一口,然后对萨博说道:那你能详细的讲解一下这个引用机制么?萨博思考了一下,于是有了以下的故事…
1、CG的基本原理
在引入Reference引用的概念之前,我们需要清楚的知道内存栈(Stack)和内存堆(Heap)在JVM虚拟机的结构分布以及基本情况,如上图所示。综上所述,我们可以了解到Java的内存管理实际上就是对象的管理,包括对象实例的分配和释放。其中GC的存在就是负责在对象“不可达”的时候将对象回收处理。当系统在创建对象实例的时候,即当使用new关键字创建一个对象的时候,GC就开始监控对象的地址、大小以及使用状态。
一般情况下,Java的GC机制都有特定的回收算法,GC通常会使用有向图的方式来记录队中的所有对象,通过此种方式确定甚至标记哪些对象是“可达的”,而哪些是“不可达的”。当GC判断一些对象不可达的时候,GC就有责任回收相关内存空间,是否能被垃圾回收机制回收,具体操作是取决于机器和平台,但判断依据主要是看对象是否有引用指向该对象。
2、Reference引用基本概述
Abstract base class for reference objects. This class defines the operations common to all reference objects. Because reference objects are implemented in close cooperation with the garbage collector, this class may not be subclassed directly.
不难发现,Reference机制对JVM的垃圾收集活动敏感,Reference的继承关系或者实现是由JDK定制,引用实例是由JVM创建,一般不推荐自行继承Reference实现自定义的引用类型,但是可以继承已经存在的引用类型。
JDK提供了强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)和虚引用(Phantom Reference),引用队列(ReferenceQueue)以及析构引用(Final Reference)等引用类型。
[⚠️注意事项]:
- 强引用可能对垃圾收集活动是不敏感的
- 自行继承Reference实现自定义的引用类型,其反复造轮子的意义不大。
- 析构引用(Final Reference),它是一种特化的虚引用
- 不同JDK版本,需要注意实际源码的对比分析。
- Reference是所有引用对象的基类
4、Reference引用类型分析
- 强引用(Strong Reference):在Java中最常见的就是强引用,也是最普遍存在的引用类型。处于可达状态,是不可能被垃圾回收机制回收的,即使该对象以后永远都不会被用到JVM也不会回收。
- 软引用(Soft Reference):对于只有软引用的对象来说,当系统内存足够时它不会被回收,当系统内存空间不足时它会被回收。软引用通常用在对内存敏感的程序中。
- 弱引用(Weak Reference):比软引用的生存期更短,对于只有弱引用的对象来说,只要垃圾回收机制一运行,不管JVM的内存空间是否足够,总会回收该对象占用的内存。
- 虚引用(Phantom Reference):不能单独使用,必须和引用队列联合使用。虚引用的主要作用是跟踪对象被垃圾回收的状态。
引用队列(ReferenceQueue):
析构引用(Final Reference):
[⚠️注意事项]:
强引用可能对垃圾收集活动是不敏感的,没有对应的类型表示,也就是说强引用是普遍存在的,如Object object = new Object();。
软引用、弱引用和虚引用都是java.lang.ref.Reference的直接子类。
直到JDK11为止,只存在四种引用,这些引用是由JVM创建,因此直接继承java.lang.ref.Reference创建自定义的引用类型是无效的,但是可以直接继承已经存在的引用类型,如java.lang.ref.Cleaner就是继承自java.lang.ref.PhantomReference。
特殊的java.lang.ref.Reference的子类java.lang.ref.FinalReference和Object#finalize()有关,java.lang.ref.Finalizer是java.lang.ref.FinalReference子类。
版权声明:本文为博主原创文章,遵循相关版权协议,如若转载或者分享请附上原文出处链接和链接来源。