再战JVM (6) 运行时数据区-方法区

26 篇文章 0 订阅

运行时数据区-方法区

方法区是虚拟机规范定义的运行时数据区域之一,是所有线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。《Java 虚拟机规范》把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做 Non-Heap(非堆),目的是与 Java 堆 区分开来

因为是JVM规范定义,所以不同的JVM厂商,针对自己的JVM可能有不同的方法区实现方式

比如:永久代是 HotSpot 虚拟机在 JDK7 及以前对方法区的具体实现,而永久代也在堆中

只有HotSpot 虚拟机有永久代,其他虚拟机没有永久代这个概念

元空间是HotSpot在JDK8 及以后的方法区实现,元空间不再与堆连续,而且是存在于本地内存(Native memory),并且原来类的静态变量和字符串常量池从 JDK1.7开始都被转移到了java堆区,只有class元数据才在元空间。

问题来了?为什么舍弃了永久代?

oracle收购了JRockit虚拟机所在的公司,并且 想融合 Hotspot 和 JRockit

官方回答: 这是JRockit和Hotspot聚合工作的一部分,JRockit客户不需要永久代(因为JRockit没有永久代),并且习惯于不配置永久代

  • 永久代的垃圾收集是和老年代捆绑在一起的,因此无论谁满了,都会触发永久代和老年代的垃圾收集,并且永久代回收效率低
  • 类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出
  • 字符串存在永久代中,容易出现性能问题和内存溢出

本文就以原空间为本文方法区的实现,展开一篇文章。

特点

  • 类及相关的元数据的生命周期与类加载器的一致
  • 方法区与 Java 堆一样,是所有线程共享的内存区域
  • 方法区用于存放已被虚拟机加载的类信息、常量、静态变量,即编译器编译后的代码
  • 方法区在jvm启动的时候被创建,并且它的实际的物理内存空间中和java堆区一样都是可以不连续的
  • 当JVM加载的类信息容量超过了这个值,会报 OutOfMemoryError:Metaspace,可以通过-XX:MaxPermSize来设定元空间最大可用空间
  • 每个类加载器有专门的存储空间,如果GC发现某个类加载器不再存活了,会把相关的空间整个回收掉
  • 垃圾收集并不会单独回收某个类,省掉了GC扫描及压缩的时间
  • 元空间里的对象的位置是固定的

使用-XX:MetaspaceSize=256m-XX:MaxMetaspaceSize=256m 可以调整方法区的初始化大小和最大可用空间

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值