zoukankan      html  css  js  c++  java
  • 堆内存结构是怎么样的?

    站在垃圾收集器的角度来看,可以把内存分为新生代与老年代。内存的分配规则取决于当前使用的是哪种垃圾收集器的组合,以及内存相关的参数配置。往大的方向说,对象优先分配在新生代的Eden区域,而大对象直接进入老年代。

    第一, 新生代的Eden区域,对象优先分配在该区域,同时JVM可以为每个线程分配一个私有的缓存区域,称为TLAB(Thread Local Allocation Buffer),避免多线程同时分配内存时需要使用加锁等机制而影响分配速度。TLAB在堆上分配,位于Eden中。

    第二、新生代的Survivor区域。当Eden区域内存不足时会触发Minor GC,也称为新生代GC,在Minor GC存活下来的对象,会被复制到Survivor区域中。我认为Survivor区的作用在于避免过早触发Full GC。如果没有Survivor,Eden区每进行一次Minor GC都把对象直接送到老年代,老年代很快便会内存不足引发Full GC。新生代中有两个Survivor区,我认为两个Survivor的作用在于提高性能,避免内存碎片的出现。在任何时候,总有一个Survivor是empty的,在发生Minor GC时,会将Eden及另一个的Survivor的存活对象拷贝到该empty Survivor中,从而避免内存碎片的产生。

    第三、老年代。老年代放置长生命周期的对象,通常是从Survivor区域拷贝过来的对象,不过当对象过大的时候,无法在新生代中用连续内存的存放,那么这个大对象就会被直接分配在老年代上。一般来说,普通的对象都是分配在TLAB上,较大的对象,直接分配在Eden区上的其他内存区域,而过大的对象,直接分配在老年代上。

    第四、永久代。如前面所说,在早起的Hotspot JVM中有老年代的概念,老年代用于存储Java类的元数据、常量池、Intern字符串等。在JDK8之后,就将老年代移除,而引入元数据区的概念。

    第五、Vritual空间。前面说过,可以使用Xms与Xmx来指定堆的最小与最大空间。如果Xms小于Xmx,堆的大小不会直接扩展到上限,而是留着一部分等待内存需求不断增长时,再分配给新生代。Vritual空间便是这部分保留的内存区域。

    Java堆内的内存结构大体为:

    出处:https://mp.weixin.qq.com/s/mehFhIR2ne3Tnl7RlBNuhA

  • 相关阅读:
    javaSE基础(三)
    javaSE基础(二)
    javaSE基础(一)
    文件目录爬虫
    前自增 与 后自增
    查找 与 排序 总结
    python 使用 grpc
    python3.7 安装 uwsgi
    go
    go
  • 原文地址:https://www.cnblogs.com/cag2050/p/11898634.html
Copyright © 2011-2022 走看看