江苏省建设局官方网站查询,网站建设免费学习,网站建设 cms,用dw做购物网站G1 收集器
G1 (Garbage-First) 是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器。 以极高概率满足 GC 停顿时间要求的同时,还具备高吞吐量性能特征。
被视为 JDK1.7 中 HotSpot 虚拟机的一个重要进化特征。它具备以下特点#xff1a; 并行与并发 并行与并发 G1能充分利用多CPU、多核环境下的硬件优势使用多个CPUCPU或者CPU核心来缩短Stop-The-World停顿的时间部分其他收集器原本需要停顿Java线程执行的GC动作G1收集器仍然可以通过并发的方式让Java程序继续执行。 分代收集 与其他收集器一样分代概念在G1中依然得以保留。虽然G1可以不需要其他收集器配合就能独立管理整个GC堆但它能够采用不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象以获取更好的收集效果。 空间整合 与CMS的“标记—清理”算法不同G1从整体来看是基于“标记—整理”算法实现的收集器从局部两个Region之间上来看是基于“标记—复制”算法实现的但无论如何这两种算法都意味着G1运作期间不会产生内存空间碎片收集后能提供规整的可用内存。这种特性有利于程序长时间运行分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。 可预测的停顿 这是G1相对于CMS的另一大优势降低停顿时间是G1和CMS共同的关注点但G1除了追求低停顿外还能建立可预测的停顿时间模型能让使用者明确指定在一个长度为M毫秒的时间片段内消耗在垃圾收集上的时间不得超过N毫秒这几乎已经是实时JavaRTSJ的垃圾收集器的特征了。
在G1之前的其他收集器进行收集的范围都是整个新生代或者老年代而G1不再是这样。使用G1收集器时Java堆的内存布局就与其他收集器有很大差别它将整个Java堆划分为多个大小相等的独立区域Region虽然还保留有新生代和老年代的概念但新生代和老年代不再是物理隔离的了它们都是一部分Region不需要连续的集合。 在G1中还有一种特殊的区域叫Humongous区域。 如果一个对象占用的空间超过了分区容量50%以上G1收集器就认为这是一个巨型对象。这些巨型对象默认直接会被分配在年老代但是如果它是一个短期存在的巨型对象就会对垃圾收集器造成负面影响。为了解决这个问题G1划分了一个Humongous区它用来专门存放巨型对象。如果一个H区装不下一个巨型对象那么G1会寻找连续的H分区来存储。为了能找到连续的H区有时候不得不启动Full GC。
G1收集器之所以能建立可预测的停顿时间模型是因为它可以有计划地避免在整个Java堆中进行全区域的垃圾收集。G1跟踪各个Region里面的垃圾堆积的价值大小回收所获得的空间大小以及回收所需时间的经验值在后台维护一个优先列表每次根据允许的收集时间优先回收价值最大的Region这也就是Garbage-First名称的来由。这种使用Region划分内存空间以及有优先级的区域回收方式保证了G1收集器在有限的时间内可以获取尽可能高的收集效率。
一个对象分配在某个Region中它并非只能被本Region中的其他对象引用而是可以与整个Java堆任意的对象发生引用关系。那在做可达性判定确定对象是否存活的时候岂不是还得扫描整个Java堆才能保证准确性这个问题其实并非在G1中才有只是在G1中更加突出而已。在以前的分代收集中新生代的规模一般都比老年代要小许多新生代的收集也比老年代要频繁许多那回收新生代中的对象时也面临相同的问题如果回收新生代时也不得不同时扫描老年代的话那么Minor GC的效率可能下降不少。
在其他垃圾收集器中通过CardTable来维护老年代对年轻代的引用CardTable可以说是Remembered SetRS的一种特殊实现是Card的集合。Card是一块2的幂字节大小的内存区域例如HotSpot用512字节里面可能包含多个对象。CardTable要记录的是从它覆盖的范围出发指向别的范围的指针。以分代式GC的CardTable为例要记录老年代指向年轻代的跨代指针被标记的Card是老年代范围内的。当进进行年轻代的垃圾收集时只需要扫描年轻代和老年代的CardTable即可保证不对全堆扫描也不会有遗漏。CardTable通常为字节数组由Card的索引即数组下标来标识每个分区的空间地址。默认情况下每个卡都未被引用。当一个地址空间被引用时这个地址空间对应的数组索引的值被标记为”0″即标记为dirty card。
在G1收集器中也有和上面一样的CardTable。另外G1中每个Region还有一个与之对应的Remembered Set虚拟机发现程序在对Reference类型的数据进行写操作时会产生一个 Write Barrier暂时中断写操作检查Reference引用的对象是否处于不同的Region之中如果是便通过CardTable把相关引用信息记录到被引用对象所属的Region的Remembered Set之中。当进行内存回收时在GC根节点的枚举范围中加入Remembered Set即可保证不对全堆扫描也不会有遗漏。 G1收集器的垃圾收集分两种Minor GCYoung GC和 Mixed GCOld GC。
G1Minor GC
Young GC大致可以分为5个阶段
根扫描 静态和本地对象被扫描。更新RS 处理dirty card队列更新RS。处理RS 检测从年轻代指向年老代的对象。对象拷贝 拷贝存活的对象到survivor/old区域。处理引用队列 软引用弱引用虚引用处理。
G1Mixed GC
Mixed GC大致可划分为全局并发标记global concurrent marking和拷贝存活对象evacuation两个大部分
global concurrent marking是基于SATB形式的并发标记包括以下4个阶段初始标记Initial Marking、并发标记Concurrent Marking、最终标记Final Marking、清理Clean Up。 初始标记initial marking 暂停阶段会 STW。扫描根集合标记所有从根集合可直接到达的对象并将它们的字段压入扫描栈marking stack中等待后续扫描。G1使用外部的bitmap来记录mark信息而不使用对象头的mark word里的mark bit。在分代式G1模式中初始标记阶段借用young GC的暂停因而没有额外的、单独的暂停阶段。 并发标记concurrent marking 并发阶段不会 STW。不断从扫描栈取出引用递归扫描整个堆里的对象图。每扫描到一个对象就会对其标记并将其字段压入扫描栈。重复扫描过程直到扫描栈清空。过程中还会扫描SATB write barrier所记录下的引用。 最终标记final marking在实现中也叫remarking 暂停阶段会 STW。在完成并发标记后每个Java线程还会有一些剩下的SATB write barrier记录的引用尚未处理。这个阶段就负责把剩下的引用处理完。同时这个阶段也进行弱引用处理reference processing。 注意这个暂停与CMS的remark有一个本质上的区别那就是这个暂停只需要扫描SATB buffer而CMS的remark需要重新扫描mod-union table里的dirty card外加整个根集合而此时整个young gen不管对象死活都会被当作根集合的一部分因而CMS remark有可能会非常慢。 清理cleanup阶段 暂停阶段会 STW。清点和重置标记状态。这个阶段有点像mark-sweep中的sweep阶段不过不是在堆上sweep实际对象而是在marking bitmap里统计每个region被标记为活的对象有多少。这个阶段如果发现完全没有活对象的region就会将其整体回收到可分配region列表中。
Evacuation阶段是全暂停的。它负责把一部分region里的活对象拷贝到空region里去然后回收原本的region的空间。
Evacuation阶段可以自由选择任意多个region来独立收集构成收集集合collection set简称CSet靠per-region remembered set简称RSet实现。这是regional garbage collector的特征。
在选定CSet后evacuation其实就跟ParallelScavenge的young GC的算法类似采用并行copying或者叫scavenging算法把CSet里每个region里的活对象拷贝到新的region里整个过程完全暂停。从这个意义上说G1的evacuation跟传统的mark-compact算法的compaction完全不同前者会自己从根集合遍历对象图来判定对象的生死不需要依赖global concurrent marking的结果有就用没有拉倒而后者则依赖于之前的mark阶段对对象生死的判定。
纯G1模式下CSet的选定完全靠统计模型找处收益最高、开销不超过用户指定的上限的若干region。由于每个region都有RSet覆盖要单独evacuate任意一个或多个region都没问题。 对象漏标
垃圾回收的并发标记阶段gc线程和应用线程是并发执行的所以一个对象被标记之后应用线程可能篡改对象的引用关系从而造成对象的漏标、误标其实误标没什么关系顶多造成浮动垃圾在下次gc还是可以回收的但是漏标的后果是致命的把本应该存活的对象给回收了从而影响的程序的正确性。
为了解决在并发标记过程中存活对象漏标的情况GC HandBook把对象分成三种颜色三色标记
黑色从GCRoots开始已扫描过它全部引用的对象标记为黑色灰色扫描过对象本身还没完全扫描过它全部引用的对象标记为灰色白色还没扫描过的对象标记为白色。
所以漏标的情况只会发生在白色对象中且同时满足下面两个条件
有至少一个黑色对象在自己被标记之后指向了这个白色对象所有的灰色对象在自己引用扫描完成之前删除了对白色对象的引用。
例如
D对象引用E对象E引用G此时GC正好处于D已经变成黑色E处于灰色
G是白色的情况下此时因为业务逻辑的变化E不引用G了D对象引用了G
按照三色标记法看黑色对象是已完成状态不可能再去找子引用所以G就不会变成灰色这样就会造成白色对象此时正在被线程使用中
但是无法被标记成灰色或者白色造成一个正在被使用的对象被错误回收。这两个条件必须全满足,才会造成漏标问题。换言之我们破坏任何一个条件。这个白色对象就不会再被漏标这样就产生了两个解决办法。
CMS采用的是增量更新 增量更新破坏的是第一个条件我们在这个黑色对象增加了对白色对象的引用之后,将它的这个引用记录下来在最后标记的时候再以这个黑色对象为根,对它的引用进行重新扫描。 可以简单理解为,当一个黑色对象增加了对白色对象的引用,那么这个黑色对象就被变灰。这样有一个缺点,就是会重新扫描这个黑色对象的所有引用,比较浪费时间。
G1采用的是原始快照SATB 原始快照破坏的是第二个条件,我们在这个灰色对象取消对白色对象的引用之前,将这个引用记录下来,在最后标记的时候,再以这个引用指向的白色对象为根,对它的引用进行扫描。 可以简单理解为,当一个灰色对象取消了对白色对象的引用,那么这个白色对象被变灰。
这样做的缺点就是,这个白色对象有可能并没有黑色对象去引用它,但是它还是被变灰了,就会导致它和它的引用,本来应该被垃圾回收掉,但是此次GC存活了下来,就是所谓的浮动垃圾.其实这样是比较可以忍受的,只是让它多存活了一次GC而已,浪费一点点空间,但是会比增量更新更省时间.
SATB
SATB全称snapshot-at-the-beginning由Taiichi Yuasa为增量式标记清除垃圾收集器开发的一个算法主要应用于垃圾收集的并发标记阶段解决了CMS垃圾收集器重新标记阶段长时间STW的潜在风险。Region包含了5个指针分别是bottom、previous TAMS、next TAMS、top和end。 JVM运行模式
JVMJava虚拟机有两种运行模式Client模式和Server模式。它们的主要区别在于优化策略和内存管理方式。 Client模式 Client模式主要是针对启动时间短但运行时间比较短的Java应用程序如小型GUI应用程序等通过减少JVM启动时间来提高应用程序的性能。在Client模式下JVM会使用较少的内存来运行以及使用较少的线程来处理请求。这些优化措施可以提高应用程序的启动速度和响应速度。 优点启动速度快占用内存少。 缺点在长时间运行的情况下由于内存和线程的限制可能会导致应用程序的性能和响应速度下降。 Server模式 Server模式主要是针对长时间运行的Java应用程序如Web服务器、应用服务器等进行优化通过提高JVM的性能和响应速度来处理高并发的请求。在Server模式下JVM会使用更多的内存来运行以及使用更多的线程来处理请求。这些优化措施可以提高应用程序的性能和响应速度。 优点针对长时间运行的Java应用程序进行了优化可以提高应用程序的性能和响应速度。 缺点启动时间较长占用的内存较多。 区别 内存管理Client模式下使用较少的内存而Server模式下使用更多的内存。线程管理Client模式下使用较少的线程而Server模式下使用更多的线程。优化策略Client模式主要优化启动时间和响应速度而Server模式主要优化性能和响应速度。启动时间Client模式启动时间短而Server模式启动时间较长。总之选择JVM运行模式需要根据具体的应用场景来确定。对于启动时间短、运行时间短的Java应用程序可以选择Client模式而对于长时间运行的Java应用程序可以选择Server模式。