色块的网站,服务器有哪些,美颜秘籍网站建设,网站建设需要公司作者简介#xff1a;大家好#xff0c;我是smart哥#xff0c;前中兴通讯、美团架构师#xff0c;现某互联网公司CTO 联系qq#xff1a;184480602#xff0c;加我进群#xff0c;大家一起学习#xff0c;一起进步#xff0c;一起对抗互联网寒冬 学习必须往深处挖… 作者简介大家好我是smart哥前中兴通讯、美团架构师现某互联网公司CTO 联系qq184480602加我进群大家一起学习一起进步一起对抗互联网寒冬 学习必须往深处挖挖的越深基础越扎实
阶段1、深入多线程阶段2、深入多线程设计模式阶段3、深入juc源码解析阶段4、深入jdk其余源码解析阶段5、深入jvm源码解析
一、简介
我们在 JVM垃圾回收机制一章中简单介绍了JVM的垃圾回收机制先来回顾下系统运行时创建的对象优先在Java堆内存区域分配 然后新生代里的对象越来越多当快满了的时候就会触发“Minor GC”把新生代中的一些对象回收掉 那么这里就涉及一个问题 JVM如何知道要去回收哪些对象 这其实就是JVM的对象存活判定机制主要涉及两种算 可行性分析算法 和 引用计数算法 。 引用计数算法是给对象添加一个引用计数器每当有一个地方引用它时计数器就加1当引用失效时计数器值就减1任何时刻计数器为0的对象就是可以被回收的。 由于Java语言没有选用引用计数法来管理JVM内存所以本文不赘述而且引用计数法不能很好的解决循环引用的问题Python采用的是引用计数法。 二、可达性分析算法
可达性分析算法GC Root Tracing 其基本思路就是通过一系列的名为 GC Roots 的对象作为起始点从这些起始点开始搜索搜索所走过的路径称为引用链Reference Chain当一个对象到GC Roots没有任何引用链相连时即从 GC Roots 到这个对象不可达则证明此对象是不可用的就可以被回收。
GC Roots包括
Java虚拟机栈中的局部变量指向着GC堆里的对象VM的一些静态数据结构里指向GC堆里的对象的引用例如HotSpot VM里的Universe里有很多这样的引用所有当前被加载的Java类看情况Java类的运行时常量池里的引用类型常量String常量池StringTable里的引用。
可达性分析算法最难理解的就是该选取哪些对象作为GC Roots我们通过两个示例来看下。 2.1 示例一
下面是最常见的一种情况 public class Kafka {public static void main(String[] args) {loadReplicasFromDisk();}public static void loadReplicasFromDisk(){ReplicaManager replicaManager new ReplicaManager();}}当执行到loadReplicasFromDisk()时对应的JVM内存数据结构如下图 假如此时新生代的内存已经快满了发生了“Minor GC”那么JVM会分析ReplicaManager对象的可达性发现它被“replicaManager”这个局部变量引用着在JVM规范中 局部变量是可以作为GC Roots的 所以就不会被回收。 2.2 示例二
另一种比较常见的情况是下面这种样子 public class Kafka {public static ReplicaManager replicaManager new ReplicaManager();}对应的JVM内存数据结构如下图 假如此时新生代的内存已经快满了发生了“Minor GC”那么JVM会分析ReplicaManager对象的可达性发现它被“replicaManager”这个方法区中的静态变量引用着在JVM规范中 静态变量是可以作为GC Roots的 所以就不会被回收。 三、Java引用类型
可达性分析与Java的引用类型有关联为了更好的管理对象的内存更好的进行垃圾回收JVM团队扩展了引用类型从最早的强引用类型增加到 强引用 、 软引用 、 弱引用 、 虚引用 四个引用类型 3.1 强引用StrongReference
默认的对象都是强引用类型如果JVM在对象存活判定时通过GC Roots可达性分析结果为可达表示引用类型仍然被引用着这类对象始终不会被垃圾回收器回收。比如下面这段代码 public class Kafka {public static ReplicaManager replicaManager new ReplicaManager();}3.2 软引用SoftReference
在JVM内存充足的情况下软引用是不会被GC回收的 只有在JVM内存不足的情况下才会被GC回收 。比如下面这段代码 public class Kafka {public static SoftReferenceReplicaManager replicaManager new SoftReferenceReplicaManager(new ReplicaManager());}适用场景 网页缓存、图片缓存 3.3 弱引用WeakReference
不论当前JVM内存是否充足都 只能存活到下一次垃圾收集之前 说的直白点只要发生GC弱引用对象就会被回收比如下面这段代码 public class Kafka {public static WeakReferenceReplicaManager replicaManager new WeakReferenceReplicaManager(new ReplicaManager());}ThreadlLocal中定义的ThreadLocalMap就使用到的弱引用。ThreadLocalMap的Entry其Key就是一个弱引用对象读者可以参考我的《Java多线程系列》。 3.4 虚引用PhantomReference
虚引用不会影响对象的生命周期所持有的引用就跟没持有一样随时都能被GC回收。在使用虚引用时必须和 引用队列 关联使用。其使用场景是用来跟踪对象被垃圾回收器回收的活动。
在对象的垃圾回收过程中如果GC发现一个对象还存在虚引用则会把这个 虚引用加入到与之关联的引用队列 中。
程序可以通过判断引用队列中是否已经加入了虚引用来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列那么就可以在所引用的对象内存被回收之前采取必要的行动防止被回收。 四、finalize方法
大家理解完了GC Roots和引用类型的概念基本就都知道了哪些对象可以被回收哪些对象不可以被回收
有GC Roots引用的对象不能回收没有GC Roots引用的对象如果是软引用或弱引用可能会被回收。
真正的回收环节待被回收的对象其实还有一次机会拯救自己那就是对象的finalize()方法。我们通过一段代码示例来看下 public class ReplicaManager {public static ReplicaManager instance;Overrideprotected void finalize() throws Throwable {ReplicaManager.instance this;}}假如有一个ReplicaManager对象马上就要被回收了此时已经没有GC Roots到达它的链路此时GC会首先调用下该对象的finalize()方法看看它是否找了一个新的GC Roots来引用自己比如上述代码中GC发现有个静态变量instance引用了该实例那GC就不会去回收它。 finalize方法没事不要去重写这都是GC内部的机制平时也几乎不用。