九、运行时内存篇——方法区
1、堆、栈、方法区的关系
2、方法区在哪里
《Java虚拟机规范》中明确说明: “尽管所有的方法区在逻辑上是属于堆的一部分,但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩。” 但对于HotSpotJVM而言,方法区还有一个别名叫做Non-Heap(非堆),目的就是要和堆分开。所以,方法区看作是一块独立于Java堆的内存空间。
3、方法区的理解
1、方法区(Method Area)与Java堆一样,是各个线程共享的内存区域。
2、方法区在JVM启动的时候被创建,并且它的实际的物理内存空间中和Java堆区一样都可以是连续的。
3、方法区的大小,跟堆空间一样,可以选择固定大小或者可扩展。
4、方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类,导致方法区溢出,虚拟机同样会抛出内存溢出错误:java.lang.OutofMemoryError:PermGen space 或者 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