栏目:Java8新特性 作者:admin 日期:2018-10-17 评论:0 点击: 3,484 次
JVM中内存通常划分为两个部分,分别为堆内存与栈内存。
栈内存和Java类中的方法密切相关,它会存储局部变量以及方法调用的中间结果及返回值。Java中的每个线程都有自己专属的栈内存,这是别的线程无法访问的。可以通过JVM选项-Xss来进行调整
堆内存,是Java应用程序中实例化的每个对象所存储的地方。它由所有线程共享。当堆耗尽的时候,JVM会抛出java.lang.OutOfMemoryError 异常。堆的大小可以通过JVM选项-Xms和-Xmx来进行调整。
在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中把存放元数据中的永生代内存从堆内存中移到了本地内存(native memory)中,Java8中JVM堆内存结构就变成了以下所示:
这样永生代内存就不再占用堆内存。它能够通过自己主动增长来避免JDK7以及前期版本号中常见的永生代内存错误(java.lang.OutOfMemoryError: PermGen)。随着Java8的到来,JVM不再有PermGen。但类的元数据信息(metadata)还在,只不过不再是存储在连续的堆空间上,而是移动到叫做“Metaspace”的本地内存(Native memory)中。
类的元数据信息转移到Metaspace的原因是PermGen很难调整。PermGen中类的元数据信息在每次FullGC的时候可能会被收集,但成绩很难令人满意。而且应该为PermGen分配多大的空间很难确定,因为PermSize的大小依赖于很多因素,比如JVM加载的class的总数,常量池的大小,方法的大小等。
------====== 本站公告 ======------
金丝燕网,一个严谨的网站!