• JVM之方法区


    JVM之方法区

    Java虚拟机内存区域模型

    **黄色区域:**所有线程共享的内存区域,会存在垃圾回收。

    **灰色区域:**线程私有不会产生垃圾回收。

    方法区是运行时数据区中的一部分,那么方法区具体的用途是什么呢?方法区能存放什么信息呢?

    方法区是什么

    方法区和堆一样是被所有的线程所共享,有的地方将方法区称之为Non-Heap(非堆),其目的就是将方法区与堆内存区分开来,在JDK1.7中很多开发者将方法区称之为永久代,但本质上两者并不是等价的,仅仅是因为HotSpot虚拟机的设计团队将GC分代收集扩展至方法区,或者说使用永久代来实现方法区而已,这样HotSpot的垃圾收集器可以像管理堆内存一样管理永久代内存了,其余非HotSpot的虚拟机是没有永久代这个概念的

    HotSpot方法区演进

    方法区在jdk7及以前,习惯将永久代称之为方法区,结构如下所示

    在jdk1.8中采用了Metaspace(元数据空间)替换了Perm(永久区),并且从堆空间分离出来,结构如下所示

    一定一定需要注意的是Metaspace(元数据空间)不再存储到堆中,也不使用JVM内存空间而是采用本机的内存,这样元数据只受本地内存大小限制,OOM的问题就不存在了。

    为什么JDK1.8需要将方法区从JVM永久代(非直接内存)移到元空间(直接内存)呢?

    • JVM永久代存在容量限制,那么类信息存储的容量有限制容易触发OOM,而采用元空间存储,只受本地内存大小限制OOM的可能性小。

    • 因为是直接内存,JVM将会在IO操作上具有更高的性能,因为它直接作用于本地操作系统的IO操作,而堆内存做IO操作,先需要将数据复制到直接内存,再利用IO处理,而直接内存不需要这层转换。

    堆栈和方法区的交互

    如我们常常构建的业务对象,以Car对象为例

    当我们在代码中创建一个Car实例对象后,将会在堆、栈、方法区内存空间分别写入数据

    • Car:是对象模板,为Class对象,存放在方法区中。

    • car:属于引用数据,存放栈空间中。

    • new Car():需要在堆中开辟一片空间,存放在堆中。

    方法区存放什么数据

    方法区存放的数据主要是被类加载器加载后的类信息,运行时常量池等等。

    其中有两个点需要注意

    • 静态变量,在JDK1.8以前静态变量都是存在永久代内存中,JDK1.8后采用元空间替代永久代,==就将静态变量从永久代转移到了堆空间==。

    • 常量池,在JDK1.7之前运行时常量池逻辑包含了字符串常量池存放在永久代中,JDK1.7将字符串常量池转移到了堆内存中,注意这时并没有提到运行时常量池,也就是说运行时常量池还存在永久代中,JDK1.8将永久代移除用元空间代替,这时运行时常量池就存在元空间中了。

    那么类信息又包括什么东西呢?

    • 类信息

    • 类的完整名字

    • 类的直接父类完整名字

    • 类的直接实现接口有序列表

    • 类型标识(是类还是接口)

    • 类的访问修饰符(public、private等等)

    • 类型常量池

    • 存放该类型用到的常量有序集合,包括直接常量(字符串、浮点、整型),和对其它类型、字段、方法的符号引用。

    • 字段信息

    • 字段类型、名称、访问修饰符等

    • 方法信息

    • 类的所有方法

    • 方法返回类型、方法访问修饰符、方法名称等等

    • 类变量

    • 指向类加载器的引用

    • 指向Class实例的引用

    • 方法表

  • 相关阅读:
    7 航空公司客户价值分析
    《计算机操作系统-第二章》之操作系统的运行机制与体系结构
    burp || Note: Disk-based projects are onlysupported on Burp Suite Professional
    环形进度条组件
    Java面向对象,全程无废话,偏实战
    体验一下阿里云文字识别OCR
    TCP套接字【网络】
    GD32F103 ADC
    OA项目之会议排座和送审
    Visual Studio Cpp CLR C# 替换
  • 原文地址:https://blog.csdn.net/zzf1233/article/details/125512213