java jvm 内存分配和回收策略

来源:互联网 发布:数学分析 考研 知乎 编辑:程序博客网 时间:2024/05/31 13:15

有些人可能会问,讲这些东西有没有用。只是多知道了一点理论知识,在实际的项目中会有用么。还真是有。我本来也只是打算扫一眼就过去的。然后去看书后边的那章实际项目中的解决问题的方法和性能调优案例。结果发现里面有好多专业名词是前边这章的。所以就回来重新研读了一下。只有了解了jvm的整个运作方式才能在性能调优和解决bug上得心应手,就像用自己做的软件一样。哪里出问题一眼就能看出来 。

还有啊,基于上述观点,今天有个大哥给我推荐了一本书《通灵芯片》,全书只有9章。一百多页。很快就能读完。这本书全篇没有一点代码。但是把计算机硬件和软件讲得非常透彻。建议一读,必定收获颇丰。


对象优先在Eden分配

大多数情况下。对象在新生代Eden区中分配,当这个区没有足够的空间时,会触发一起MInor GC,这个的意思 是新生代GC,前面我们讲过Full GC也叫做Major GC,Minor GC是在发生新生代的垃圾收集动作,比如我们for循环时会用到的临时变量i,Minor GC非常频繁,速度也快,只需要FUll GC的十分之一左右。Minor GC会收集死掉的对象 。如果原有的对象依然存活而新的对象又没有内存可以分配 的时候 ,原有的对象 会从新生代通过 分配 担保机制提前转移到老年代去。


大对象直接进入老年代

大对象就是需要大量连续内存空间的java对象 ,比如很长的字符串或者数组,写程序的时候 应当避免使用那些朝生夕灭的短命大对象,原因如上。Full GC时间 更长,效率更低。


长期存活的对象将进入老年代

虚拟机采用的是分代收集的思想来管理内存。如何实现分代呢,虚拟机为每个对象 定义 了一个年龄计数器。如果对象在Eden出生并且经过第一次Minor GC后仍然活的,并且能被 Survivor容纳将被移动到Survivor中。此时它1岁了。每熬过一次M gc就长一岁,等它到15岁的时候 就会被 晋升到老年 代中。这个阈值可以通过-XX:MaxTenuringThreshold来设置。


动态对象年龄判定

对于长期存活的对象进入老年代这一规则显然不是死的。比如在第一条就出现了直接进入老年代的情况。动态对象年龄判定规则如下,如果 在Survivor空间中相同年龄所有对象 大小的总和大于Survivior的一半,年龄大于或等于该 年龄的对象就可以直接进入 老年代。原因很简单。为了腾地方嘛。


空间分配担保

第一条的时候提到过一个分配担保机制,在进行Minor GC的时候,虚拟机会检查老年代最大可用的连续空间是否大于新生代所有对象的总空间。原因就是前边说的,新生代可能会转入老年代。这时候地方不够可就麻烦了。如果前边说的这个条件成立那么M GC可以说是安全的。如果不成立,那么虚拟机会检查 HandlePromotionFailure设置值是否允许担保失败,如果允许那么会继续检查老年代最大可用连续空间是否大于历次晋升到老年代对象的平均大小,这个很简单,取一个平均数,预测一下会不会超出可用内存,这个就像是页面置换算法里边的最近最少使用置换算法,以之前来预测以后。前边的条件如果是大于 那么尝试着进行一次M GC,如果小于或者参数不允许冒险,那么改为进行一次Full GC。

在以后的应用中,我们在根据实际需求调这些参数来确保最优。没有万能的设置,只有合适的才是最好的~


0 0
原创粉丝点击