/**
* java 性能优化实践
* GC根和Arena
* GC根是内存的锚点,属于外部指针,本质上是已知的指针,处于内存池之外,并指向这个内存池
* 内部指针是处于内存池,并指向当前内存池中的另一个位置
* GC根类型
* 栈帧
* JNI
* 寄存器(用于变量提升情况)
* 代码根(来自jvm的代码缓存)
* 全局变量
* 来自加载类的元数据
*
* #最简单的GC根的例子就会引用类的局部变量,它总是指向堆中的一个对象(假设对象不为null)
*
* HotSpot垃圾收集器是以内存区域的方式工作的,这里的内存区域被称为Arena
* HotSpot不需要通过系统调用来管理java堆,相反HotSpot通过用户空间代码来管理堆的大小
* 我们可以使用简单的观测对象来判断垃圾收集子系统是否正在引发某些类型的性能问题
*
* @分配和生命周期
* 一个java应用程序的垃圾收集行为主要两个驱动因素
* 分配率
* 是新创建的对象在一个时间段内所使用的内存量(MB/s)
* 对象生命周期
* 真正理解实际应用程序中的对象生命周期过于复杂
* 这也是垃圾收集多方权衡的重要权重
* #弱分代假说
* JVM内存管理的一个关键部分依赖于一个观察到的软件系统在运行时的表现——弱分代假说(weak generational hypothesis)
* 在jvm和类似的软件系统中,对象生命周期的表现为双峰分布——大部分对象寿命短,次级对象的寿命长于预期
* 垃圾收集堆应该以这样的方式组织,即能够方便快速的收集寿命短的对象,并且最好让寿命长的对象可以与寿命短的隔离开
* HotSpot 使用的机制
* 跟踪每个对象的年龄——代数——即该对象到目前为止熬过的垃圾收集次数
* 除了大对象外,它在Eden空间——Nursery中创建新对象,并且期望移动存活的对象
* 它维护着一个单独内存区域Old Generation 或 Tenured Generation
* 来保存那些已经存活足够长且很有可能继续存活下去的对象
*
* @HotSpot中的垃圾收集
* JVM启动时通过分配预设的内存,并留在用户空间管理单一连续的内存池
* 这样的内存池又会被分为不同的区域进行维护,对象的地址也会经常发生变化
* 因为GC会重新安置这些对象,比如从最开始的创建对象Eden,然后继续存活的对象被疏散到其他区域,Old Generation
*
* #线程本地分配
* Eden是一个需要进行高效管理的关键区域,大多数对象是在这里创建的,寿命非常短的对象(生命周期小于下一个垃圾收集周期的剩余时间),永远不会出现在其他的地方
* 为了提高效率JVM将Eden区划分成若干个缓冲区,并将这些缓冲区交给应用程序线程使用,用于分配新的对象
* 好处,每个线程都知道自己不需要考虑其他线程在该缓冲区分配内存的可能性
* 这些区域称为线程本地分配缓冲区(thread-local allocation buffer)
* HotSpot会动态设置分配给应用程序线程的TLAB的大小,也可以手动调整避免自动扩容带来的开销。
*
* #半空间收集
* 两个空间
* 主要思想——将这些空间作为哪些实际寿命比较短的对象的临时存储区,这样可以防止短寿命的对象把老年代弄乱,还可以降低整堆收集的频率
* 主要属性
* 当收集器正在收集当前活跃的半空间时,对象会被以压缩的方式转移到另一个空间,完成收集的一半空间会被清空等待复用
* 任何时间总有一半是空的
* 新生代堆的半空间部分被称为survivor
* 通常比较小,而且它的角色会随着每一次新生代的垃圾收集而互换
* #并行收集器
* JDK8前默认收集是并行收集
* 他们的新生代和老年代收集全部停顿(STW),针对吞吐量进行优化
* 在停止所有应用线程之后,并行收集器会利用所有可利用的CPU尽快回收内存
*
* Parallel GC 新生代最简单的收集器
* ParNew 与CMS收集器配合使用的并行垃圾收集的变种
* ParallelOld 老年代并行收集器
*
* @新生代并行收集器
* 发生情况——一个应用程序线程试图向Eden空间中分配一个对象,但在其TLAB中已经没有足够的空间,而且jvm也无法为该线程分配
* 一个新的TLAB,此时jvm除了停止所有应用程序线程之外别无选择,如果一个线程无法分配。其他也无法分配
* 一旦停止所有应用程序线程,HotSpot就会查看新生代(Eden和Survivor)空间,并识别出所有非垃圾对象
* 将GC ROOT 作为并行扫描的起点
* 然后 ParallelGC 将所有幸存对象疏散到当前非空的Survivor空间中,疏散安置的过程中增加这些对象的代数
* Eden和Survivor空间标记空的,可重复使用的空间
* 启动所有应用程序线程,这样就可以继续向应用程序线程分配TLAB
*
* @老年代并行收集
* 连续内存空间压缩收集器,在此空间重新安置对象,高效利用内存;也消耗大量的CPU资源
*
* 在java中可以轻易的创建线程,但也让垃圾收集变得更加复杂
* 有了新的线程,意味着有了新的执行栈,其中没一个栈帧都是GC ROOT的来源
*
* @分配作用
* 垃圾收集器通常是在请求内存分配但手头上没有足够的空闲内存来提供所需数量时触发
* 不确定性的,也不会以固定的节奏发生,相反,当一个或多个内存空间基本上满了。没有办法创建对象了,就会触发一个垃圾收集周期
*/
java 性能优化实践——垃圾收集GC
最新推荐文章于 2023-06-12 21:23:35 发布