上一篇线程共享分类图显示,堆和方法区都是线程共享的区域,在 HotSpot JVM 中,永久代( ≈ 方法区)中用于存放虚拟机加载的类信息、常量池、静态属性。每当一个类初次被加载的时候,都会放到永久代中。
永久代是有大小限制的,因此如果加载的类太多,很有可能导致永久代内存溢出,即万恶的java.lang.OutOfMemoryError: PermGen。为此不得不对虚拟机做出相应的性能调优,于是在Java8时,永久代正式被废弃移除。
根据官方文档(JEP 122: Remove the Permanent Generation),描述PermGen正式被移除的原因:
1. 由于 PermGen 内存经常会溢出,引发恼人的 java.lang.OutOfMemoryError: PermGen,因此 JVM 的开发者希望这一块内存可以更灵活地被管理,不要再经常出现这样的OOM;
2. 移除 PermGen 可以促进 HotSpot JVM 与 JRockit VM 的融合,因为 JRockit 没有永久代。
由于以上种种原因,PermGen被移除,方法区移至Metaspace,字符串常量池移至堆区(实际上,字符串常量池是在Java7就移到了堆区)
【延伸拓展:java三大虚拟机 HotSpot,oracle JRockit,IBM J9。
JRockit是oracle发明的,用于其WebLogic服务器,IBM JVM是IBM发明的用于其Websphere服务器(所以在某行开发的时候,他们用的是IBM的JDK,因为他们使用的IBM的应用程序服务器Websphere,使用其他JDK可能存在兼容性问题)。
JRockit和J9不存在永久代这种说法。这里只讨论HotSpot虚拟机,这也是目前使用的最多的JVM。】
Metaspace代最大的区别在于:Metaspace并不在虚拟机内存中而是使用本地内存。
Metaspace相关JVM参数:
- https://mp.weixin.qq.com/sbiz=MzI3ODcxMzQzMw==&mid=2247492302&idx=2&sn=81486286d47bc47fc617dc813fa37d88&chksm=eb5067f8dc27eeee76245b8b307b95c321be115fd268677fe00745b4f2dc43732ff7f4f8341 c&scene=21#wechat_redirect
- http://lovestblog.cn/blog/2016/10/29/metaspace/
- https://blog.csdn.net/kingmax54212008/article/details/104165185
- https://www.cnblogs.com/lsgxeva/p/10220831.html