本篇主要讲解方法区/永久代/元空间这三个概念。
Java内存模型回顾
这是个经典的问题,Java的内存模型是什么样的?
堆
堆是所有线程共享的,主要用来存储对象。其中,堆可分为:年轻代和老年代两块区域。使用NewRatio参数来设定比例。对于年轻代,一个Eden区和两个Suvivor区,使用参数SuvivorRatio来设定大小
栈
线程私有的,主要存放局部变量表,操作数栈,动态链接和方法出口等
程序计数器
同样是线程私有的,记录当前线程的行号指示器,为线程的切换提供保障
方法区
线程共享的,主要存储类信息、常量池、静态变量、JIT编译后的代码等数据。方法区理论上来说是堆的逻辑组成部分
永久代和方法区的关系
涉及到内存模型时,往往会提到永久代,那么它和方法区又是什么关系呢?《Java虚拟机规范》只是规定了有方法区这么个概念和它的作用,并没有规定如何去实现它。那么,在不同的 JVM 上方法区的实现肯定是不同的了。 同时,大多数用的JVM都是Sun公司的HotSpot。在HotSpot上把GC分代收集扩展至方法区,或者说使用永久代来实现方法区。
因此,我们得到了结论,永久代是HotSpot的概念,方法区是Java虚拟机规范中的定义,是一种规范,而永久代是一种实现,一个是标准一个是实现。其他的虚拟机实现并没有永久带这一说法。
在1.7之前,可以使用如下参数来调节方法区的大小:
元空间
对于Java8, HotSpots取消了永久代,那么是不是也就没有方法区了呢?当然不是,方法区是一个规范,规范没变,它就一直在。那么,取代永久代的就是元空间。它可永久代有什么不同的?
存储位置不同,永久代物理是是堆的一部分,和新生代,老年代地址是连续的,而元空间属于本地内存。
存储内容不同,元空间存储类的元信息,静态变量和常量池等并入堆中。相当于永久代的数据被分到了堆和元空间中。