java8JVM

首先简单介绍一下JVM中内存的划分

JVM中内存通常划分为两个部分,分别为堆内存与栈内存。
栈内存和Java类中的方法密切相关,它会存储局部变量以及方法调用的中间结果及返回值。Java中的每个线程都有自己专属的栈内存,这是别的线程无法访问的。可以通过JVM选项-Xss来进行调整
堆内存,是Java应用程序中实例化的每个对象所存储的地方。它由所有线程共享。当堆耗尽的时候,JVM会抛出java.lang.OutOfMemoryError 异常。堆的大小可以通过JVM选项-Xms和-Xmx来进行调整。
 

回顾一下旧版本JDK中堆内存划分

在JDK7以及其前期的JDK版本号中。堆内存通常被分为三块区域:新生代内存(young generation)、老生代(old generation)、永生代(Permanent Generation for VM Matedata),例如以下图:
 
上图所示堆内存被分为:
Eden区 —— 新对象或者生命周期很短的对象会存储在这个区域中,这个区的大小可以通过-XX:NewSize和-XX:MaxNewSize参数来调整。新生代GC(垃圾回收器)会清理这一区域。
Survivor区 —— 那些历经了Eden区的垃圾回收仍能存活下来的依旧存在引用的对象会待在这个区域。这个区的大小可以由JVM参数-XX:SurvivorRatio来进行调节。
Old Generation老年代 —— 那些在历经了Eden区和Survivor区的多次GC后仍然存活下来的对象会存储在这个区里。这个区会由一个特殊的垃圾回收器来负责。年老代中的对象的回收是由老年代的GC(major GC)来进行的。
永生代 —— 存放着对象的方法、变量等元数据信息。如果永生代内存不够,我们就会得到例如以下错误:java.lang.OutOfMemoryError: PermGen

java8的内存结构的新特性:再见PermGen,你好Metaspace

Java8中把存放元数据中的永生代内存从堆内存中移到了本地内存(native memory)中,Java8中JVM堆内存结构就变成了以下所示:
  
这样永生代内存就不再占用堆内存。它能够通过自己主动增长来避免JDK7以及前期版本号中常见的永生代内存错误(java.lang.OutOfMemoryError: PermGen)。随着Java8的到来,JVM不再有PermGen。但类的元数据信息(metadata)还在,只不过不再是存储在连续的堆空间上,而是移动到叫做“Metaspace”的本地内存(Native memory)中。
类的元数据信息转移到Metaspace的原因是PermGen很难调整。PermGen中类的元数据信息在每次FullGC的时候可能会被收集,但成绩很难令人满意。而且应该为PermGen分配多大的空间很难确定,因为PermSize的大小依赖于很多因素,比如JVM加载的class的总数,常量池的大小,方法的大小等。

Metaspace的参数设置

当然Java8也提供了一个新的设置Matespace内存大小的參数。通过这个參数能够设置Matespace内存大小,这样我们能够依据自己项目的实际情况,避免过度浪费本地内存,达到有效利用:
-XX:MaxMetaspaceSize=128m 设置最大的元内存空间128m。如果你设置的元内存空间过小,你的应用程序可能得到下面错误:
java.lang.OutOfMemoryError: Metadata space

你可能感兴趣的:(JVM)