关于GC之一-JVM内存划分

JVM内存划分

JVM内存的划分网上已经有一大堆,这里根据自己的理解,做一些记录。(大部分知识来源于深入理解JVM虚拟机、Java性能权威指南、Plumbr Handbook Java GC,推荐可以都看看)。
总体来说,JVM的内存分为堆及堆外,堆是javaer关注的重点,而在经历过一些问题之后,意识到堆外也需要多了解。

内存区域划分可以参考这里:
http://gityuan.com/2016/01/09/java-memory/

在这里借鉴其中的两幅图:


图片发自简书App
图片发自简书App

堆外空间

jdk1.8之后,perm区变迁为metaspace。metaspace也是一块堆外空间。

metaspace,在hotspot虚拟机中可以对应为方法区。笨神写过一篇相关的文章,我就不班门弄斧了。可以简单理解为这里存储了编译后的类信息,包含常量池等数据。

参考笨神的文章: http://lovestblog.cn/blog/2016/10/29/metaspace/

其默认大小为1g,对应的常用jvm参数为-XX:MetaspaceSize 和-XX:MaxMetaspaceSize设定大小,但如果不指定MaxMetaspaceSize的话,Metaspace的大小仅受限于native memory的剩余大小。

还有一块不在JVM内存管理范畴之内,即直接内存。为了减少GC、提高数据交换性能引入的,一般在NIO时使用,通过DirectByteBuffer来管理,详见另一偏《堆外内存》的笔记。

堆空间

堆的整体大小指定可以通过-xms和-xmx指定对应的最大最小值。不过对于一般的应用场景,都建议这两个指定的参数值设置相同的值,避免需要频繁扩容,产生过多fgc。

堆空间主要分为两大块,年轻代(young)和老年代(old),其中年轻代又划分为三块区域,eden、survivor0(又称为from)、survivor1(又称为to)。默认年轻代占堆空间的3/8,而年轻代中survivor区域默认占整个年轻代的20%,survivor0和survivor1各占10%,剩余的80%空间给到了eden。详见下图:

1353728416_1655.jpg

对象分配

对象的分配主要在eden区域,当然也不排除eden区域内空间不够时,有大对象直接分配在old区域,这种情况下需要关注大对象的生存周期,避免频繁出现fgc。

eden区域的内存分配是多线程的,但是对于吞吐量比较大的系统,有时一秒钟可以分配上g的内存,如果要在其中再加入锁或者同步,会导致对象的内存分配效率很低。所以jvm引入了tlab,即thread local allocate buffer。它是线程级别的,每个线程在创建的时候都会在堆中分配一块专属的内存区域,用于线程内部的对象内存分配。如果TLAB空间耗完,再需要分配内存时,就需要为线程扩容TLAB。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,366评论 11 349
  • http://www.cnblogs.com/angeldevil/p/3801189.html值得一看 Clas...
    snail_knight阅读 1,449评论 1 0
  • 工作之余,想总结一下JVM相关知识。 Java运行时数据区: Java虚拟机在执行Java程序的过程中会将其管理的...
    Huang远阅读 644评论 0 2
  • Java 虚拟机有自己完善的硬件架构, 如处理器、堆栈、寄存器等,还具有相应的指令系统。JVM 屏蔽了与具体操作系...
    尹小凯阅读 1,706评论 0 10
  • JVM 内存区域 JVM会将Java进程所管理的内存划分为若干不同的数据区域. 这些区域有各自的用途、创建/销毁时...
    CodeKing2017阅读 848评论 0 3