定义
方法区是所有java线程所共享的一块内存区域。这块区域内存储了类结构相关的信息,包括,运行时常量池,字段,方法数据,方法代码,构造方法,特殊方法等等。
方法区在虚拟机启动时创建,逻辑上是堆的一部分,但是不同的jvm实现不一定会严格遵守这一原则。jdk1.6把方法区放在了堆中(叫做永久代),而jdk1.8则把方法区放在了本地内存(叫做元空间,metaspace)。具体如下图所示(该图截取自黑马程序员jvm课程):
最后,如果方法区内存溢出,则会抛出OutOfMemoryError异常。
什么情况容易出现方法区溢出
JDK1.8之后方法区存放在了本地内存上,由于现在计算机的内存大小都比较大,所以很难出现方法区溢出,我们必须添加jvm参数,手动将方法区调小,才有可能出现溢出错误。指令如下:
-XX:MaxPerSize=8m(适用于1.8以前)
-XX:MaxMetaspaceSize=8m(适用于1.8及以后)
将内存大小调小后,如果此时我们的项目定义了大量的类和方法,或者说加载了大量的的动态类,那么就会出现溢出。
常量池
就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息
运行时常量池
常量池信息存在.class文件中,当该类被加载后,它的常量池信息就会被加载到内存中,成为运行时常量池,并且里面的#1,#2这种符号会被替换为真实的内存地址。