1.方法区
说到方法区肯定需要了解《Java虚拟机规范》中对内存管理的划分。如图所示
这是《规范》中对内存的具体划分,说白了这只是个规范,是理论的东西。具体的实现因人而异。因此不同的jvm实现方法区的方式不同,甚至不同版本的实现也不同。目前除了openjdk和甲骨文的hotspotvm,商业上说得出名字的jdk只有IBM的j9vm和Azul的zingvm了。hotspotvm 的JDK 1.7、JDK 1.8实现就不同
2.永久代和元空间
永久代和元空间就是hotspot的不同版本的实现方式,分别属于JDK 1.7之前和之后。
PermGen(永久代)
永久代是hotspot 的jdk1.8以前的实现,使用jdk1.7的老司机肯定以前经常遇到过“java.lang.OutOfMemoryError: PremGen space”异常。这里的“PermGen space”其实指的就是方法区。不过方法区和“PermGen space”又有着本质的区别。前者是JVM的规范,而后者则是JVM规范的一种实现,并且只有HotSpot才有“PermGen space”。
元空间
其实,移除永久代的工作从JDK 1.7就开始了。JDK 1.7中,存储在永久代的部分数据就已经转移到Java Heap或者Native Heap。但永久代仍存在于JDK 1.7中,并没有完全移除,譬如符号引用(Symbols)转移到了native heap;字面量(interned strings)转移到了Java heap;类的静态变量(class statics)转移到了Java heap。
JDK1.8对JVM架构的改造将类元数据放到本地内存中,另外,将常量池和静态变量放到Java堆里。HotSpot VM将会为类的元数据明确分配和释放本地内存。在这种架构下,类元信息就突破了原来-XX:MaxPermSize的限制,现在可以使用更多的本地内存。
对于僵死的类及类加载器的垃圾回收将在元数据使用达到“MaxMetaspaceSize”参数的设定值时进行。
适时地监控和调整元空间对于减小垃圾回收频率和减少延时是很有必要的。持续的元空间垃圾回收说明,可能存在类、类加载器导致的内存泄漏或是大小设置不合适
3.使用元空间的优点
1.不会出现“java.lang.OutOfMemoryError: PremGen space”异常
2.字符串常量池迁移到堆中,避免溢出
3,永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。
4.通过类加载器来控制垃圾回收。