Excel不相邻列如何打印在一起-英雄云拓展知识分享
148
2023-11-07
【摘要】 本书摘自《深入理解 Java 虚拟机 JVM 高级特性与最佳实践(第3版)》一书中第3章,第2节,周志明著。
3.2.5 回收方法区
有些人认为方法区(如 HotSpot 虚拟机中的元空间或者永久代)是没有垃圾收集行为 的,《Java 虚拟机规范》中提到过可以不要求虚拟机在方法区中实现垃圾收集,事实上也确 实有未实现或未能完整实现方法区类型卸载的收集器存在(如JDK 11时期的ZGC 收集器 就不支持类卸载),方法区垃圾收集的“性价比”通常也是比较低的:在Java堆中,尤其是 在新生代中,对常规应用进行一次垃圾收集通常可以回收70%至99%的内存空间,相比之 下,方法区回收囿于苛刻的判定条件,其区域垃圾收集的回收成果往往远低于此。
方法区的垃圾收集主要回收两部分内容:废弃的常量和不再使用的类型。回收废弃常 量与回收Java 堆中的对象非常类似。举个常量池中字面量回收的例子,假如一个字符串 “java” 曾经进入常量池中,但是当前系统又没有任何一个字符串对象的值是 “java”, 换句 话说,已经没有任何字符串对象引用常量池中的 “java” 常量,且虚拟机中也没有其他地 方引用这个字面量。如果在这时发生内存回收,而且垃圾收集器判断确有必要的话,这个 “java” 常量就将会被系统清理出常量池。常量池中其他类(接口)、方法、字段的符号引用 也与此类似。
判定一个常量是否“废弃”还是相对简单,而要判定一个类型是否属于“不再被使用 的类”的条件就比较苛刻了。需要同时满足下面三个条件:
口该类所有的实例都已经被回收,也就是Java 堆中不存在该类及其任何派生子类的 实例。
口加载该类的类加载器已经被回收,这个条件除非是经过精心设计的可替换类加载器 的场景,如 OSGi 、JSP 的重加载等,否则通常是很难达成的。
口该类对应的java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射 访问该类的方法。
Java 虚拟机被允许对满足上述三个条件的无用类进行回收,这里说的仅仅是“被允许”, 而并不是和对象一样,没有引用了就必然会回收。关于是否要对类型进行回收, HotSpot 虚 拟机提供了-Xnoclassgc 参数进行控制,还可以使用-verbose:class 以及-XX:+TraceClass-
Loading 、-XX:+TraceClassUnLoading 查看类加载和卸载信息,其中-verbose:class 和-XX: +TraceClassLoading 可以在 Product 版的虚拟机中使用, -XX:+TraceClassUnLoading 参数需 要 FastDebug 版9的虚拟机支持。
在大量使用反射、动态代理、CGLib 等字节码框架,动态生成 JSP 以 及OSGi 这类频 繁自定义类加载器的场景中,通常都需要Java 虚拟机具备类型卸载的能力,以保证不会对 方法区造成过大的内存压力。
3.3 垃圾收集算法
垃圾收集算法的实现涉及大量的程序细节,且各个平台的虚拟机操作内存的方法都有 差异,在本节中我们暂不过多讨论算法实现,只重点介绍分代收集理论和几种算法思想及 其发展过程。如果读者对其中的理论细节感兴趣,推荐阅读 Richard Jones 撰写的《垃圾回 收算法手册》③的第2~4章的相关内容。
从如何判定对象消亡的角度出发,垃圾收集算法可以划分为“引用计数式垃圾收集” (Reference Counting GC) 和“追踪式垃圾收集” (Tracing GC) 两大类,这两类也常被称作 “直接垃圾收集”和“间接垃圾收集”。由于引用计数式垃圾收集算法在本书讨论到的主流 Java 虚拟机中均未涉及,所以我们暂不把它作为正文主要内容来讲解,本节介绍的所有算 法均属于追踪式垃圾收集的范畴。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们 18664393530@aliyun.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~