网站栏目结构设计,seo1视频发布会,wordpress自定义右键,搭建三合一网站对象存活判断 引用计数法
在对象中添加一个引用计数器#xff0c;每当有一个地方引用它时#xff0c;计数器值就加一#xff1b;当引用失效时#xff0c;计数器值就减一#xff1b;任何时刻计数器为零的对象就是不可能再被使用的。
可达性分析算法
通过一系列称为“GC …对象存活判断 引用计数法
在对象中添加一个引用计数器每当有一个地方引用它时计数器值就加一当引用失效时计数器值就减一任何时刻计数器为零的对象就是不可能再被使用的。
可达性分析算法
通过一系列称为“GC Roots”的根对象作为起始节点集从这些节点开始根据引用关系向下搜索搜索过程所走过的路径称为“引用链”ReferenceChain如果某个对象到 GC Roots 间没有任何引用链相连或者用图论的话来说就是从 GC Roots 到这个对象不可达时则证明此对象是不可能再被使用的
其中固定可作为 GC Roots 的对象如下
在虚拟机栈栈帧中的本地变量表中引用的对象譬如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等。在方法区中类静态属性引用的对象譬如 Java 类的引用类型静态变量。在方法区中常量引用的对象譬如字符串常量池String Table里的引用。在本地方法栈中 JNI即通常所说的 Native 方法引用的对象。Java 虚拟机内部的引用如基本数据类型对应的 Class 对象一些常驻的异常对象比如 NullPointExcepiton、OutOfMemoryError等还有系统类加载器所有被同步锁synchronized 关键字持有的对象反映 Java 虚拟机内部情况的 JMXBean、JVMTI 中注册的回调、本地代码缓存等其他对象“临时性”地加入
对象引用 强引用是最传统的“引用”的定义是指在程序代码之中普遍存在的引用赋值即类似“Object objnew Object()”这种引用关系。无论任何情况下只要强引用关系还存在垃圾收集器就永远不会回收掉被引用的对象。 软引用是用来描述一些还有用但非必须的对象。只被软引用关联着的对象在系统将要发生内存溢出异常前会把这些对象列进回收范围之中进行第二次回收如果这次回收还没有足够的内存才会抛出内存溢出异常。在 JDK 1.2 版之后提供了SoftReference 类来实现软引用。 弱引用也是用来描述那些非必须对象但是它的强度比软引用更弱一些被弱引用关联的对象只能生存到下一次垃圾收集发生为止。当垃圾收集器开始工作无论当前内存是否足够都会回收掉只被弱引用关联的对象。在 JDK 1.2 版之后提供了WeakReference 类来实现弱引用 虚引用也称为“幽灵引用”或者“幻影引用”它是最弱的一种引用关系。一个对象是否有虚引用的存在完全不会对其生存时间构成影响也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知。在 JDK 1.2 版之后提供了 PhantomReference 类来实现虚引用
垃圾收集算法 标记-清除算法
算法分为“标记”和“清除”两个阶段首先标记出所有需要回收的对象在标记完成后统一回收掉所有被标记的对象也可以反过来标记存活的对象统一回收所有未被标记的对象。
标记-复制算法
它将可用内存按容量划分为大小相等的两块每次只使用其中的一块。当这一块的内存用完了就将还存活着的对象复制到另外一块上面然后再把已使用过的内存空间一次清理掉。
标记-整理算法
标记过程仍然与“标记-清除”算法一样但后续步骤不是直接对可回收对象进行清理而是让所有存活的对象都向内存空间一端移动然后直接清理掉边界以外的内存。
垃圾收集器 Serial 收集器
一个单线程工作的收集器但它的“单线程”的意义并不仅仅是说明它只会使用一个处理器或一条收集线程去完成垃圾收集工作更重要的是强调在它进行垃圾收集时必须暂停其他所有工作线程直到它收集结束。
ParNew 收集器
是 Serial 收集器的多线程并行版本除了同时使用多条线程进行垃圾收集之外其余的行为包括 Serial 收集器可用的所有控制参数
Parallel Scavenge 收集器
基于标记-复制算法实现的收集器也是能够并行收集的多线程收集器。目标则是达到一个可控制的吞吐量Throughput。所谓吞吐量就是处理器用于运行用户 代码的时间与处理器总消耗时间的比值。 Parallel Scavenge 收集器提供了两个参数用于精确控制吞吐量分别是控制最大垃圾收集停顿时间的-XXMaxGCPauseMillis 参数以及直接设置吞吐量大小的-XXGCTimeRatio 参数自适应调节策略也是 Parallel Scavenge 收集器区别于 ParNew 收集器的一个重要特性。
-XXMaxGCPauseMillis 参数允许的值是一个大于 0 的毫秒数收集器将尽力保证内存回收花费的时间不超过用户设定值。-XXGCTimeRatio 参数的值则应当是一个大于 0 小于 100 的整数也就是垃圾收集时间占总时间的比率相当于吞吐量的倒数。-XXUseAdaptiveSizePolicy 开关参数开启后不需要人工指定新生代的大小-Xmn、Eden 与 Survivor 区的比例-XXSurvivorRatio、晋升老年代对象大小-XXPretenureSizeThreshold等细节参数
Serial Old 收集器
Serial Old 是 Serial 收集器的老年代版本它同样是一个单线程收集器使用标记-整理算法
Parallel Old 收集器
Parallel Old 是 Parallel Scavenge 收集器的老年代版本支持多线程并发收集基于标记-整理算法实现。
CMS 收集器
CMSConcurrent Mark Sweep收集器是一种以获取最短回收停顿时间为目标的收集器。 CMS 收集器是基于标记-清除算法实现的它的运作过程相对于前面几种收集器来说要更复杂一些整个过程分为四个步骤包括 初始标记CMS initial mark 并发标记CMS concurrent mark 重新标记CMS remark 并发清除CMS concurrent sweep 其中初始标记、重新标记这两个步骤仍然需要“Stop The World”。初始标记仅仅只是标记一下 GC Roots 能直接关联到的对象速度很快并发标记阶段就是从 GC Roots 的直接关联对象开始遍历整个对象图的过程这个过程耗时较长但是不需要停顿用户线程可以与垃圾收集线程一起并发运行而重新标记阶段则是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录
缺点
CMS 收集器对处理器资源非常敏感。CMS 默认启动的回收线程数是处理器核心数量3/4。并发回收时垃圾收集线程只占用不超过 25%的处理器运算资源并且会随着处理器核心数量的增加而下降。CMS 收集器无法处理“浮动垃圾”Floating Garbage有可能出现“Con-current Mode Failure”失败进而导致另一次完全“Stop The World”的 Full GC 的产生。CMS 收集器不能像其他收集器那样等待到老年代几乎完全被填满了再进行收集必须预留一部分空间供并发收集时的程序运作使用。参数-XXCMSInitiatingOccu-pancyFraction 的值来提高 CMS 的触发百分比降低内存回收频率获取更好的性能。CMS 收集器的启动阈值就已经默认提升至 92%。要是 CMS 运行期间预留的内存无法满足程序分配新对象的需要就会出现一次“并发失败”Concurrent Mode Failure这时候虚拟机将不得不启动后备预案冻结用户线程的执行临时启用 Serial Old 收集器来重新进行老年代的垃圾收集但这样停顿时间就很长了。所以参数-XXCMSInitiatingOccupancyFraction 设置得太高将会很容易导致大量的并发失败产生性能反而降低用户应在生产环境中根据实际应用情况来权衡设置CMS 是一款基于“标记-清除”算法实现的收集器容易产生大量内存碎片。 -XXUseCMS-CompactAtFullCollection 开关参数默认开启用于在 CMS 收集器不得不进行 Full GC 时开启内存碎片的合并整理过程由于这个内存整理必须移动存活对象在 Shenandoah 和 ZGC 出现前是无法并发的。 数-XXCMSFullGCsBeforeCompaction此参数从 JDK 9 开始废弃这个参数的作用是要求 CMS 收集器在执行过若干次数量由参数值决定不整理空间的 Full GC 之后下一次进入 Full GC 前会先进行碎片整理默认值为 0表示每次进入 Full GC 时都进行碎片整理
G1收集器
JDK 8 Update 40 的时候G1 提供并发的类卸载的支持补全了其计划功能的最后一块拼图。这个版本以后的 G1 收集器才被Oracle 官方称为“全功能的垃圾收集器”。 G1 开创的基于 Region 的堆内存布局把连续的 Java 堆划分为多个大小相等的独立区域Region每一个 Region 都可以根据需要扮演新生代的 Eden 空间、Survivor 空间或者老年代空间。收集器能够对扮演不同角色的 Region 采用不同的策略去处理这样无论是新创建的对象还是已经存活了一段时间、熬过多次收集的旧对象都能获取很好的收集效果。 Region 中还有一类特殊的 Humongous 区域专门用来存储大对象。G1 认为只要大小超过了一个 Region 容量一半的对象即可判定为大对象。每个 Region 的大小可以通过参数-XXG1HeapRegionSize设定取值范围为 1MB32MB且应为 2 的 N 次幂。而对于那些超过了整个 Region 容量的超级大对象将会被存放在 N 个连续的 Humongous Region之中G1 的大多数行为都把 Humongous Region 作为老年代的一部分来进行看待。 垃圾回收过程主要是有以下几个步骤
初始标记Initial Marking仅仅只是标记一下 GC Roots 能直接关联到的对象并且修改 TAMS 指针的值让下一阶段用户线程并发运行时能正确地在可用的Region中分配新对象。这个阶段需要停顿线程但耗时很短而且是借用进行 Minor GC 的时候同步完成的所以 G1收集器在这个阶段实际并没有额外的停顿并发标记Concurrent Marking从 GC Root 开始对堆中对象进行可达性分析递归扫描整个堆里的对象图找出要回收的对象这阶段耗时较长但可与用户程序并发执行。当对象图扫描完成以后还要重新处理 SATB记录下的在并发时有引用变动的对象。最终标记Final Marking对用户线程做另一个短暂的暂停用于处理并发阶段结束后仍遗留下来的最后那少量的 SATB 记录。筛选回收Live Data Counting and Evacuation负责更新 Region 的统计数据对各个 Region 的回收价值和成本进行排序根据用户所期望的停顿时间来制定回收计划可以自由选择任意多个Region 构成回收集然后把决定回收的那一部分 Region 的存活对象复制到空的 Region中再清理掉整个旧 Region 的全部空间。这里的操作涉及存活对象的移动是必须暂停用户线程由多条收集器线程并行完成的。
JDK默认垃圾收集器演进
查看垃圾回收器信息
jmap -heap [pid]jdk1.7 默认垃圾收集器Parallel Scavenge新生代Parallel Old老年代 jdk1.8 默认垃圾收集器Parallel Scavenge新生代Parallel Old老年代 jdk1.9 默认垃圾收集器G1