堆与方法区在jdk以来的各种变化总结

方法区在jdk1.8前,很多人都把方法区当称呼为永久代,或者将俩者混为一谈。本质上这俩这并不是等价的,因为仅仅是hotspot虚拟机设计团队选择把收集器的分带设计扩展至方法区,或者说使用永久代来实现方法区而已.这样使得hotspot的垃圾收集器能够像管理java堆一样管理这部分内存,省去专门为方法区编写内存管理代码的工作。但是对于其他虚拟机实现,譬如BEA Jrockit IBM J9等来说,是不存在永久代的概念的,原则上如何实现方法区的细节,不受java虚拟机规范的约束,并不要求统一。但现在来看,当年使用永久代老实现方法区的决定并不是一个好主意,这导致了java应用程序更容易遇到内存溢出的问题考虑到hotspot未来的房展,在jdk6的时候hotspot开发团队就有放弃永久代,逐步改为采用与Jrockit J9一样在本地内存中实现的元空间来代替,把jdk7中永久代还剩余的内容(主要是类型信息)全部移到了元空间中

阅读本文先明确以下概念

  • :存放对象的实例
  • 方法区:存放虚拟机加载类信息,常量,静态变量,以及编译后的代码缓存
  • 运行时常量池:是方法区的一部分,class文件中除了有类的版本,字段接口信息外,还有一项信息是常量表,用于存放编译期生成的各种字面量与符号的引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
  • 常量池:一个java源文件的类,接口,编译后会产生一个字节码文件。通常这种数据会很大以至于不能直接存到字节码里,换一种方式,可以存到常量池中,这个字节码包含了指向常量池的引用。在动态链接的时候会用到运行时常量池。可以包括:数量值,字符串值,类引用,字段引用,方法引用。
    常量池可以看作是一张表,虚拟机指令根据这张常量表找到要执行的类名,方法名,参数类型,字面量等类型。
  • 字符串常量池:HotSpot VM里,记录interned string的一个全局表叫做StringTable,它本质上就是个HashSet<String>。注意它只存储对java.lang.String实例的引用,而不存储String对象的内容

以上是深入理解jvm中的一段话,我们来看看各个版本具体的变动

  • jdk1.6:之前 有永久代,静态变量存放在永久代上,字符串常量池存放在永久代,静态变量也存放在永久代
  • 1.7:有永久带,但逐步去永久代,字符串常量池,静态变量移除,保存在堆中
  • 1.8:之后无永久代,字段方法,常量保存在本地内存的元空间,但字符串常量池静态变量仍在堆
Last modification:April 19, 2022
如果觉得我的文章对你有用,请随意赞赏