<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>GC | 酷 壳 - CoolShell</title>
	<atom:link href="https://coolshell.cn/tag/gc/feed" rel="self" type="application/rss+xml" />
	<link>https://coolshell.cn</link>
	<description>享受编程和技术所带来的快乐 - Coding Your Ambition</description>
	<lastBuildDate>Wed, 07 May 2014 03:28:00 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.2</generator>
	<item>
		<title>面向GC的Java编程</title>
		<link>https://coolshell.cn/articles/11541.html</link>
					<comments>https://coolshell.cn/articles/11541.html#comments</comments>
		
		<dc:creator><![CDATA[王 晨纯]]></dc:creator>
		<pubDate>Wed, 07 May 2014 03:24:38 +0000</pubDate>
				<category><![CDATA[Java语言]]></category>
		<category><![CDATA[GC]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JVM]]></category>
		<guid isPermaLink="false">http://coolshell.cn/?p=11541</guid>

					<description><![CDATA[<p>（感谢网友 @Hesey小纯纯 投稿  博客 &#124;　原文链接） Java程序员在编码过程中通常不需要考虑内存问题，JVM经过高度优化的GC机制大部分情况下都能够很...</p>
<p class="read-more"><a class="btn btn-default" href="https://coolshell.cn/articles/11541.html"> Read More<span class="screen-reader-text">  Read More</span></a></p>
The post <a href="https://coolshell.cn/articles/11541.html">面向GC的Java编程</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></description>
										<content:encoded><![CDATA[<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3415450859608158"
     crossorigin="anonymous"></script><strong>（感谢网友 <a href="http://weibo.com/tbmujian" target="_blank">@Hesey小纯纯</a> 投稿  <a href="http://blog.hesey.net/" target="_blank">博客</a> |　<a href="http://blog.hesey.net/2014/05/gc-oriented-java-programming.html" target="_blank">原文链接</a>）</strong></p>
<p>Java程序员在编码过程中通常不需要考虑内存问题，JVM经过高度优化的GC机制大部分情况下都能够很好地处理堆(Heap)的清理问题。以至于许多Java程序员认为，我只需要关心何时创建对象，而回收对象，就交给GC来做吧！甚至有人说，如果在编程过程中频繁考虑内存问题，是一种退化，这些事情应该交给编译器，交给虚拟机来解决。</p>
<p>这话其实也没有太大问题，的确，大部分场景下关心内存、GC的问题，显得有点“杞人忧天”了，高老爷说过：</p>
<p style="padding-left: 30px;">过早优化是万恶之源。</p>
<p>但另一方面，<strong>什么才是“过早优化”？</strong></p>
<p style="padding-left: 30px;">If we could do things right for the first time, why not?</p>
<p>事实上<strong>JVM的内存模型</strong>( <a href="http://www.cs.umd.edu/~pugh/java/memoryModel/" target="_blank">JMM</a> )理应是Java程序员的基础知识，处理过几次JVM线上内存问题之后就会很明显感受到，很多系统问题，都是内存问题。</p>
<p>对JVM内存结构感兴趣的同学可以看下 <a href="http://blog.hesey.net/2011/04/introduction-to-java-virtual-machine.html" target="_blank">浅析Java虚拟机结构与机制</a> 这篇文章，本文就不再赘述了，本文也并不关注具体的GC算法，相关的文章汗牛充栋，随时可查。</p>
<p>另外，不要指望GC优化的这些技巧，可以对应用性能有成倍的提高，特别是对I/O密集型的应用，或是实际落在YoungGC上的优化，可能效果只是帮你减少那么一点YoungGC的频率。</p>
<p>但我认为，<strong>优秀程序员的价值，不在于其所掌握的几招屠龙之术，而是在细节中见真著</strong>，就像前面说的，<strong>如果我们可以一次把事情做对，并且做好，在允许的范围内尽可能追求卓越，为什么不去做呢？</strong><span id="more-11541"></span></p>
<h4>一、GC分代的基本假设</h4>
<p>大部分GC算法，都将堆内存做分代(Generation)处理，但是为什么要分代呢，又为什么不叫内存分区、分段，而要用面向时间、年龄的“代”来表示不同的内存区域？</p>
<p>GC分代的<strong>基本假设</strong>是：</p>
<p style="padding-left: 30px;"><strong>绝大部分对象的生命周期都非常短暂，存活时间短。</strong></p>
<p>而这些短命的对象，恰恰是GC算法需要首先关注的。所以在大部分的GC中，YoungGC（也称作MinorGC）占了绝大部分，对于负载不高的应用，可能跑了数个月都不会发生FullGC。</p>
<p>基于这个前提，在编码过程中，我们应该<strong>尽可能地缩短对象的生命周期</strong>。在过去，分配对象是一个比较重的操作，所以有些程序员会尽可能地减少new对象的次数，尝试减小堆的分配开销，减少内存碎片。</p>
<p>但是，短命对象的创建在JVM中比我们想象的性能更好，所以，不要吝啬new关键字，大胆地去new吧。</p>
<p>当然前提是不做无谓的创建，对象创建的速率越高，那么GC也会越快被触发。</p>
<p>结论：</p>
<ul>
<li>分配小对象的开销分享小，不要吝啬去创建。</li>
<li>GC最喜欢这种小而短命的对象。</li>
<li>让对象的生命周期尽可能短，例如在方法体内创建，使其能尽快地在YoungGC中被回收，不会晋升(romote)到年老代(Old Generation)。</li>
</ul>
<h4>二、对象分配的优化</h4>
<p>基于大部分对象都是小而短命，并且不存在多线程的数据竞争。这些小对象的分配，会优先在线程私有的<strong> TLAB</strong> 中分配，TLAB中创建的对象，不存在锁甚至是CAS的开销。</p>
<p>TLAB占用的空间在Eden Generation。</p>
<p>当对象比较大，TLAB的空间不足以放下，而JVM又认为当前线程占用的TLAB剩余空间还足够时，就会直接在Eden Generation上分配，此时是存在并发竞争的，所以会有CAS的开销，但也还好。</p>
<p>当对象大到Eden Generation放不下时，JVM只能尝试去Old Generation分配，这种情况需要尽可能避免，因为一旦在Old Generation分配，这个对象就只能被Old Generation的GC或是FullGC回收了。</p>
<h4>三、不可变对象的好处</h4>
<p>GC算法在扫描存活对象时通常需要从ROOT节点开始，扫描所有存活对象的引用，构建出对象图。</p>
<p>不可变对象对GC的优化，主要体现在Old Generation中。</p>
<p>可以想象一下，如果存在Old Generation的对象引用了Young Generation的对象，那么在每次YoungGC的过程中，就必须考虑到这种情况。</p>
<p>Hotspot JVM为了提高YoungGC的性能，避免每次YoungGC都扫描Old Generation中的对象引用，采用了 <strong>卡表(Card Table) </strong>的方式。</p>
<p>简单来说，当Old Generation中的对象发生对Young Generation中的对象产生新的引用关系或释放引用时，都会在卡表中响应的标记上标记为脏(dirty)，而YoungGC时，只需要扫描这些dirty的项就可以了。</p>
<p>可变对象对其它对象的引用关系可能会频繁变化，并且有可能在运行过程中持有越来越多的引用，特别是容器。这些都会导致对应的卡表项被频繁标记为dirty。</p>
<p>而不可变对象的引用关系非常稳定，在扫描卡表时就不会扫到它们对应的项了。</p>
<p>注意，这里的不可变对象，不是指仅仅自身引用不可变的final对象，而是真正的<strong><span style="color: #ff0000;">Immutable Objects</span></strong>。</p>
<h4>四、引用置为null的传说</h4>
<p>早期的很多Java资料中都会提到在方法体中将一个变量置为null能够优化GC的性能，类似下面的代码：</p>
<pre data-enlighter-language="java" class="EnlighterJSRAW">List&lt;String&gt; list = new ArrayList&lt;String&gt;();
// some code
list = null; // help GC
</pre>
<p>事实上这种做法对GC的帮助微乎其微，有时候反而会导致代码混乱。</p>
<p>我记得几年前 @rednaxelafx 在HLL VM小组中详细论述过这个问题，原帖我没找到，结论基本就是：</p>
<ul>
<li>在一个非常大的方法体内，对一个较大的对象，将其引用置为null，某种程度上可以帮助GC。</li>
<li>大部分情况下，这种行为都没有任何好处。</li>
</ul>
<p>所以，还是早点放弃这种“优化”方式吧。</p>
<p>GC比我们想象的更聪明。</p>
<h4>五、手动档的GC</h4>
<p>在很多Java资料上都有下面两个奇技淫巧：</p>
<ul>
<li>通过<strong>Thread.yield()</strong>让出CPU资源给其它线程。</li>
<li>通过<strong>System.gc()</strong>触发GC。</li>
</ul>
<p>事实上JVM从不保证这两件事，而System.gc()在JVM启动参数中如果允许显式GC，则会<strong>触发FullGC</strong>，对于响应敏感的应用来说，几乎等同于自杀。</p>
<p>So，让我们牢记两点：</p>
<ul>
<li>Never use Thread.yield()。</li>
<li>Never use System.gc()。除非你真的需要回收Native Memory。</li>
</ul>
<p>第二点有个Native Memory的例外，如果你在以下场景：</p>
<ul>
<li>使用了NIO或者NIO框架（Mina/Netty）</li>
<li>使用了DirectByteBuffer分配字节缓冲区</li>
<li>使用了MappedByteBuffer做内存映射</li>
</ul>
<p>由于<strong>Native Memory只能通过FullGC（或是CMS GC）回收</strong>，所以除非你非常清楚这时真的有必要，否则不要轻易调用System.gc()，且行且珍惜。</p>
<p>另外为了防止某些框架中的System.gc调用（例如NIO框架、Java RMI），建议在启动参数中加上-XX:+DisableExplicitGC来禁用显式GC。</p>
<p>这个参数有个巨大的坑，如果你禁用了System.gc()，那么上面的3种场景下的内存就无法回收，可能造成OOM，如果你使用了CMS GC，那么可以用这个参数替代：-XX:+ExplicitGCInvokesConcurrent。</p>
<p>关于System.gc()，可以参考 @bluedavy 的几篇文章：</p>
<ul>
<li><a href="http://hellojava.info/?p=56" target="_blank">CMS GC会不会回收Direct ByteBuffer的内存</a></li>
<li><a href="http://hellojava.info/?p=323" target="_blank">说说在Java启动参数上我犯的错</a></li>
<li><a href="http://hellojava.info/?p=319" target="_blank">java.lang.OutOfMemoryError:Map failed</a></li>
</ul>
<p>&nbsp;</p>
<h4>六、指定容器初始化大小</h4>
<p>Java容器的一个特点就是可以动态扩展，所以通常我们都不会去考虑初始大小的设置，不够了反正会自动扩容呗。</p>
<p>但是扩容不意味着没有代价，甚至是很高的代价。</p>
<p>例如一些基于数组的数据结构，例如StringBuilder、StringBuffer、ArrayList、HashMap等等，在扩容的时候都需要做ArrayCopy，对于不断增长的结构来说，经过若干次扩容，会存在大量无用的老数组，而回收这些数组的压力，全都会加在GC身上。</p>
<p>这些容器的构造函数中通常都有一个可以指定大小的参数，如果对于某些大小可以预估的容器，建议加上这个参数。</p>
<p>可是因为容器的扩容并不是等到容器满了才扩容，而是有一定的比例，例如HashMap的扩容阈值和负载因子(loadFactor)相关。</p>
<p>Google Guava框架对于容器的初始容量提供了非常便捷的工具方法，例如：</p>
<p>[code lang=&#8221;java&#8221;]Lists.newArrayListWithCapacity(initialArraySize);</p>
<p>Lists.newArrayListWithExpectedSize(estimatedSize);</p>
<p>Sets.newHashSetWithExpectedSize(expectedSize);</p>
<p>Maps.newHashMapWithExpectedSize(expectedSize);<br />
[/code]</p>
<p>这样我们只要传入预估的大小即可，容量的计算就交给Guava来做吧。</p>
<p><strong>反例</strong>：如果采用默认无参构造函数，创建一个ArrayList，不断增加元素直到OOM，那么在此过程中会导致：</p>
<ul>
<li>多次数组扩容，重新分配更大空间的数组</li>
<li>多次数组拷贝</li>
<li>内存碎片</li>
</ul>
<h4>七、对象池</h4>
<p>为了减少对象分配开销，提高性能，可能有人会采取对象池的方式来缓存对象集合，作为复用的手段。</p>
<p>但是对象池中的对象由于在运行期长期存活，大部分会晋升到Old Generation，因此无法通过YoungGC回收。</p>
<p>并且通常……没有什么效果。</p>
<p>对于对象本身：</p>
<ul>
<li>如果对象很小，那么分配的开销本来就小，对象池只会增加代码复杂度。</li>
<li>如果对象比较大，那么晋升到Old Generation后，对GC的压力就更大了。</li>
</ul>
<p>从线程安全的角度考虑，通常池都是会被并发访问的，那么你就需要处理好同步的问题，这又是一个大坑，并且<strong>同步带来的开销，未必比你重新创建一个对象小</strong>。</p>
<p>对于对象池，唯一合适的场景就是<strong>当池中的每个对象的创建开销很大</strong>时，缓存复用才有意义，例如每次new都会创建一个连接，或是依赖一次RPC。</p>
<p>比如说：</p>
<ul>
<li>线程池</li>
<li>数据库连接池</li>
<li>TCP连接池</li>
</ul>
<p>即使你真的需要实现一个对象池，也请使用成熟的开源框架，例如Apache Commons Pool。</p>
<p>另外，使用JDK的ThreadPoolExecutor作为线程池，不要重复造轮子，除非当你看过AQS的源码后认为你可以写得比Doug Lea更好。</p>
<h4>八、对象作用域</h4>
<p>尽可能缩小对象的作用域，即生命周期。</p>
<ul>
<li>如果可以在方法内声明的局部变量，就不要声明为实例变量。</li>
<li>除非你的对象是单例的或不变的，否则尽可能少地声明static变量。</li>
</ul>
<h4>九、各类引用</h4>
<p>java.lang.ref.Reference有几个子类，用于处理和GC相关的引用。JVM的引用类型简单来说有几种：</p>
<ul>
<li>Strong Reference，最常见的引用</li>
<li>Weak Reference，当没有指向它的强引用时会被GC回收</li>
<li>Soft Reference，只当临近OOM时才会被GC回收</li>
<li>Phantom Reference，主要用于识别对象被GC的时机，通常用于做一些清理工作</li>
</ul>
<p>当你需要实现一个缓存时，可以考虑优先使用WeakHashMap，而不是HashMap，当然，更好的选择是使用框架，例如Guava Cache。</p>
<p>最后，再次提醒，以上的这些未必可以对代码有多少性能上的提升，但是熟悉这些方法，是为了帮助我们写出更卓越的代码，和GC更好地合作。</p>
<p>（全文完）<!--



<p align="center"><a href= target=_blank><img decoding="async" src=""></a></p>





<p align="center"><img decoding="async" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.weixin.jpg"> <img decoding="async" loading="lazy" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.mini_.jpg" width="300" height="300"> <br />关注CoolShell微信公众账号和微信小程序</p>

 

--></p>
<div style="margin-top: 15px; font-size: 16px;color: #cc0000;">
<p align="center"><strong>（转载本站文章请注明作者和出处 <a href="https://coolshell.cn/">酷 壳 &#8211; CoolShell</a> ，请勿用于任何商业用途）</strong></p>
</div>

<div class="wp_rp_wrap  wp_rp_vertical_m" id="wp_rp_first"><div class="wp_rp_content"><h3 class="related_post_title">相关文章</h3><ul class="related_post wp_rp"><li ><a href="https://coolshell.cn/articles/2631.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/8.jpg" alt="五大基于JVM的脚本语言" width="150" height="150" /></a><a href="https://coolshell.cn/articles/2631.html" class="wp_rp_title">五大基于JVM的脚本语言</a></li><li ><a href="https://coolshell.cn/articles/1252.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/5.jpg" alt="G1新型垃圾回收器一瞥" width="150" height="150" /></a><a href="https://coolshell.cn/articles/1252.html" class="wp_rp_title">G1新型垃圾回收器一瞥</a></li><li ><a href="https://coolshell.cn/articles/20845.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2020/03/rust-social-wide-150x150.jpg" alt="Rust语言的编程范式" width="150" height="150" /></a><a href="https://coolshell.cn/articles/20845.html" class="wp_rp_title">Rust语言的编程范式</a></li><li ><a href="https://coolshell.cn/articles/18360.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2018/05/300x262-150x150.jpg" alt="程序员练级攻略（2018)  与我的专栏" width="150" height="150" /></a><a href="https://coolshell.cn/articles/18360.html" class="wp_rp_title">程序员练级攻略（2018)  与我的专栏</a></li><li ><a href="https://coolshell.cn/articles/11454.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/17.jpg" alt="从LongAdder看更高效的无锁实现" width="150" height="150" /></a><a href="https://coolshell.cn/articles/11454.html" class="wp_rp_title">从LongAdder看更高效的无锁实现</a></li><li ><a href="https://coolshell.cn/articles/11175.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2014/03/cow-copy-150x150.jpg" alt="Java中的CopyOnWrite容器" width="150" height="150" /></a><a href="https://coolshell.cn/articles/11175.html" class="wp_rp_title">Java中的CopyOnWrite容器</a></li></ul></div></div>The post <a href="https://coolshell.cn/articles/11541.html">面向GC的Java编程</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></content:encoded>
					
					<wfw:commentRss>https://coolshell.cn/articles/11541.html/feed</wfw:commentRss>
			<slash:comments>46</slash:comments>
		
		
			</item>
		<item>
		<title>G1新型垃圾回收器一瞥</title>
		<link>https://coolshell.cn/articles/1252.html</link>
					<comments>https://coolshell.cn/articles/1252.html#comments</comments>
		
		<dc:creator><![CDATA[陈皓]]></dc:creator>
		<pubDate>Thu, 13 Aug 2009 13:54:26 +0000</pubDate>
				<category><![CDATA[Java语言]]></category>
		<category><![CDATA[编程语言]]></category>
		<category><![CDATA[G1]]></category>
		<category><![CDATA[GC]]></category>
		<category><![CDATA[Java]]></category>
		<guid isPermaLink="false">http://coolshell.cn/?p=1252</guid>

					<description><![CDATA[<p>G1垃圾回收器 “G1垃圾回收”的英文全称是 Garbage-First Garbage Collector （又被称作G1 GC），这是一个新型的垃圾回收器，...</p>
<p class="read-more"><a class="btn btn-default" href="https://coolshell.cn/articles/1252.html"> Read More<span class="screen-reader-text">  Read More</span></a></p>
The post <a href="https://coolshell.cn/articles/1252.html">G1新型垃圾回收器一瞥</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></description>
										<content:encoded><![CDATA[<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3415450859608158"
     crossorigin="anonymous"></script></p>
<h4>G1垃圾回收器</h4>
<p>“G1垃圾回收”的英文全称是 <em>Garbage-First Garbage Collector</em> （又被称作G1 GC），这是一个新型的垃圾回收器，由JDK 7中的Java HotSpot VM 引入。这个技术曾经在Java SE 6 Update 14版本中出现过一个试验性的，然后 G1 被 HotSpot的 反应快速（low-latency）的 <em>Concurrent Mark-Sweep</em> GC （简称 <em>CMS</em>）长期取代。</p>
<h4>属性</h4>
<p>G1 是一个“服务器风格（server-style）”的垃圾回收器，它主要有下面的这些属性：</p>
<p><span id="more-1252"></span></p>
<ul>
<li><strong>并行和并发。</strong> G1 可以从今天最新的硬件中获得并行的能力。它能够使用所有可用的CPU（CPU多核，硬件多线程，等）来加速它的 “stop-the-world” 机制（这个机制简称STW，即，在执行垃圾收集算法时，Java应用程序的其他所有除了垃圾收集帮助器线程之外的线程都被挂起）。</li>
<li><strong>分代处理。</strong> 就像其它的HotSpot 垃圾回收器，G1 是分代的，也就是说，它在处理新分配的对象（年轻代）和已经生存了一段时间的对象（年老代）时会不同，它会更多地考虑一些新创建的对象实例，因为越新创建的就越有最大的可能性被回收，老对象只是偶尔访问一下。对于大多数的Java应用来说，这个机制可以极大地提高回收效率。</li>
<li><strong>紧凑内存（碎片整理）。</strong> 不像CMS，G1 会对堆进行内存整理。压缩可以消除潜在的内存碎片的问题，这样程序就可以更长时间的平滑运行。</li>
<li><strong>预见性的。</strong> G1 比起 CMS 来有更多的预见性。这个主要还是用来消除内存碎片的问题。内存的碎片少了，Stop-the-World的暂停时间也会被减少。</li>
</ul>
<h4>描述</h4>
<p>比起其它的HotSpot 垃圾回收器来说，G1 使用了一种非常不同寻常的方法来管理堆内存的布局。在G1中，在对象新生代和老一代上没有在物理上把他们分隔开来。取而代之的是，它把一个连续的堆内存拆分成了几个相同大小的区域。新产生的对象和老的对象都会被放在一系列可能不会连续的区域中。之所以这样做，就是为了让G1可以更灵活地移动老对象所占用的资源给新的对象。</p>
<p>G1中的内存收集会发生 “疏散暂停”，当内存从一系例区域开始回收时，这些区域所引用的 <em>collection set</em> 会被疏散到另一些区域中，这样，我们会有一整块的内存来重新被申请。疏散会发生整个程序的暂停，但“疏散”这些内存可以被并行运行，当然，你要有多核或多线程技术来支持。绝大多数的“疏散暂停”会去收集那些可用的比较新的内存区域，因此，这和其它的 HotSpot 垃圾回收器是相同的。偶而才会去查看一下老区域中的内存是否可以回收。</p>
<p>在 CMS中，其周期性的执行一个 <em>concurrent marking phase</em>。 这个phase中最主要的事情是，识别哪些老的区域中充满了可以回收的对象，因为这是最有效率和最合适的回收。但在G1中，G1不会执行那个所谓的 <em>concurrent sweeping phase</em>， 取而代之的是，去识别那些的最合适的老的区域是在并发的“疏散暂停”中进行的（后面会做介绍）。</p>
<h4>使用 G1</h4>
<p>G1 目前仍然还在试验阶段，使用下面两个参数可以打开G1机制：</p>
<p><code>-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC</code></p>
<p>下面是设置垃圾回收器的暂停时间：</p>
<p><code>-XX:MaxGCPauseMillis =50</code> (设置暂停时间为 50ms)</p>
<p>在G1中，你还可以给垃圾回收器的暂停设置一个时间间隔：</p>
<p><code>-XX:GCPauseIntervalMillis =200</code> (设置暂停时间间隔 200ms)</p>
<p>注意，上面的两个参数只是代表目标，回收器并不保证。他们可能在某些情况下工作地很好，也可能在其它情况下不行，所以，垃圾回收器并不总是服从这两个参数设置。</p>
<p>另外，新生代的内存大小可以被设置，这个参数同样会影响“疏散暂停”的时间：</p>
<p><code>-XX:+G1YoungGenSize=512m</code> (设置新生代内存为 512兆字节)</p>
<p>G1 同样可以使用survivor 空间，是的，这就是多少个区域。大小可以由通用的参数所指定(如： <code>-XX:SurvivorRatio=6</code>).</p>
<p>最后，如果你要发挥G1的所有潜能，你可以尝试设置下面两个参数，它们默认上是关闭的，因为在一些很稀有的情况下，这两个参数会发生race condition（竞争条件）:</p>
<p><code>-XX:+G1ParallelRSetUpdatingEnabled<br />
-XX:+G1ParallelRSetScanningEnabled</code></p>
<p>还有一件事是G1能够报告比其它垃圾回收站更详细的信息，当然，你需要设置下面这个参数：</p>
<p> <code>-XX:+PrintGCDetails</code></p>
<p>这个参数会输出很多有用的信息供你查看性能与以 trouble-shooting。如果你想要简单的日志，你可以把这个开关设置到 <code>-verbosegc</code> 。</p>
<h4>状态</h4>
<p>G1 开发目前主要关注于解决一些残留的稳定性的问题，以及提高性能，并且去除下面的限制：</p>
<ul>
<li>G1 并不完全支持 JVM Tool Interface (JVM TI) 或 Java Management Extensions (JMX)，所以，这些监控和管理工具无法正确地作用于G1。</li>
<li>G1 不支持增量的永生代collection。如果一个应用在卸载很多的类，因些需要很多的永生代Collection，目前的G1还不支持，不过最终版会支持。</li>
<li>关于垃圾回收器的暂停时间，G1的表现比起CMS来说是时好时坏。所以，还有很多工作需要让G1的表现更加稳定，绝不能比CMS还差，不然G1还有什么意思呢？</li>
</ul>
<h4>相关资源</h4>
<ul>
<li>Description of HotSpot GCs: Memory Management in the Java HotSpot Virtual Machine White Paper: <a href="https://coolshell.cn/j2se/reference/whitepapers/memorymanagement_whitepaper.pdf">http://java.sun.com/j2se/reference/whitepapers/memorymanagement_whitepaper.pdf</a></li>
<li>The original CMS paper: Printezis, T. and Detlefs, D. 2000. A generational mostly-concurrent garbage collector. In <em>Proceedings of the 2nd international Symposium on Memory Management</em> (Minneapolis, Minnesota, United States, October 15 &#8211; 16, 2000). <a href="http://portal.acm.org/citation.cfm?id=362422.362480" target="_blank">http://portal.acm.org/citation.cfm?id=362422.362480</a> (requires access to ACM&#8217;s portal)</li>
<li>The original G1 paper: Detlefs, D., Flood, C., Heller, S., and Printezis, T. 2004. Garbage-first garbage collection. In Proceedings of the 4th international Symposium on Memory Management (Vancouver, BC, Canada, October 24 &#8211; 25, 2004). <a href="http://portal.acm.org/citation.cfm?id=1029879" target="_blank">http://portal.acm.org/citation.cfm?id=1029879</a> (requires access to ACM&#8217;s portal)</li>
<li>G1 talk from JavaOne 2008: <a href="http://developers.sun.com/learning/javaoneonline/j1sessn.jsp?sessn=TS-5419&amp;yr=2008">http://developers.sun.com/learning/javaoneonline/j1sessn.jsp?sessn=TS-5419&amp;yr=2008</a></li>
</ul>
<p>文章：<a href="http://java.sun.com/javase/technologies/hotspot/gc/g1_intro.jsp" target="_blank">来源</a></p>
<p><!-- =================== --><!-- END OF MAIN CONTENT --><!-- =================== --><!--stopindex--><!-- BEGIN D7 COMPONENT V.5 --><!--



<p align="center"><a href= target=_blank><img decoding="async" src=""></a></p>





<p align="center"><img decoding="async" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.weixin.jpg"> <img decoding="async" loading="lazy" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.mini_.jpg" width="300" height="300"> <br />关注CoolShell微信公众账号和微信小程序</p>

 

--></p>
<div style="margin-top: 15px; font-size: 16px;color: #cc0000;">
<p align="center"><strong>（转载本站文章请注明作者和出处 <a href="https://coolshell.cn/">酷 壳 &#8211; CoolShell</a> ，请勿用于任何商业用途）</strong></p>
</div>

<div class="wp_rp_wrap  wp_rp_vertical_m" ><div class="wp_rp_content"><h3 class="related_post_title">相关文章</h3><ul class="related_post wp_rp"><li ><a href="https://coolshell.cn/articles/11541.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/24.jpg" alt="面向GC的Java编程" width="150" height="150" /></a><a href="https://coolshell.cn/articles/11541.html" class="wp_rp_title">面向GC的Java编程</a></li><li ><a href="https://coolshell.cn/articles/20845.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2020/03/rust-social-wide-150x150.jpg" alt="Rust语言的编程范式" width="150" height="150" /></a><a href="https://coolshell.cn/articles/20845.html" class="wp_rp_title">Rust语言的编程范式</a></li><li ><a href="https://coolshell.cn/articles/18360.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2018/05/300x262-150x150.jpg" alt="程序员练级攻略（2018)  与我的专栏" width="150" height="150" /></a><a href="https://coolshell.cn/articles/18360.html" class="wp_rp_title">程序员练级攻略（2018)  与我的专栏</a></li><li ><a href="https://coolshell.cn/articles/11454.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/17.jpg" alt="从LongAdder看更高效的无锁实现" width="150" height="150" /></a><a href="https://coolshell.cn/articles/11454.html" class="wp_rp_title">从LongAdder看更高效的无锁实现</a></li><li ><a href="https://coolshell.cn/articles/11175.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2014/03/cow-copy-150x150.jpg" alt="Java中的CopyOnWrite容器" width="150" height="150" /></a><a href="https://coolshell.cn/articles/11175.html" class="wp_rp_title">Java中的CopyOnWrite容器</a></li><li ><a href="https://coolshell.cn/articles/9703.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2013/05/图1-3-150x150.jpg" alt="无锁HashMap的原理与实现" width="150" height="150" /></a><a href="https://coolshell.cn/articles/9703.html" class="wp_rp_title">无锁HashMap的原理与实现</a></li></ul></div></div>The post <a href="https://coolshell.cn/articles/1252.html">G1新型垃圾回收器一瞥</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></content:encoded>
					
					<wfw:commentRss>https://coolshell.cn/articles/1252.html/feed</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
	</channel>
</rss>
