方法区就用来存储了每一个类的结构信息,不同的虚拟机实现是不一样的,有些叫永久代,有些称为元空间
1、类型信息
- 类型的全限定名
- 超类的全限定名
- 直接超接口的全限定名
- 类型标志(该类是类类型还是接口类型)
- 类的访问描述符(public、private、default、abstract、final、static)
2、类型常量池
vm为每个已加载的类型都维护一个常量池。常量池就是这个类型用到的常量的一个有序集合,包括实际的常量(string, integer, 和floating point常量)和对类型,域和方法的符号引用。池中的数据项象数组项一样,是通过索引访问的。 因为常量池存储了一个类型所使用到的所有类型,域和方法的符号引用,所以它在java程序的动态链接中起了核心的作用。
3、字段信息
- 字段修饰符(public、protect、private、default)
- 字段的类型
- 字段名称
4、方法信息
- 方法修饰符
- 方法返回类型
- 方法名
- 方法参数个数、类型、顺序等
- 方法字节码
- 操作数栈和该方法在栈帧中的局部变量区大小
- 异常表
5、类变量(静态变量)
就是类的静态变量,它只与类相关,所以称为类变量 。在jvm使用一个类之前,它必须在方法区中为每个non-final类变量分配空间。
6、指向类加载器的引用
jvm必须知道一个类型是由启动加载器加载的还是由用户类加载器加载的。如果一个类型是由用户类加载器加载的,那么jvm会将这个类加载器的一个引用作为类型信息的一部分保存在方法区中。每一个被JVM加载的类型,都保存这个类加载器的引用,类加载器动态链接时会用到。
类加载器加载完某个类后,将这个类的一些信息保存在方法区,并将这个类加载器的一个引用作为类型信息的一部分保存在方法区中
7、指向Class实例的引用
jvm为每个加载的类型(译者:包括类和接口)都创建一个java.lang.Class的实例。而jvm必须以某种方式把Class的这个实例和存储在方法区中的类型数据联系起来。
例如,假如你有一个java.lang.Integer的对象引用,可以激活getClass()得到对应的类引用
类加载的过程中(通过new 或者Class.forName方式加载某个类),虚拟机会创建该类型的Class实例,方法区中必须保存对该对象的引用。通过Class.forName(String className)来查找获得该实例的引用,然后创建该类的对象
8、方法表
9、运行时常量池