在Java虚拟机中, 关于被装载类的信息存储在一个逻辑上被称为方法区的内存中。 当虚拟机加载某个类型时,它使用类加载器定位相应的class文件,然后读入这个class文件——一个线性二进制数据流,然后将它传输到虚拟机中 ,紧接者虚拟机提取其中的类型信息, 并将这些信息存储到方法区。该类型中的类(静态)变量同样也是存储在方法区中。
由于所有线程都共享方法区, 因此它们对方法区数据的访问必须被设计为是线程安全的 。假设同时有两个线程都企图访问一个类, 而这个类还投有被装入虚拟机, 那么,这时只应该有一个线程去加载它,而另一个线程则只能等待。
方法区的大小不必是固定的, 虚拟机可以根据应用的需要动态调整。同样, 方法区也不必是連续的, 方法区可以在一个堆(甚至是虚担机自已的谁)中自由分配。 另外, 虚拟机也可以允许用户或者程序员指定方法区的初始大小以及最小和最大尺寸等 。
方法区也可以被垃圾收集, 因为虚拟机允许通过用户定又的类加载器来动态扩展Java程序, 因此一些类也会成为程序“不再引用”的类。当某个类变为不再被引用的类时, Java虚拟机可以卸裁这个类(垃圾收集),从而使方法区占据的内存保持最小。
运行时常量池
运行时常量池(RuntimeConstant Pool)是方法区的一部分。 Class文件中除了有类的版本、字段、方法、接口等描述等信息外。还有一项信息是常量池(ConstantPooI Tabte), 用于存放编译期生成的各种字面量和符号引用, 这部分内容将在类加载后存放到方法区的运行时常量池中 。
类型信息
类型信息
对每个装载的类, Java虚拟机都会在方法区中存储以下类型信息:
- 这个类的全限定名
- 这个类的直接超类的全限定名(除非这个类型是java.]ang.0t,ject,它没有超类)。
- 这个类是类类型还是接口类型
- 这个类的访问修饰符( public、 abstract或final的某个子集)。
- 任何直接超接口的全限定名的有序列表
在Java class文件和虚拟机中, 类型名总是以全限定名出现。 在Java源代码中,全限定名由类所属包的名称加一个“.”,再加上类名组成。例如,类0bject的所属包为java.iang,那它的全限定名应该是java.lang.0bject,但在class文件里,所有的“.”都被斜杠 “/”代替,这样就成为java/lang/0bject。 至于全限定名在方法区中的表示, 则因不同的设计者有不同的选择而不同, 可以用任何形式和数据结构来代表。
参考:
http://www.hollischuang.com/archives/80