Java 元空间与永久代

永久代:

java7及以前版本中JVM内存区域中的方法区的称呼,本质上两者不等价,仅因为Hotspot将GC分代扩展至方法区,或者说使用永久代来实现方法区。在他虚拟机上是没有永久代的概念的,永久代是Hotspot针对该规范进行的实现。

HotSpot:我们通常使用的Java SE都是由Sun JDK和OpenJDK所提供,这也是应用最广泛的版本。 而该版本使用的VM就是HotSpot VM。简单来说,我们所讲的java虚拟机指的就是HotSpot的版本。

Java7及以前版本的Hotspot中方法区位于永久代中。同时,永久代和堆在逻辑上是相互隔离的,但它们使用的物理内存是连续的。永久代的垃圾收集是和老年代捆绑在一起的,因此无论谁满了,都会触发永久代和老年代的垃圾收集。
但是在Java8中取消了永久代,使用元空间来代替

java7 的JVM内存结构
Java7

在这里插入图片描述

元空间:

对于Java8,HotSpots取消了永久代,那么是不是就没有方法区了呢?当然不是,方法区只是一个规范,只不过它的实现变了。

在Java8中,元空间(Metaspace)登上舞台,方法区存在于元空间(Metaspace)。同时,元空间不再与堆连续,而且是存在于本地内存(Native memory)。

本地内存(Native memory),也称为C-Heap,是供JVM自身进程使用的。当Java Heap空间不足时会触发GC(Garbage collection,垃圾回收),但Native memory空间不够却不会触发GC。

在这里插入图片描述
元空间存在于本地内存,意味着只要本地内存足够,它不会出现像永久代中“java.lang.OutOfMemoryError: PermGen space”这种错误。
默认情况下元空间是可以无限使用本地内存的,但为了不让它如此膨胀,JVM同样提供了参数来限制它使用的使用。

-XX:MetaspaceSize,class metadata的初始空间配额,以bytes为单位,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当的降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize(如果设置了的话),适当的提高该值。

-XX:MaxMetaspaceSize,可以为class metadata分配的最大空间。默认是没有限制的。

-XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为class metadata分配空间导致的垃圾收集。

-XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为class metadata释放空间导致的垃圾收集。

为什么永久代被被替换了?

表面上看是为了避免OOM异常。因为通常使用PermSize和MaxPermSize设置永久代的大小就决定了永久代的上限。但是,不是总能知道应该设置为多大合适, 如果使用默认值很容易遇到OOM错误。

当使用元空间时,可以加载多少类的元数据就不再由MaxPermSize控制, 而由系统的实际可用空间来控制。

更深层的原因还是要合并HotSpot和JRockit的代码,JRockit从来没有所谓的永久代,也不需要开发运维人员设置永久代的大小,但是运行良好。同时也不用担心运行性能问题了,在覆盖到的测试中, 程序启动和运行速度降低不超过1%,但是这点性能损失换来了更大的安全保障。

参考地址:原文

java8 JVM内存空间结构

在这里插入图片描述
那么一个Java进程最大占用的物理内存为:

Max Memory = eden + survivor + old + String Constant Pool + Code cache + compressed class space + Metaspace + Thread stack(*thread num) + Direct + Mapped + JVM + Native Memory

### Java 空间方法区的关系及区别 #### 方法区的概念 方法区是《Java虚拟机规范》中定义的一个逻辑区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的码等数据。不同的虚拟机实现可能会采用不同的方式来具体实现这一抽象概念。 #### 永久的历史背景 在JDK 7及其之前版本中,HotSpot虚拟机使用了一种名为“永久”的内存模型来实现方法区的功能[^4]。这种设计允许垃圾回收机制如同对待堆中的对象一样处理这些数据,简化了内存管理优化工作。 #### 空间的新特性 自JDK 8起,为了更好地适应现硬件架构并提高性能表现,HotSpot VM引入了一个新的运行时组件——空间(Metaspace)[^1]。相比于之前的永久: - **位置差异**:空间位于本地内存(Native Memory)而非传统的Java堆内;这减少了GC压力,并且避免了由于频繁调整堆尺寸带来的开销。 - **灵活性增强**:不再受限于固定大小,可根据实际需求自动增长或收缩其容量范围; - **配置变化**:原有的针对永久设置的相关参数已失效,转而提供了专门控制空间行为的新选项[^3]。 因此,在JDK 8之后,“空间”成为了HotSpot JVM内部对于方法区的具体实现形式之一,取了早期版本中存在的“永久”。 ```java // 示例展示如何查看当前使用的空间大小 public class MetaspaceExample { public static void main(String[] args) throws Exception{ RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean(); List<String> arguments = runtimeMxBean.getInputArguments(); boolean isMetaspaceUsed = false; for (String arg : arguments){ if(arg.startsWith("-XX:MaxMetaspaceSize=")){ System.out.println("Current Max Metaspace Size:" + arg.substring(20)); isMetaspaceUsed=true; } } if(!isMetaspaceUsed){ System.out.println("Default Metaspace size will be used."); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值