关于jvm方法区

先以两个问题开篇:

1.如果一个类有多个子类,那么new多个子类对象时,父类的对象是一个还是多个?

2.每个类型有一个常量池,还是每个对象都有自己的常量池?

你可以很快地正确回答吗?了解了java虚拟机方法区的原理,这两个问题就很清晰了。

java虚拟机把内存划分为方法区、堆和线程栈。简单说方法区用来存储类型的元数据信息,一个.class文件是类被java虚拟机使用之前的表现形式,一旦这个类要被使用,java虚拟机就会对其进行装载、连接(验证、准备、解析)和初始化。而装载(这里涉及到类加载器的相关理论)后的结果就是由.class文件转变为方法区中的一段特定的数据结构。这个数据结构会存储如下信息:

类型信息

这个类型的全限定名

这个类型的直接超类的全限定名

这个类型是类类型还是接口类型

这个类型的访问修饰符

任何直接超接口的全限定名的有序列表

字段信息

字段名

字段类型

字段的修饰符

方法信息

方法名

方法返回类型

方法参数的数量和类型(按照顺序)

方法的修饰符


除了常量以外的所有类(静态)变量

一个指向ClassLoader的指针

一个指向Class对象的指针

类型的常量池(这里就回到了开篇时的第二个问题):常量数据以及对其他类型的符号引用。


每个类的这些元数据,无论是在构建这个类的实例还是调用这个类某个对象的方法,都会访问方法区的这些元数据。

构建一个对象时,jvm会在堆中给对象分配空间,这些空间用来存储当前对象实例属性以及其父类的实例属性(而这些属性信息都是从方法区获得),注意,这里并不是仅仅为当前对象的实例属性分配空间,还需要给父类的实例属性分配,到此其实我们就可以回答第一个问题了,即实例化父类的某个子类时,jvm也会同时构建父类的一个对象。从另外一个角度也可以印证这个问题:调用当前类的构造方法时,首先会调用其父类的构造方法直到Object,而构造方法的调用意味着实例的创建,所以子类实例化时,父类肯定也会被实例化。


posted on 2011-08-14 12:17  wenfeng762  阅读(1753)  评论(0编辑  收藏  举报