这是我参与8月更文挑战的第8天
Java技术体系的自动内存管理,最根本的目的:自动给对象分配内存,自动回收分配给对象的内存
内存分配策略
基于分代理论(以往文章介绍),新生对象通常会分配在新生代中,少数对象会进入老年代。
对象优先在Eden空间进行分配
在垃圾回收算法-“标记-复制“算法中有提到Apple式回收,会将新生代分为一块大的Eden和两块较小的Survivor空间。
其实在HotSpot虚拟机中,大多数情况,对象都会在新生代Eden进行分配,当Eden空间不足时,虚拟机将会发起一次Minor GC。
可通过虚拟机参数-Xms、-Xmx、-Xmn指定堆内存,-XX:Survivor-Ratio=8决定新生代Eden区与Survivor比例。
大对象直接进入老年代
大对象就是指需要大量连续空间的Java对象,最典型的就是长字符串、数组。
可通过配置虚拟机参数-XX:PretenureSizeThreshold,指定大于该设置值的对象直接在老年代分配。避免在Eden区及两个Survivor区之间来回复制,产生大量的内存复制操作。
长期存活的对象进入老年代
虚拟机会给每个对象定义一个Age,存储在对象头中。如果改对象每次回收都不被销毁且可以正常复制到 Survivor空间,则将Age+1。如果该对象Age>一定年龄后(默认15),则将会晋升至老年代。可配置虚拟机参数-XX:MaxTenuringThreshold=(15),来指定age。
动态对象年龄判定
如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代.
空间分配担保
在发生Minor GC之前,虚拟机必须先检查老年代最大可用的连续空间是否大于新生代所有对象的总空间。
可配置虚拟机参数XX:HandlePromotionFailure=true?flase来配置老年代是否允许冒险担保
如果允许,则会进行一次冒险的担保机制,则直接将新生代Survivor空间无法容纳的对象放入老年代,如果失败,则老年代需要进行一次Full GC。如果不允许,则会先进行一次Full Gc。