JVM 系列 - 内存区域 - 方法区(六)

2018-12-19  本文已影响0人  _晓__

特点

Java 中基本类型的包装类的大部分都实现了常量池技术,这些类是 Byte、Short、Integer、Long、Character、Boolean,另外 Float 和 Double 类型的包装类则没有实现。另外 Byte、Short、Integer、Long、Character 这5种整型的包装类也只是在对应值在-128到127之间时才可使用对象池。

运行时常量池

随JDK版本变迁的方法区

JDK6

JDK7

JDK8

关于 Open JDK 移除永久代的相关信息:http://openjdk.java.net/jeps/122

类信息

方法区 详细信息
类型信息 1. 类型的全限定名 2. 超类的全限定名 3. 直接超接口的全限定名 4. 类型标志(该类是类类型还是接口类型) 5. 类的访问描述符(public、private、default、abstract、final、static)
类型的常量池 存放该类型所用到的常量的有序集合,包括直接常量(如字符串、整数、浮点数的常量)和对其他类型、字段、方法的符号引用。常量池中每一个保存的常量都有一个索引,就像数组中的字段一样。因为常量池中保存中所有类型使用到的类型、字段、方法的符号引用,所以它也是动态连接(栈中对应的方法指向这个引用)的主要对象(在动态链接中起到核心作用)。
字段信息 1. 字段修饰符(public、protect、private、default) 2. 字段的类型 3. 字段名称
方法信息 1. 方法名 2.方法的返回类型(包括void)3. 方法参数的类型、数目以及顺序 4. 方法修饰符(public、private、protected、static、final、synchronized、native、abstract) 5. 针对非本地方法,还有些附加方法信息需要存储在方法区中(局部变量表大小和操作数栈大小、方法体字节码、异常表)
类变量(静态变量) 指该类所有对象共享的变量,即使没有创建该对象实例,也可以访问的类变量。它们与类进行绑定
指向类加载器的引用 JVM 必须知道一个类型是由启动加载器加载的还是由用户类加载器加载的。如果一个类型是由用户类加载器加载的,那么 JVM 会将这个类加载器的一个引用作为类型信息的一部分保存在方法区中。JVM 在动态链接的时候需要这个信息。当解析一个类型到另一个类型的引用的时候,JVM 需要保证这两个类型的类加载器是相同的。这对 JVM 区分名字空间的方式是至关重要的。
指向 Class 实例的引用 JVM 为每个加载的类和接口都创建一个 java.lang.Class 实例(JDK6 存储在方法区,JDK6 之后存储在 Java 堆),这个对象存储了所有这个字节码内存块的相关信息,如平时使用的 this.getClass().getName() this.getClass().getDeclaredMethods() this.getClass().getDeclaredFields(),可以获取类的各种信息,都是通过这个 Class 引用获取。
方法表 为了提高访问效率,必须仔细的设计存储在方法区中的数据信息结构。除了以上讨论的结构,JVM 的实现者还可以添加一些其他的数据结构,如方法表。JVM 对每个加载的非虚拟类的类型信息中都添加了一个方法表,方法表是一组对类实例方法的直接引用(包括从父类继承的方法)。JVM 可以通过方法表快速激活实例方法。(这里的方法表与 C++ 中的虚拟函数表一样。正像 Java 宣称没有指针了,其实 Java 里全是指针。更安全只是加了更完备的检查机制,但这都是以牺牲效率为代价的,Java 的设计者始终是把安全放在效率之上的,所有 Java 才更适合于网络开发)

疑问?

Class 对象存储在哪个区域?

上一篇下一篇

猜你喜欢

热点阅读