运行时内存数据区之方法区(二)

news/2024/10/18 0:30:32/

方法区的演进细节

  1. 首先明确:只有HotSpot才有永久代。BEA JRockit、IBMJ9等来说,是不存在永久代的概念的。原则上如何实现方法区属于虚拟机实现细节,不受《]Va虚拟机规范》管束,并不要求统一。
  2. Hotspot中方法区的变化:

永久代为什么要被元空间替换?

  • 随着Java8的到来,Hotspot VM中再也见不到永久代了。但是这并不意味着类的元数据信息也消失了。这些数据被移到了一个与堆不相连的本地内存区域,这个区域叫做元空间(Metaspace)。
  • 由于类的元数据分配在本地内存中,元空间的最大可分配空间就是系统可用内存空间。
  • 这项改动是很有必要的,原因有:
  1. 为永久代设置空间大小是很难确定的。
    1. 在某些场景下,如果动态加载类过多,容易产生Perm区的OOM。比如某个实际Web工程中,因为功能点比较多,在运行过程中,要不断动态加载很多类,经常出现致命错误。
      1. "Exception in thread 'dubbo client x.x connector'java.lang.OutOfMemoryError:PermGen space"
    1. 而元空间和永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。
  1. 对永久代进行调优是很困难的。

StringTable为什么要调整?

jdk7中将StringTablej放到了堆空间中。因为永久代的回收效率很低,在Full GC的时候才会触发。而Full GC是老年代的空间不足、永久代不足时才会触发。这就导致StringTable回收效率不高。而我们开发中会有大量的字符串被创建,回收效率低,导致永久代内存不足。放到堆里,能及时回收内存。

方法区的垃圾回收

有些人认为方法区(如HotSpot虚拟机中的元空间或者永久代)是没有垃圾收集行为的,其实不然。《Java虚拟机规范》对方法区的约束是非常宽松的,提到过可以不要求虚拟机在方法区中实现垃圾收集。事实上也确实有未实现或未能完整实现方法区类型卸载的收集器存在

(如JDK11时期的ZGC收集器就不支持类卸载)。

一般来说这个区域的回收效果比较难令人满意,尤其是类型的卸载,条件相当苛刻。但是这部分区域的回收有时又确实是必要的。以前Sun公司的Bug列表中,曾出现过的若干个严重的Bug就是由于低版本的HotSpot虚拟机对此区域未完全回收而导致内存泄漏。

方法区的垃圾收集主要回收两部分内容:常量池中废弃的常量和不再使用的类型。

先来说说方法区内常量池之中主要存放的两大类常量:字面量和符号引用。字面量比较接近Java语言层次的常量概念,如文本字符串、被声明为final的常量值等。而符号引用则属于编译原理方面的概念,包括下面三类常量:

  1. 类和接口的全限定名
  2. 字段的名称和描述符
  3. 方法的名称和描述符

HotSpot虚拟机对常量池的回收策略是很明确的,只要常量池中的常量没有被任何地方引用,就可以被回收。

回收废弃常量与回收Java堆中的对象非常类似。

判定一个常量是否“废弃”还是相对简单,而要判定一个类型是否属于“不再被使用的类”的条件就比较苛刻了。需要同时满足下面三个条件:

  1. 该类所有的实例都已经被回收,也就是]ava堆中不存在该类及其任何派生子类的实例。
  2. 加载该类的类加载器已经被回收,这个条件除非是经过精心设计的可替换类加载器的场景,如OSGi、JSP的重加载等,否则通常是很难达成的。
  3. 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

Java虚拟机被允许对满足上述三个条件的无用类进行回收,这里说的仅仅是“被允许”,而并不是和对象一样,没有引用了就必然会回收。关于是否要对类型进行回收,

HotSpot虚拟机提供了-Xnoclassgc参数进行控制,还可以使用-verbose:class以及-XX:+TraceClass-Loading、-XX:+TraceClassUnLoading查看类加载和卸载信息。

在大量使用反射、动态代理、CGLib等字节码框架,动态生成JSP以及OSGi这类频繁自定义类加载器的场景中,通常都需要Java虚拟机具备类型卸载的能力,以保证不会对方法区造成过大的内存压力。


http://www.ppmy.cn/news/47235.html

相关文章

学系统集成项目管理工程师(中项)系列08b_合同管理(下)

1. 项目变更约定 1.1. 合同生效后,当事人不得因姓名、名称的变更或者法定代表人、负责人、承办人的变动而不履行合同义务 2. 违约责任的承担方式 2.1. 继续履行 2.2. 采取补救措施 2.3. 赔偿损失 2.4. 支付约定违约金或定金 3. 注意事项 3.1. 当事人的法律资…

业余爱好者想入门编程,一定远离那些只会说No的家伙,尤其程序员

视频:https://haokan.baidu.com/v?pdwisenatural&vid3050207991292418741 自媒体上的程序员群体有一个非常有意思的特点,就是特别愿意否定别人,特别喜欢说no,还有一个特点,特别不爱分享一些有用的技术和知识&…

jdk8到jdk17新增新特性介绍

JDK 8: Lambda表达式和函数式接口 Lambda表达式是一个匿名方法,可以用于将行为作为参数传递给方法,或者在函数式接口中直接表示行为。Lambda表达式使用箭头 -> 将参数列表分隔开来,并且主体由花括号包含。以下是一个简单的Lambda表达式示…

【学习笔记】[JSOI2019]节日庆典

我觉得很厉害。因为这道字符串题目的分析非常自然而且并不复杂。 考虑枚举右端点到 r r r时,维护可能成为答案的位置的集合。显然对于相邻两个元素 i , j i,j i,j,我们有 lcp(S[i:],S[j:]) > r − j \text{lcp(S[i:],S[j:])}>r-j lcp(S[i:],S[j:]…

SSM整合的基本思路梳理

SSM整合的简单思路流程 基本思路 我在整合的时候一般习惯从MyBatis开始向上构建,也就是在开始一个项目的时候先将DAO层搭建起来,再向上整合Spring以及SpringMVC。按照这个流程,可以做出一个比较简单的大致流程作为参考,帮助我们…

【MyBatis Plus】003 -- 配置(基本、进阶、DB策略) 条件构造器

目录 4、配置 4.1 基本配置 4.1.1 configLocation (MyBatis 配置文件位置) 4.1.2 mapperLocations(MyBatis Mapper 所对应的 XML 文件位置) 4.1.3 typeAliasesPackage (别名包扫描路径) 4.2 进阶配置 4.2.1…

图解项目延期的原因及解决应对方案大全

项目管理中经常出现项目延期的情况,面对项目延期的风险如何应对是考验每个项目经理管理水平的时候,很多人纵然是工作多年也没有对延期的种种情况进行总结思考。 咱们社区的小竹对大家常见的项目延期情况及处理方案进行了详细全面的总结,供大…

Kotlin 泛型的使用

一、Kotlin 泛型是一种允许在编译时指定类型参数的机制&#xff0c;它可以提高代码的重用性和类型安全性。 Kotlin 泛型使用尖括号&#xff08;< >&#xff09;来指定类型参数。Kotlin 泛型支持类泛型、接口泛型和方法泛型。Kotlin 泛型可以在类、函数、接口和委托中使用…