方法区
方法区与Java堆一样,是各个线程共享的内存区域,它用于存储已经被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。
他也有一个别名为"非堆",目的是与Java堆区分开来。
方法区和永久代
在JDK8以前,很多把方法区和永久代混为一谈,本质上这两者并不是等价的,仅仅是因为当时的HotSpot虚拟机设计团队选择吧收集器的分代设计扩展至方法区,或者说使用永久代来实现方法区而已,这样使得HotSpot的垃圾收集器能够像管理Java堆一样管理方法区的内存,省去专门为方法区编写内存管理的工作。
但是对于其他的虚拟机是不存在永久代的概率的。
缺陷以及改变
缺陷
使用永久代来实现方法区的使得Java应用更容易遇到内存溢出的问题(永久代有-XX:MaxPermSize的上限,几时不设置也有默认大小,而J9和JRockit只要没有触碰到进程可用内存的上限,例如32位系统中的4GB限制,就不会出现问题)
而极少数的方法(例如:String::intern())会因为永久代的原因导致在不同虚拟机下有不同的表现
改变
- 在JDK6的时候HotSpot开发团队就有放弃永久代,逐步改为采用本地内存来实现方法区的计划了
- 到了JDK7,已经把原本放入永久代的字符串常量池、静态变量等移出
- 到了JDK8,终于完全废弃了永久代的概念了,该用与JRockit、J9一样在本地内存中实现的元空间来代替,并将在JDk7中永久代还剩余的内容全部移到元空间中