10.Java永久代去哪了

      在Java虚拟机中,类包含了其对应的元数据,比如类的层级信息,方法数据和方法信息(如字节码,栈和变量大小),运行时常量池,已确定的符号引用和虚方法表;

      在过去(当自定义类加载器使用地不是很普遍的时候),类几乎是静态的,并且很少被卸载和回收;因此类可以被看做是“永久的”;另外由于类作为JVM实现的一部分,它们不由程序来创建,因此它们也被认为是“非堆”的内存;

      在JDK8之前,类的这些“永久的”数据存放在一个叫做永久代的区域;在JVM启动之前可以通过设置-XX:MaxPermSize的值来控制永久代的大小;32位机器默认永久代大小为64MB,64位为85MB;永久代的垃圾回收和老年代的垃圾回收是绑定的,一旦其中一个区域被占满,这两个区域都要进行垃圾回收;但这也带来了一个问题,一旦类的元数据超过了设定的大小,程序就会耗尽内存,并出现内存溢出错误(OOM);

-----------------------------------------------

      但在Java8的时候,永久代“不见”了;类的元数据信息被移到了一个与堆不相连的本地内存区域,即元空间

      这样改动是很有必要的,因为对永久代的调优是很困难的;永久代中的元数据可能会随着每一次Full GC发生而进行移动,而且永久代的空间大小也是很难确定的,因为这其中有很多影响因素,比如类的总数,常量池的大小和方法数量等;同时,JVM中的每种垃圾回收器都需要对永久代中的元数据进行特殊处理;

       将元数据从永久代剥离出来,不仅实现了对元空间的无缝管理,还可以简化Full GC以及对以后的并发隔离类元数据等方面进行优化;

移除永久代的影响

       由于类的元数据分配在本地内存中,元空间的最大可分配空间就是系统的可用内存空间;因此,就不会遇到永久代存在时的内存溢出错误,也不会出现泄漏的数据移到交换区这样的事情;最终,用户可以为元空间设置一个可用空间的最大值,如果不进行设置,JVM会根据类的元数据大小动态地增加元空间的容量;

注意:永久代的移除并不代表自定义的类加载器泄漏的问题就解决了;因此,还需监控内存消耗情况,因为一旦发生泄漏,会占用大量本地内存,并且还可能导致交换区交换更加糟糕;

元空间内存管理

       元空间的内存管理由元空间虚拟机来完成;永久代未被移除之前,JVM中的每种垃圾回收器都需要对永久代中的元数据进行特殊处理;现在只需要执行元空间虚拟机的C++代码即可;

       在元空间中,类和其元数据的生命周期和其对应的类加载器是相同的;也就是说,只要类加载器存活,其加载的类的元数据也是存活的,是不会被回收的;

       准确来说,每一个类加载器的存储区域都被称作一个元空间,所有的元空间合在一起就是我们所说的元空间;当一个类加载器被垃圾回收器标记为不再存活时,其对应的元空间会被回收;在元空间的回收过程中没有重定向和压缩等操作,但是元空间内的元数据会进行扫描来确定Java引用;

       元空间虚拟机负责元空间的分配,其采用的形式为组块分配;组块的大小因类加载器的类型而异;在元空间虚拟机中存在一个全局的空闲组块列表;当一个类加载器需要组块时,它就会从这个全局的组块列表中获取并维持一个自己的组块列表;当一个类加载器不再存活,其持有的组块将会被释放,并返回给全局组块列表;

       类加载器持有的组块又会被分成多个块,每一块存储一个单元的元信息;组块中的块是线性分配的(指针碰撞分配形式),组块分配自内存映射区域。这些全局的虚拟内存映射区域以链表形式连接,一旦某个虚拟内存映射区域清空,这部分内存就会返回给操作系统;

元空间调优与工具

      正如上面提到的,元空间虚拟机控制元空间的增长。但是有些时候我们想限制其增长,比如通过显式在命令行中设置- XX:MaxMetas paceSize ;默认情况下,-XX:MaxMetaspaceSize 的值没有限制,因此元空间甚至可以延伸到交换区,但是这时候进行本地内存分配会失败;

       对于一个64 位的服务器端NM 来说,其默认的- XX:MetaspaceSize 值为21MB 。这就是初始的高水位线,一旦触及这个水位线, Full GC 将会被触发井卸载没用的类(即这些类对应的类加载器不再存活),然后这个高水位线将会重置。新的高水位线的值取决于GC 后释放了多少元空间。如果释放的空间不足,则这个高水位线上升。如果释放空间过多,则高水位线下降。如果初始化的高水位线设置过低,上述高水位线调整情况会发生很多次。通过垃圾回收器的日志可以观察到Full GC 多次调用。为了避免频繁地GC ,建议将- XX:MetaspaceSize 设置为一个相对较高的值;

       经过多次GC 之后,元空间虚拟机自动调节高水位线,以此来推迟下一次垃圾回收的到来;

       有这样两个选项:-XX:MinMetaspaceFreeRatio 和-XX:MaxMetaspaceFreeRatio ,它们类似于GC 的FreeRatio 选项,用来设置元空间空闲比例的最大值和最小值。可以通过命令行设置这两个选项的值;

       前面已经提到,元空间虚拟机采用了组块分配的形式,同时区块的大小由类加载器类型决定。类信息并不是固定大小的,因此有可能分配的空闲区块和类需要的区块大小不同,这种情况下可能导致碎片存在。元空间虚拟机目前并不支持压缩操作,所以碎片化是目前最大的问题;

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值