对象有什么
Mark work
实例数据的指针
[数组长度]
[对齐填充]
如果对象是一个数组,对象头里还有数组长度
HotSpot中要求对象必须是8字节的整数倍。需要有个对齐填充
Mark Work有什么
不固定,会根据对象状态复用存储空间
分代年龄、是否偏向锁、锁标志位、线程ID
oopMap可以快速枚举GcRoots 。只有在safePoint 才会生成
safePoint : 要符合“长时间执行”。指令序列复用就很满足。
例如:方法调用、循环跳转、异常跳转
safeRegion:进入了safeRegion区域的线程Jvm不用管。退出区域时检查自己是否完成了根节点的枚举。Done就可以退出,还没有就等通知。
Serial Old 两个用处。
1.jdk1.5之前和PS搭配使用
2.用作CMS的备用收集器
PS:
吞吐量高。可以设置-XX:UseAdaptiveSizePolicy来让收集器动态调节新生代大小。晋升老年代的大小等细节参数。
CMS:
基于标记清除。4个步骤 (2,4需要STW下进行)
1.初始标记 标记GCRoots直接关联到的对象
2.并发标记 GCRoots Tracing
3.重新标记 修正并发标记过程中产生变化的对象
4.并发清除
CPU资源敏感
无法处理浮动垃圾(并发清除时产生的垃圾)。可能出现 Concurrent Mode Failure.
解决:降低GC的启动阈值 -XX:CMSInitiatingOccupancyFraction。 失败了就会启动Serial Old收集器
碎片多:CMS基于标记清除。
参数1:-XX:UseCMSCompactAtFullCollection FullGC时整理内存。
参数2:-XX:CMSFullGCsBeforeCompaction 多少次FullGC一次整理 默认0
G1:
特点:
分代收集
整体来看基于“标记-整理” 局部(Region来看)“复制算法”。所以不会产生碎片。
可预测的停顿。
维护一个Remenbered Set 来避免全堆扫描
回收步骤:
初始标记
并发标记
最终标记,利用Remenbed SetLogs 来修改并发标记出现的更改。RemenberedSetLogs合并到RemenberedSet中。
筛选回收:通过回收成本和时间进行排序。通过用户期望的停顿时间,来制定回收计划。
内存的分配
一般是在堆上分配(也有可能jit编译拆散为标量直接在栈上分配),在Eden去分配,如果开启了本地线程分配缓冲,则在ThreadLocal Allocation Buffer上分配,也可能直接在老年代分配,不是百分百。看收集器和参数
默认的 Young:Old的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio )
大对象直接进入老年代: -XX:pretenureSizeThreshold 大于这个参数的直接老年代分配
长期存活对象进入老年代: -XX:MaxTenuringThreshold 调整进入老年代的分代年龄
年龄相同的所有对象大于Survivor空间的一半直接进入老年代
空间担保分配:-XX:HandlePromotionFailure 核心思想:能少一次FullGC是一次