Broad Broad
首页
  • 中间件相关

    • RabbitMQ
前端
JVM
杂文
八股文
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Wang Bu Zheng

开发农名工
首页
  • 中间件相关

    • RabbitMQ
前端
JVM
杂文
八股文
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 类的加载

  • Jvm内存结构

    • 程序计数器
    • 虚拟机栈
    • 本地方法栈
    • 堆
    • 方法区
  • GC垃圾回收

  • JVM
  • Jvm内存结构
WangBuZheng
2023-02-03
目录

方法区

# 一. 概述

  • 方法区(Method Area)与堆一样,也是所有线程共享的内存区域。
  • 《Java虚拟机规范》明确: 尽管多有的方法区在逻辑上属于堆的一部分,但简单的实现可能不会选择去进行垃圾收集或者进行压缩。 所以方法区看做是一块独立于Java堆的内存空间
  • 方法区的大小,跟堆一样可以选择固定大小或者可扩展
  • 方法区在JVM启动的时候被创建,并且它的实际的物理内存空间中和Java堆区一样都可以是不连续的。
  • 关闭JVM就会释放这个区域的内存。

# 二. 方法区大小的设置

jdk1.8:

  • -XX:MetaspaceSize 设置初始的元空间大小

  • -XX:MaxMetaspaceSize 设置最大的元空间大小

# 三. 方法区内存结构

方法区用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。以下做详细介绍:

# 3.1 类型信息

对每个加载的类型(类class、接口interface、枚举enum、注解annotation)。JVM必须在方法区中存储以下类型信息。

  • 这个类型的完整有效名称。
  • 这个类型直接父类的完整有效名。
  • 这个类型的修饰符(public、abstract、final的某个子集)。
  • 这个类型直接接口的一个有序列表。

# 3.2 方法信息

JVM 必须保存所有方法:

  • 方法名称。
  • 方法的返回类型。
  • 方法参数的数量和类型。
  • 方法的修饰符(public,private,protected,static,final,synchronized,native,abstract 的一个子集)
  • 方法的字符码(bytecodes)、操作数栈、局部变量表及大小(abstract 和 native 方法除外)异常表(abstract 和 native 方法除外)
    • 每个异常处理的开始位置、结束位置、代码处理在程序计数器中的偏移地址、被捕获的异常类的常量池索引。

# 3.3 域信息

JVM 必须在方法区中保存类型的所有域的相关信息以及域的声明顺序

  • 域的相关信息包括:域名称、域类型、域修饰符(public、private、protected、static、final、volatile、transient 的某个子集)

# 3.4 运行时常量池

字节码文件内部包含了常量池。 方法区内部包含了运行时常量池。当字节码加载过后到方法区 常量池也就变成了运行时常量池。

# 3.4.1 class文件中的常量池(Constant Poll)

  • 一个有效的字节码文件除了包含类的版本信息、字段、方法以及接口等描述信息,还包含一项信息就是常量池(Constant Pool Table)。包含各种字面量和对类型、域和方法的符号引用。 如下图所示:

  • 常量池内存储的数据类型包括:

    • 数量值
    • 字符串值
    • 类引用
    • 字段引用
    • 方法引用

    # 3.4.2 运行时常量池小节

    • 常量池表(Constant Poll Table)是Class文件的一部分,用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区运行时常量池中。
    • 运行时常量池中包含多种不同的常量,包含编译器就已经明确的数值字面量,也包括到运行期解析后才能够获得的方法或者字段引用。此时不再是常量池中的符号地址,这里换位真是地址。

    # 四. 方法区的垃圾收集

    方法区的垃圾收集主要回收两部分内容: 常量池中废弃的常量和不在使用的类型

    方法区内常量池之中主要存放的两大类常量:字面量和符号引用。字面量比较接近 Java 语言层次的常量概念,如文本字符串、被声明为 final 的常量值等。而符号引用则属于编译原理方面的概念,包括下面三类常量:

    • 类和接口的全限定名
    • 字段的名称和描述符
    • 方法的名称和描述符

    HotSpot 虚拟机对常量池的回收策略是很明确的,只要常量池中的常量没有被任何地方引用,就可以被回收

    判定一个类型是否属于“不再被使用的类”,需要同时满足三个条件:

    • 该类所有的实例都已经被回收,也就是 Java 堆中不存在该类及其任何派生子类的实例。
    • 加载该类的类加载器已经被回收,这个条件除非是经过精心设计的可替换类加载器的场景,如 OSGi、JSP 的重加载等,否则通常很难达成。
    • 该类对应的 java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
总结

方法区是否被GC,《Java虚拟机规范》没有明确规定。所以可以回收也可以不回收。而需要回收时回收的是常量池中废弃的常量和不在使用的类型

编辑 (opens new window)
#JVM
上次更新: 2023/02/04, 14:30:19
堆
垃圾回收算法-标记

← 堆 垃圾回收算法-标记→

最近更新
01
垃圾回收算法-清除
03-28
02
垃圾回收算法-标记
02-13
03
堆
01-30
更多文章>
Theme by Vdoing | Copyright © 202102-2023 Broad-Bean | 豫ICP备2022009421号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式