跳到主要内容

09、JVM 实战 - 运行时内存篇,方法区

1、堆、栈、方法区的关系

 

 

2、方法区在哪里

《Java虚拟机规范》中明确说明: “尽管所有的方法区在逻辑上是属于堆的一部分,但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩。” 但对于HotSpotJVM而言,方法区还有一个别名叫做Non-Heap(非堆),目的就是要和堆分开。所以,方法区看作是一块独立于Java堆的内存空间。

3、方法区的理解

1、 方法区(MethodArea)与Java堆一样,是各个线程共享的内存区域;
2、 方法区在JVM启动的时候被创建,并且它的实际的物理内存空间中和Java堆区一样都可以是连续的;
3、 方法区的大小,跟堆空间一样,可以选择固定大小或者可扩展;
4、 方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类,导致方法区溢出,虚拟机同样会抛出内存溢出错误:java.lang.OutofMemoryError:PermGenspace或者java.lang.OutOfMemoryError:Metaspace(加载大量的第三方的jar包;Tomcat部署的工程过多(30-59个);大量动态的生成反射类);
5、 关闭JVM就会释放这个区域的内存;

4、HotSpot方法区的演进

在jdk1.7及之前,习惯上把方法区称为永久代。jdk1.8开始,使用元空间代替了永久代。

5、方法区的常用参数

方法区的大小不必是固定的,JVM可以根据应用的需要动态调整。
jdk7及以前:
-XX:PermSize来设置永久代初始分配空间。默认值是20.75M
-XX:MaxPermSize来设定永久代最大可分配空间。32位机器默认是64M,64位机器模式是82M
当JVM加载的类信息容量超过了这个值,会报异常OutofMemoryError:PermGenspace

jdk8及以后:
元数据区大小可以使用参数-XX:MetaspaceSize和-Xx:MaxMetaspaceSize指定,替代上述原有的两个参数。
默认值依赖于平台。windows下,-XX:MGtaspaceSize是21M,-XX:MaxMetaspaceSize的值是-1,即没有限制。
与永久代不同,如果不指定大小,默认情况下,虚拟机会耗尽所有的可用系统内存。如果元数据区发生溢出,虚拟机一样会抛出异常OutOfMemoryError:Metaspace

6、方法区存些什么

类型信息
域(Field)信息
方法信息
non-final的类变量
运行时常量池:常量池,可以看做是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等类型。

7、永久代和元空间

为什么要用元空间代替永久代?

1、 对永久代设置空间大小是很难确定的在某些场景下,如果动态加载类过多,容易产生Perm的OOM比如某个实际web工程中,因为功能点比较多,在运行过程中,要不断动态加载很多类经常出现java.lang.OuOfMemoryError:PermGenspace,而元空间和永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存因此,默认情况下,元空间的大小仅受本地内存限制;
2、 对永久代进行调优是很困难的;