Java基础-JVM内存管理-Class对象与Class数据

Java工程师知识树 / Java基础


创建对象时符号引用指向了方法区的Class数据,还是堆内存中Class对象?

首先要分清楚方法区中的类数据和堆中Class对象的区别。

堆Class对象本质上是对方法区类型数据的一个访问接口。在Java类文件(除了数组类型)的加载过程中,首先会把.class二进制文件转化为方法区的运行时数据结构,然后会在Java堆内存中实例化一个java.lang.Class类的对象,用来访问方法区中的类型数据。因此,堆中的Class并不存储静态变量、常量、方法等实际信息。创建对象时符号表引用指向的类肯定是方法区中的类数据,因为没有必要通过Class对象来间接访问方法区,这样需要两次引用解析,开销更大。

创建好的对象的对象头里存放的类型指针指向的是方法区中类型数据还是堆内存的Class对象?

首先要搞清楚,对象为什么要引用方法区中的类型数据?

  • 进行类型强转(cast)操作或者instanceof判断时,虚拟机需要查看目标类型是不是当前对象的类型或者父类之一。
  • 当调用实例方法时,需要进行动态绑定,动态绑定的过程需要类的信息。

和上一问一样,我们需要引用的最终目标是方法区中类有关的信息,所以类型指针直接指向方法区中的类型数据。

如果类型指针指向的是方法区中的类数据,那么这个在堆中的Class对象又有什么用?

Class对象为程序员提供了查看方法区类型信息的接口, 如类名,当前对象的父类,方法,变量等。对于同一个ClassLoader, 只存在一个Class对象。Class对象可以通过两种方法获得:

  • 根据实例对象获得:ref.getClass()
  • 根据类名获得:ClassName.class , 基本类型只可以通过这种方式获得Class对象。

new操作返回的instanceOopDesc类型指针指向instanceKlass,而instanceKlass指向了对应的类型的Class实例的instanceOopDesc;既然已经指向了方法区的类数据,那为什么还要指回Class实例?

因为对象指向的是方法区,所以要想得到Class实例的引用,就必须通过方法区的数据,instanceKlass保留对Class实例的引用是必要的。

你可能感兴趣的:(Java基础-JVM内存管理-Class对象与Class数据)