持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第28天,点击查看活动详情
持久代
-
持久代中包含了虚拟机中所有可通过反射获取到的数据,比如Class和Method对象。不同的Java虚拟机之间可能会进行类共享,因此持久代又分为只读区和读写区。
-
JVM用于描述应用程序中用到的类和方法的元数据也存储在持久代中。JVM运行时会用到多少持久代的空间取决于应用程序用到了多少类。除此之外,Java SE库中的类和方法也都存储在这里。
-
如果JVM发现有的类已经不再需要了,它会去回收(卸载)这些类,将它们的空间释放出来给其它类使用。FullGC会进行持久代的回收。
-
JVM中类的元数据在Java堆中的存储区域。
-
Java类对应的HotSpot虚拟机中的内部表示也存储在这里。
-
类的层级信息,字段,名字、方法的编译信息及字节码、变量、常量池和符号解析也存储在这里
- 在JVM中,类包含其对应的元数据,比如类的层级信息,方法数据和方法信息(如字节码,栈和变量大小),运行时常量池,已确定的符号引用和虚方法表。
-
另外还需要注意的是在HotSpot虚拟机中永久带和堆虽然相互隔离,但是他们的物理内存是连续的。而且老年代和永久带的垃圾收集器进行了捆绑,因此无论谁满了都会触发永久带和老年带的GC。
持久代的大小
-
它的上限是MaxPermSize,默认是64M
-
Java堆中的连续区域:如果存储在非连续的堆空间中的话,要定位出持久代到新对象的引用非常复杂并且耗时。卡表(card table),是一种记忆集((Remembered Set),它用来记录某个内存代中普通对象指针(oops)的修改。
-
持久代用完后,会抛出Qut0fMemoryError ""PermGen space"异常。
- 解决方案:应用程序清理引用来触发类卸载;增加MaxPermSize的大小。
-
需要多大的持久代空间取决于类的数量,方法的大小,以及常量池的大小。
永久代为什么被移出HotSpot JVM了?
- 由于Permanent Generation内存经常不够用或发生内存泄露,引发恼人的java.lang.OutOfMemoryError: PermGen (在Java Web开发中非常常见)。\
- 移除Permanent Generation可以促进HotSpot JVM与JRockit VM的融合, JRockit从来没有一个叫永久代的东西, 但是运行良好, 也不需要开发运维人员设置这么一个永久代的大小.\
- 它的大小是在启动时固定好的,所以对永久代进行调优是很困难的。
元空间
持久代的空间被彻底地删除了,它被一个叫元空间的区域所替代了。持久代删除了之后,很明显,JIMM会忽略PermSize和MaxPermSize这两个参数,还有就是你再也看不到java.lang.QutOfMemoryError: PermGen error的异常了。原来类的静态变量和Interned Strings都被转移到了java堆区,
只有class元数据才在元空间。
JDK8的HotSpot JVM现在使用的是本地内存来表示类的元数据,这个区域就叫做元空间。
元空间的特点:
- 充分利用了Java语言规范中的好处:类及相关的元数据的生命周期与类加载器的一致。
- 每个加载器有专门的存储空间
- 只进行线性分配
- 不会单独回收某个类
- 省掉了GC扫描及压缩的时间
- 元空间里的对象的位置是固定的
- 如果GC发现某个类加载器不再存活了,会把相关的空间整个回收掉
注意:
-
在jdk1.7以前,永久代包含:字符串常量池、类的元数据等
-
在jdk1.7时,永久代的字符串常量池、类的静态变量被转移到堆中,其他的东西还是在永久代
-
在jdk1.8时,用元空间实现方法区,并交给操作系统管理
-
而在java8中移除了永久代,新增了元空间,其实在这两者之间存储的内容几乎没怎么变化,而是在内存限制、垃圾回收等机制上改变较大。元空间的出现就是为了解决突出的类和类加载器元数据过多导致的OOM问题,而从jdk7中开始永久代经过对方法区的分裂后已经几乎只存储类和类加载器的元数据信息了,到了jdk8,元空间中也是存储这些信息,而符号引用、字符串常量等存储位置与jdk7一致,还是“分裂”的方法区。
符号引用没有存在元空间中,而是存在native heap中,这是两个方式和位置,不过都可以算作是本地内存,在虚拟机之外进行划分,没有设置限制参数时只受物理内存大小限制,即只有占满了操作系统可用内存后才OOM。
原因:\
- 字符串存在永久代中,容易出现性能问题和内存溢出。\
- 类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。 \
- 永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。
JVM8中元空间有哪些特点?
- 每个加载器有专门的存储空间。\
- 不会单独回收某个类。 \
- 元空间里的对象的位置是固定的。\
- 如果发现某个加载器不再存货了,会把相关的空间整个回收