方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的应该是与Java堆区分开来。
对于习惯在HotSpot虚拟机上开发和部署程序的开发者来说,很多人愿意把方法区称为“永久代”(Permanent Generation),本质上两者并不等价,仅仅是因为HotSpot虚拟机的设计团队选择把GC分代收集扩展至方法区,或者说使用永久代来实现方法区而已。对于其他虚拟机(如BEA JRockit、IBM J9等)来说是不存在永久代的概念的。即使是HotSpot虚拟机本身,根据官方发布的路线图信息,现在也有放弃永久代并“搬家”至Native Memory来实现方法区的规划了。
Java虚拟机规范对这个区域的限制非常宽松,除了和Java堆一样不需要连续的内存和可以选择固定大小或者可扩展外,还可以选择不实现垃圾收集。相对而言,垃圾收集行为在这个区域是比较少出现的,但并非数据进入了方法区就如永久代的名字一样“永久”存在了。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载,一般来说这个区域的回收“成绩”比较难以令人满意,尤其是类型的卸载,条件相当苛刻,但是这部分区域的回收确实是有必要的。在Sun公司的BUG列表中,曾出现过的若干个严重的BUG就是由于低版本的HotSpot虚拟机对此区域未完全回收而导致内存泄漏。
根据Java虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。

以上描述截取自:
《深入理解Java虚拟机:JVM高级特性与最佳实践》 作者: 周志明
----------------------------------------------------------------------------------

Inside a Java Virtual Machine instance, information about loaded types is stored in a logical area of memory called the method area. When the Java Virtual Machine loads a type, it uses a class loader to locate the appropriate class file. The class loader reads in the class file--a linear stream of binary data--and passes it to the virtual machine. The virtual machine extracts information about the type from the binary data and stores the information in the method area. Memory for class (static) variables declared in the class is also taken from the method area.
在Java虚拟机中,关于被装载类型的信息存储在一个逻辑上被称为方法区(Method Area)的内存中,当虚拟机装载某个类型时,它使用类装载器定位相应的class文件,然后读入这个class文件——一个线性二进制数据流——然后将它传输到虚拟机中。紧接着虚拟机提取其中的类型信息,并将这些信息存储到方法区(Method Area)。该类型中的类变量(static变量)同样也是存储在方法区(Method Area)中。

The manner in which a Java Virtual Machine implementation represents type information internally is a decision of the implementation designer. For example, multi-byte quantities in class files are stored in big-endian (most significant byte first) order. When the data is imported into the method area, however, a virtual machine can store the data in any manner. If an implementation sits on top of a little-endian processor, the designers may decide to store multi-byte values in the method area in little-endian order.
Java虚拟机在内部如何存储类型信息,这是由具体实现的设计者来决定的。比如,在class文件中,多字节值总是以高位在前的顺序存储。但是当这些数据引入到方法区后,虚拟机可以以任何方式存储它。假设某个实现是运行在低位优先的处理器上,那么它很可能会把多字节值以低位优先的顺序存储到方法区。


The virtual machine will search through and use the type information stored in the method area as it executes the application it is hosting. Designers must attempt to devise data structures that will facilitate speedy execution of the Java application, but must also think of compactness. If designing an implementation that will operate under low memory constraints, designers may decide to trade off some execution speed in favor of compactness. If designing an implementation that will run on a virtual memory system, on the other hand, designers may decide to store redundant information in the method area to facilitate execution speed. (If the underlying host doesnít offer virtual memory, but does offer a hard disk, designers could create their own virtual memory system as part of their implementation.) Designers can choose whatever data structures and organization they feel optimize their implementations performance, in the context of its requirements.
当虚拟机运行Java程序时,它会查找使用存储在方法区中的类型信息。设计者应当为类型信息的内部表示设计恰当的数据结构,以尽可能在保持虚拟机小巧紧凑的同时加快程序的运行效率。如果正在设计一个需要在少量内存的限制中操作的实现,设计者可能会决定以牺牲某些运行速度来换取紧凑性。另外一个方面,如果设计一个将在虚拟内存系统中运行的实现,设计者可能会决定在方法区中保存一些冗余信息,一次来加快执行速度。(如果底层主机没有提供虚拟内存,但是提供了一个硬盘,设计者可能会在实现中创建一个虚拟内存系统。)Java虚拟机的设计者可以根据目标平台的资源限制和需求,在空间和时间上做出权衡,选择实现什么样的数据结果和数据组织。

All threads share the same method area, so access to the method areaís data structures must be designed to be thread-safe. If two threads are attempting to find a class named Lava, for example, and Lava has not yet been loaded, only one thread should be allowed to load it while the other one waits.
由于所有线程都共享方法区,因此它们对方法区数据的访问必须被设计为是线程安全的。比如,假设同时有两个线程都企图访问一个名为Lava的类,而这个类还没有被装入虚拟机,那么,这时只应该有一个线程去装载它,而另一个线程则只能等待。

The size of the method area need not be fixed. As the Java application runs, the virtual machine can expand and contract the method area to fit the applicationís needs. Also, the memory of the method area need not be contiguous. It could be allocated on a heap--even on the virtual machineís own heap. Implementations may allow users or programmers to specify an initial size for the method area, as well as a maximum or minimum size.
方法区的大小不必是固定的,虚拟机可以根据应用的需要动态调整。同样,方法区也不必是连续的,方法区可以在一个堆中自由分配。另外,虚拟机也可以允许用户或者程序员指定方法区的初始大小以及最小和最大尺寸等。


The method area can also be garbage collected. Because Java programs can be dynamically extended via class loader objects, classes can become "unreferenced" by the application. If a class becomes unreferenced, a Java Virtual Machine can unload the class (garbage collect it) to keep the memory occupied by the method area at a minimum. The unloading of classes--including the conditions under which a class can become "unreferenced"--is described in Chapter 7, "The Lifetime of a Class."
方法区也可以被垃圾收集,因为虚拟机允许通过用户定义的类装载器来动态扩展Java程序,因此一些类也会成为程序“不再引用”的类。当某个类变为不再被引用的类时,Java虚拟机可以卸载这个类(垃圾收集),从而使方法区占据的内存保持最小。类的卸载以及一个类变为“不再被引用”的必需条件,都将在第7章中描述。

以上描述截取自:
《Inside the Java Virtual Machine 2nd Edition》 作者:Bill Venners