zoukankan      html  css  js  c++  java
  • zbb20180930 java,gc,Java堆空间的划分:新生代、老年代

    在JVM中堆空间划分如下图所示
     
    上图中,刻画了Java程序运行时的堆空间,可以简述成如下2条  
    1.JVM中堆空间可以分成三个大区,新生代、老年代、永久代  
    2.新生代可以划分为三个区,Eden区,两个幸存区  在JVM运行时,可以通过配置以下参数改变整个JVM堆的配置比例
    1.JVM运行时堆的大小
     
      -Xms堆的最小值
     
      -Xmx堆空间的最大值
     
    2.新生代堆空间大小调整
     
      -XX:NewSize新生代的最小值
     
      -XX:MaxNewSize新生代的最大值
     
      -XX:NewRatio设置新生代与老年代在堆空间的大小
     
      -XX:SurvivorRatio新生代中Eden所占区域的大小
     
    3.永久代大小调整
     
      -XX:MaxPermSize
     
    4.其他
     
       -XX:MaxTenuringThreshold,设置将新生代对象转到老年代时需要经过多少次垃圾回收,但是仍然没有被回收
     

    在上面的配置中,老年代所占空间的大小是由-XX:SurvivorRatio这个参数进行配置的,看完了上面的JVM堆空间分配图,可能会奇怪,为啥新生代空间要划分为三个区Eden及两个Survivor区?有何用意?为什么要这么分?要理解这个问题,就得理解一下JVM的垃圾收集机制(复制算法也叫copy算法),步骤如下:

    复制(Copying)算法

    将内存平均分成A、B两块,算法过程:

    1. 新生对象被分配到A块中未使用的内存当中。当A块的内存用完了, 把A块的存活对象对象复制到B块。
    2. 清理A块所有对象。
    3. 新生对象被分配的B块中未使用的内存当中。当B块的内存用完了, 把B块的存活对象对象复制到A块。
    4. 清理B块所有对象。
    5. goto 1。

    优点:简单高效。缺点:内存代价高,有效内存为占用内存的一半。

    图解说明如下所示:(图中后观是一个循环过程)


    对复制算法进一步优化:使用Eden/S0/S1三个分区  平均分成A/B块太浪费内存,采用Eden/S0/S1三个区更合理,空间比例为Eden:S0:S1==8:1:1,有效内存(即可分配新生对象的内存)是总内存的9/10。  
    算法过程:  
    1. Eden+S0可分配新生对象;
    2. 对Eden+S0进行垃圾收集,存活对象复制到S1。清理Eden+S0。一次新生代GC结束。
    3. Eden+S1可分配新生对象; 
    4. 对Eden+S1进行垃圾收集,存活对象复制到S0。清理Eden+S1。二次新生代GC结束。 
    5. goto 1。  
    默认Eden:S0:S1=8:1:1,因此,新生代中可以使用的内存空间大小占用新生代的9/10,那么有人就会问,为什么不直接分成两个区,一个区占9/10,另一个区占1/10,这样做的原因大概有以下几种  1.S0与S1的区间明显较小,有效新生代空间为Eden+S0/S1,因此有效空间就大,增加了内存使用率 2.有利于对象代的计算,当一个对象在S0/S1中达到设置的XX:MaxTenuringThreshold值后,会将其分到老年代中,设想一下,如果没有S0/S1,直接分成两个区,该如何计算对象经过了多少次GC还没被释放,你可能会说,在对象里加一个计数器记录经过的GC次数,或者存在一张映射表记录对象和GC次数的关系,是的,可以,但是这样的话,会扫描整个新生代中的对象, 有了S0/S1我们就可以只扫描S0/S1区了.
     
    一个对象的一辈子:
    我是一个普通的Java对象,我出生在Eden区,在Eden区我还看到和我长的很像的小兄弟,我们在Eden区中玩了挺长时间。有一天Eden区中的人实在是太多了,我就被迫去了Survivor区的“From”区,自从去了Survivor区,我就开始漂了,有时候在Survivor的“From”区,有时候在Survivor的“To”区,居无定所。直到我18岁的时候,爸爸说我成人了,该去社会上闯闯了。于是我就去了年老代那边,年老代里,人很多,并且年龄都挺大的,我在这里也认识了很多人。在年老代里,我生活了20年(每次GC加一岁),然后被回收。

     
     
    jvm区域总体分两类,heap区和非heap区。heap区又分:Eden Space(伊甸园)、Survivor Space(幸存者区)、Tenured Gen(老年代-养老区)。 非heap区又分:Code Cache(代码缓存区)、Perm Gen(永久代)、Jvm Stack(java虚拟机栈)、Local Method Statck(本地方法栈)。
     
    HotSpot虚拟机GC算法采用分代收集算法:
     
    1、一个人(对象)出来(new 出来)后会在Eden Space(伊甸园)无忧无虑的生活,直到GC到来打破了他们平静的生活。GC会逐一问清楚每个对象的情况,有没有钱(此对象的引用)啊,因为GC想赚钱呀,有钱的才可以敲诈嘛。然后富人就会进入Survivor Space(幸存者区),穷人的就直接kill掉。
     
    2、并不是进入Survivor Space(幸存者区)后就保证人身是安全的,但至少可以活段时间。GC会定期(可以自定义)会对这些人进行敲诈,亿万富翁每次都给钱,GC很满意,就让其进入了Genured Gen(养老区)。万元户经不住几次敲诈就没钱了,GC看没有啥价值啦,就直接kill掉了。
     
    3、进入到养老区的人基本就可以保证人身安全啦,但是亿万富豪有的也会挥霍成穷光蛋,只要钱没了,GC还是kill掉。
     
    分区的目的:新生区由于对象产生的比较多并且大都是朝生夕灭的,所以直接采用标记-清理算法。而养老区生命力很强,则采用复制算法,针对不同情况使用不同算法。
     
    非heap区域中Perm Gen中放着类、方法的定义,jvm Stack区域放着方法参数、局域变量等的引用,方法执行顺序按照栈的先入后出方式。

    --------------------- 本文来自 大脸萌嘟嘟 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/kobesilent/article/details/58605329?utm_source=copy 

  • 相关阅读:
    Windows8 自制DatePicker
    Windows8 商店支付功能
    通过(Node Js||.Net)基于HTML5的WebSocket实现实时视频文字传输(上)
    Windows8 检测网络
    Windows8 推送通知
    Windows8&Windows Phone 做一个图片效果
    js 两种时间数字字符串格式
    使用Homebrew安装Git(Mac)
    JavaScript核心参考教程客户端JavaScript
    MVC模式浅谈
  • 原文地址:https://www.cnblogs.com/super-admin/p/9733060.html
Copyright © 2011-2022 走看看