??xml version="1.0" encoding="utf-8" standalone="yes"?>浙江福彩快乐12:BlogJava-xiaomage234-随笔分类 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/category/30805.html生命本就是一次凄美的漂流,记忆中放不下的,永远是孩提时代的那一份浪漫与纯真?/description>zh-cnSat, 30 Mar 2019 16:24:49 GMTSat, 30 Mar 2019 16:24:49 GMT60Java堆外内存排查小结【转?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2019/03/30/433695.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Sat, 30 Mar 2019 03:44:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2019/03/30/433695.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/433695.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2019/03/30/433695.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/433695.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/433695.html</trackback:ping><description><![CDATA[from:<a >https://blog.csdn.net/lycyingO/article/details/80854669<br /><br /><br /><div class="yibqv"> 版权声明:微信公众号《小姐姐味道》,转载注明出处<span style="white-space:pre"> </span>https://blog.csdn.net/lycyingO/article/details/80854669</div><div class="yibqv"></div><div class="yibqv"></div><div class="yibqv">简?/div><div class="yibqv">JVM堆外内存难排查但经常会出现问题,这可能是目前最全的JVM堆外内存排查思路?/div><div class="yibqv"></div><div class="yibqv">通过本文,你应该了解?/div><div class="yibqv"></div><div class="yibqv">pmap 命令</div><div class="yibqv">gdb 命令</div><div class="yibqv">perf 命令</div><div class="yibqv">内存 RSS、VSZ的区?/div><div class="yibqv">java NMT</div><div class="yibqv">起因</div><div class="yibqv">这几天遇到一个比较奇怪的问题,觉得有必要和大家分享一下。我们的一个服务,运行在docker上,在某个版本之后,占用的内存开始增长,直到docker分配的内存上限,但是并不会OOM。版本的更改如下?/div><div class="yibqv"></div><div class="yibqv">升级了基础软件的版?/div><div class="yibqv">将docker的内存上限由4GB扩展?GB</div><div class="yibqv">上上个版本的一项变动是使用了EhCache的Heap缓存</div><div class="yibqv">没有读文件,也没有mmap操作</div><div class="yibqv">使用jps 查看启动参数,发现分配了大约3GB的堆内存</div><div class="yibqv"></div><div class="yibqv">[root]$ jps -v</div><div class="yibqv">75 Bootstrap -Xmx3000m -Xms3000m  -verbose:gc -Xloggc:/home/logs/gc.log -XX:CMSInitiatingOccupancyFraction=80 -XX:+UseCMSCompactAtFullCollection -XX:MaxTenuringThreshold=10 -XX:MaxPermSize=128M -XX:SurvivorRatio=3 -XX:NewRatio=2 -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+UseParNewGC -XX:+UseConcMarkSweepGC</div><div class="yibqv">使用ps查看进程使用的内存和虚拟内存 ( Linux内存管理 )。除了虚拟内存比较高达到17GB以外,实际使用的内存RSS也夸张的达到?GB,远远超过了-Xmx的设定?/div><div class="yibqv"></div><div class="yibqv">[root]$ ps -p 75 -o rss,vsz  </div><div class="yibqv"> </div><div class="yibqv">RSS    VSZ 7152568 17485844</div><div class="yibqv">原创文章,转载注明出?(//sayhiai.com)</div><div class="yibqv">排查过程</div><div class="yibqv">明显的,是有堆外内存的使用,不太可能是由于EhCache引起的(因为我们使用了heap方式)。了解到基础软件的升级涉及到netty版本升级,netty会用到一些DirectByteBuffer,第一轮排查我们采用如下方式:</div><div class="yibqv"></div><div class="yibqv">jmap -dump:format=b,file=75.dump 75 通过分析堆内存找到DirectByteBuffer的引用和大小</div><div class="yibqv">部署一个升级基础软件之前的版本,持续观察</div><div class="yibqv">部署另一个版本,更改EhCache限制其大小到1024M</div><div class="yibqv">考虑到可能由Docker的内存分配机制引起,部署一实例到实体机</div><div class="yibqv">结果4个环境中的服务,无一例外的都出现了内存超用的问题。问题很奇怪,宝宝睡不着觉?/div><div class="yibqv"></div><div class="yibqv">pmap</div><div class="yibqv">为了进一步分析问题,我们使用pmap查看进程的内存分配,通过RSS升序序排列。结果发现除了地址000000073c800000上分配的3GB堆以外,还有数量非常多的64M一块的内存段,还有巨量小的物理内存块映射到不同的虚拟内存段上。但到现在为止,我们不知道里面的内容是什么,是通过什么产生的?/div><div class="yibqv"></div><div class="yibqv">[root]$ pmap -x 75  | sort -n -k3</div><div class="yibqv"> </div><div class="yibqv">.....省略N?/div><div class="yibqv"> </div><div class="yibqv">0000000040626000   55488   55484   55484 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007fa07c000000   65536   55820   55820 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007fa044000000   65536   55896   55896 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007fa0c0000000   65536   56304   56304 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007f9db8000000   65536   56360   56360 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007fa0b8000000   65536   56836   56836 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007fa084000000   65536   57916   57916 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007f9ec4000000   65532   59752   59752 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007fa008000000   65536   60012   60012 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007f9e58000000   65536   61608   61608 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007f9f18000000   65532   61732   61732 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007fa018000000   65532   61928   61928 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007fa088000000   65536   62336   62336 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007fa020000000   65536   62428   62428 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007f9e44000000   65536   64352   64352 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007f9ec0000000   65528   64928   64928 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007fa050000000   65532   65424   65424 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007f9e08000000   65512   65472   65472 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007f9de0000000   65524   65512   65512 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007f9dec000000   65532   65532   65532 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007f9dac000000   65536   65536   65536 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007f9dc8000000   65536   65536   65536 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007f9e30000000   65536   65536   65536 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007f9eb4000000   65536   65536   65536 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007fa030000000   65536   65536   65536 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">00007fa0b0000000   65536   65536   65536 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">000000073c800000 3119140 2488596 2487228 rwx--    [ anon ]</div><div class="yibqv"> </div><div class="yibqv">total kB        17629516 7384476 7377520</div><div class="yibqv">通过google,找到以下资?Linux glibc >= 2.10 (RHEL 6) malloc may show excessive virtual memory usage)</div><div class="yibqv"></div><div class="yibqv">文章指出造成应用程序大量申请64M大内存块的原因是由Glibc的一个版本升级引起的,通过export MALLOC_ARENA_MAX=4可以解决VSZ占用过高的问题。虽然这也是一个问题,但却不是我们想要的,因为我们增长的是物理内存,而不是虚拟内存?/div><div class="yibqv"></div><div class="yibqv">NMT</div><div class="yibqv">幸运的是 JDK1.8有Native Memory Tracker可以帮助定位。通过在启动参数上加入-XX:NativeMemoryTracking=detail就可以启用。在命令行执行jcmd可查看内存分配?/div><div class="yibqv"></div><div class="yibqv">#jcmd 75 VM.native_memory summary</div><div class="yibqv"> </div><div class="yibqv">Native Memory Tracking: Total: reserved=5074027KB, committed=3798707KB -                 Java Heap (reserved=3072000KB, committed=3072000KB)                            (mmap: reserved=3072000KB, committed=3072000KB) -                     Class (reserved=1075949KB, committed=28973KB)                            (classes #4819)                            (malloc=749KB #13158)                            (mmap: reserved=1075200KB, committed=28224KB) -                    Thread (reserved=484222KB, committed=484222KB)                            (thread #470)                            (stack: reserved=482132KB, committed=482132KB)                            (malloc=1541KB #2371)                            (arena=550KB #938) -                      Code (reserved=253414KB, committed=25070KB)                            (malloc=3814KB #5593)                            (mmap: reserved=249600KB, committed=21256KB) -                        GC (reserved=64102KB, committed=64102KB)                            (malloc=54094KB #255)                            (mmap: reserved=10008KB, committed=10008KB) -                  Compiler (reserved=542KB, committed=542KB)                            (malloc=411KB #543)                            (arena=131KB #3) -                  Internal (reserved=50582KB, committed=50582KB)                            (malloc=50550KB #13713)                            (mmap: reserved=32KB, committed=32KB) -                    Symbol (reserved=6384KB, committed=6384KB)                            (malloc=4266KB #31727)                            (arena=2118KB #1) -    Native Memory Tracking (reserved=1325KB, committed=1325KB)                            (malloc=208KB #3083)                            (tracking overhead=1117KB) -               Arena Chunk (reserved=231KB, committed=231KB)                            (malloc=231KB) -                   Unknown (reserved=65276KB, committed=65276KB)                            (mmap: reserved=65276KB, committed=65276KB)</div><div class="yibqv">虽然pmap得到的内存地址和NMT大体能对的上,但仍然有不少内存去向成谜。虽然是个好工具但问题并不能解决?/div><div class="yibqv"></div><div class="yibqv">gdb</div><div class="yibqv">非常好奇64M或者其他小内存块中是什么内容,接下来通过gdbdump出来。读?proc目录下的maps文件,能精准的知晓目前进程的内存分布?/div><div class="yibqv"></div><div class="yibqv">以下脚本通过传入进程id,能够将所关联的内存全部dump到文件中(会影响服务,慎用)?/div><div class="yibqv"></div><div class="yibqv">grep rw-p /proc/$1/maps | sed -n 's/^\([0-9a-f]*\)-\([0-9a-f]*\) .*$/\1 \2/p' | while read start stop; do gdb --batch --pid $1 -ex "dump memory $1-$start-$stop.dump 0x$start 0x$stop"; done</div><div class="yibqv">更多时候,推荐之dump一部分内存?再次提醒操作会影响服务,注意dump的内存块大小,慎??/div><div class="yibqv"></div><div class="yibqv">gdb --batch --pid 75 -ex "dump memory a.dump 0x7f2bceda1000 0x7f2bcef2b000</div><div class="yibqv">[root]$ du -h *</div><div class="yibqv">dump 4.0K</div><div class="yibqv">55-00600000-00601000.dump 400K</div><div class="yibqv">55-00eb7000-00f1b000.dump 0</div><div class="yibqv">55-704800000-7c0352000.dump 47M</div><div class="yibqv">55-7f2840000000-7f2842eb8000.dump 53M</div><div class="yibqv">55-7f2848000000-7f284b467000.dump 64M</div><div class="yibqv">55-7f284c000000-7f284fffa000.dump 64M</div><div class="yibqv">55-7f2854000000-7f2857fff000.dump 64M</div><div class="yibqv">55-7f285c000000-7f2860000000.dump 64M</div><div class="yibqv">55-7f2864000000-7f2867ffd000.dump 1016K</div><div class="yibqv">55-7f286a024000-7f286a122000.dump 1016K</div><div class="yibqv">55-7f286a62a000-7f286a728000.dump 1016K</div><div class="yibqv">55-7f286d559000-7f286d657000.dump</div><div class="yibqv">是时候查看里面的内容?/div><div class="yibqv"></div><div class="yibqv">[root]$ view 55-7f284c000000-7f284fffa000.dump</div><div class="yibqv">^@^@X+^?^@^@^@^@^@d(^?^@^@^@ ÿ^C^@^@^@^@^@ ÿ^C^@^@^@^@^@^@^@^@^@^@^@^@±<97>p^C^@^@^@^@ 8^^Z+^?^@^@ ^@^@d(^?^@^@ 8^^Z+^?^@^@ ^@^@d(^?^@^@</div><div class="yibqv">achine":524993642,"timeSecond":1460272569,"inc":2145712868,"new":false},"device":{"client":"android","uid":"xxxxx","version":881},"</div><div class="yibqv">device_android":{"BootSerialno":"xxxxx","CpuInfo":"0-7","MacInfo":"2c:5b:b8:b0:d5:10","RAMSize":"4027212","SdcardInfo":"xxxx","Serialno":"xxxx",</div><div class="yibqv">"android_id":"488aedba19097476","buildnumber":"KTU84P/1416486236","device_ip":"0.0.0.0","mac":"2c:5b:b8:b0:d5:10","market_source":"12","model":"OPPO ...more</div><div class="yibqv">纳尼?这些内容不应该在堆里面么?为何还会使用额外的内存进行分配?上面已经排查netty申请directbuffer的原因了,那么还有什么地方在分配堆外内存呢?</div><div class="yibqv"></div><div class="yibqv">perf</div><div class="yibqv">传统工具失灵,快到了黔驴技穷的时候了,是时候祭出神器perf了?/div><div class="yibqv"></div><div class="yibqv">使用 perf record -g -p 55 开启监控栈函数调用。运行一段时间后Ctrl+C结束,会生成一个文件perf.data?/div><div class="yibqv"></div><div class="yibqv">执行perf report -i perf.data查看报告?/div><div class="yibqv"></div><div class="yibqv"></div><div class="yibqv">如图,进程大量执行bzip相关函数。搜索zip,结果如下:</div><div class="yibqv"></div><div class="yibqv"></div><div class="yibqv"></div><div class="yibqv">-.-!</div><div class="yibqv"></div><div class="yibqv">进程调用了Java_java_util_zip_Inflater_inflatBytes() 申请了内存,仅有一小部分调用Deflater释放内存。与pmap内存地址相比对,确实是bzip在搞鬼?/div><div class="yibqv"></div><div class="yibqv">原创文章,转载注明出?(//sayhiai.com)</div><div class="yibqv">解决</div><div class="yibqv">java项目搜索zip定位到代码,发现确实有相关bzip压缩解压操作,而且GZIPInputStream有个地方没有close?/div><div class="yibqv"></div><div class="yibqv">GZIPInputStream使用Inflater申请堆外内存,Deflater释放内存,调用close()方法来主动释放。如果忘记关闭,Inflater对象的生命会延续到下一次GC。在此过程中,堆外内存会一直增长?/div><div class="yibqv"></div><div class="yibqv">原代码:</div><div class="yibqv"></div><div class="yibqv">public byte[] decompress ( byte[] input) throws IOException {</div><div class="yibqv">                ByteArrayOutputStream out = new ByteArrayOutputStream();</div><div class="yibqv">                IOUtils.copy(new GZIPInputStream(new ByteArrayInputStream(input)), out);</div><div class="yibqv">                return out.toByteArray();</div><div class="yibqv">            }</div><div class="yibqv">修改后:</div><div class="yibqv"></div><div class="yibqv"> public byte[] decompress(byte[] input) throws IOException {</div><div class="yibqv">        ByteArrayOutputStream out = new ByteArrayOutputStream();</div><div class="yibqv">        GZIPInputStream gzip = new GZIPInputStream(new ByteArrayInputStream(input));</div><div class="yibqv">        IOUtils.copy(gzip, out);</div><div class="yibqv">        gzip.close();</div><div class="yibqv">        return out.toByteArray();</div><div class="yibqv">    }</div><div class="yibqv">经观察,问题解决?/div><div class="yibqv">--------------------- </div><div class="yibqv">作者:lycyingO </div><div class="yibqv">来源:CSDN </div><div class="yibqv">原文:https://blog.csdn.net/lycyingO/article/details/80854669 </div><div class="yibqv">版权声明:本文为博主原创文章,转载请附上博文链接?/div></a><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/433695.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2019-03-30 11:44 <a href="//www.ot7t.com.cn/xiaomage234/archive/2019/03/30/433695.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java问题排查工具库(转) - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/archive/2018/11/23/433512.html小马?/dc:creator>小马?/author>Fri, 23 Nov 2018 02:47:00 GMT//www.ot7t.com.cn/xiaomage234/archive/2018/11/23/433512.html//www.ot7t.com.cn/xiaomage234/comments/433512.html//www.ot7t.com.cn/xiaomage234/archive/2018/11/23/433512.html#Feedback0//www.ot7t.com.cn/xiaomage234/comments/commentRss/433512.html//www.ot7t.com.cn/xiaomage234/services/trackbacks/433512.html阅读全文

]]>
【OSGI?.初识OSGI-到底什么是OSGI 【转?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2017/08/10/432733.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Thu, 10 Aug 2017 07:57:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2017/08/10/432733.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/432733.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2017/08/10/432733.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/432733.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/432733.html</trackback:ping><description><![CDATA[<div style="padding-top: 20px; padding-bottom: 20px; font-family: Arial, Console, Verdana, "Courier New"; font-size: 12px; background-color: #ffffff;"><p style="margin: 0px; padding: 0px 0px 0px 10px; height: 14px; line-height: 14px; border-left: 3px solid #e41c1e; color: #666666; font-size: 14px;">from:<span style="font-size: 12px;">//blog.csdn.net/acmman/article/details/50848595</span></p><p style="margin: 0px; padding: 0px 0px 0px 10px; height: 14px; line-height: 14px; border-left: 3px solid #e41c1e; color: #666666; font-size: 14px;">版权声明:本文为博主原创文章,未经博主允许不得转载?/p></div><div id="article_content" tracking-ad"="" data-mod="popu_307" data-dsm="post" style="margin: 20px 0px 0px; font-stretch: normal; line-height: 26px; font-family: Arial; background-color: #ffffff;">目前,业内关于OSGI技术的学习资源或者技术文?还是很少的。我在某宝网搜索了一?#8220;OSGI”的书籍,结果倒是有,但是种类少的可怜,而且几乎没有人购买?br />因为工作的原因我需要学习OSGI,所以我不得不想尽办法来主动学习OSGI。我将用文字记录学习OSGI的整个过程,通过整理书籍和视频教程,来让我更加了解这门技术,同时也让需要学习这门技术的同志们有一个清晰的学习路线?br /><br />我们需要解决一下几问题:<br /><span style="font-size: 18px;"><strong class="yibqv">1.如何正确的理解和认识OSGI技术?</strong></span><br /><br />我们从外文资料上或者从翻译过来的资料上看到OSGi解释和定义,都是直译过来的,但是OSGI的真实意义未必是中文直译过来的意思。OSGI的解释就是Open Service Gateway Initiative,直译过来就?#8220;开放的服务入口(网关)的初始化”,听起来非常费解,什么是服务入口初始化?<br /><br />所以我们不去直译这个OSGI,我们换一种说法来描述OSGI技术?br /><br />我们来回到我们以前的某些开发场景中去,假设我们使用SSH(struts+spring+hibernate)框架来开发我们的Web项目,我们做产品设计和开发的时候都是分模块的,我们分模块的目的就是实现模块之间?#8220;解?#8221;,更进一步的目的是方便对一个项目的控制和管理?br />我们对一个项目进行模块化分解之后,我们就可以把不同模块交给不同的开发人员来完成开发,然后项目经理把大家完成的模块集中在一起,然后拼装成一个最终的产品。一般我们开发都是这样的基本情况?br /><br />那么我们开发的时候预计的是系统的功能,根据系统的功能来进行模块的划分,也就是说,这个产品的功能或客户的需求是划分的重要依据?br /><br />但是我们在开发过程中,我们模块之间还要彼此保持联系,比如A模块要从B模块拿到一些数据,而B模块可能要调用C模块中的一些方?除了公共底层的工具类之外)。所以这些模块只是一种逻辑意义上的划分?br /><br />最重要的一点是,我们把最终的项目要去部署到tomcat或者jBoss的服务器中去部署。那么我们启动服务器的时候,能不能关闭项目的某个模块或功能呢?很明显是做不到的,一旦服务器启动,所有模块就要一起启动,都要占用服务器资源,所以关闭不了模块,假设能强制拿掉,就会影响其它的功能?br /><br />以上就是我们传统模块式开发的一些局限性?br /><br />我们做软件开发一直在追求一个境界,就是<span style="color: #ff0000;"><strong class="yibqv">模块之间的真?#8220;解?#8221;?#8220;分离”</strong></span>,这样我们在软件的管理和开发上面就会更加的灵活,甚至包括给客户部署项目的时候都可以做到更加的灵活可控。但是我们以前使用SSH框架等架构模式进行产品开发的时候我们是达不到这种要求的?br /><br />所以我?#8220;架构?#8221;或顶尖的技术高手都在为模块化开发努力的摸索和尝试,然后我们的OSGI的技术规范就应运而生?br /><br />现在我们的OSGI技术就可以满足我们之前所说的境界:在不同的模块中做到彻底的分离,而不是逻辑意义上的分离,是物理上的分离,也就是说在运行部署之后都可以在不停止服务器的时候直接把某些模块拿下来,其他模块的功能也不受影响?br /><br />由此,OSGI技术将来会变得非常的重要,因为它在实现模块化解耦的路上,走得比现在大家经常所用的SSH框架走的更远。这个技术在未来大规模、高访问、高并发的Java模块化开发领域,或者是项目规范化管理中,会大大超过SSH等框架的地位?br /><br />现在主流的一些应用服务器,Oracle的weblogic服务器,IBM的WebSphere,JBoss,还有Sun公司的glassfish服务器,都对OSGI提供了强大的支持,都是在OSGI的技术基础上实现的。有那么多的大型厂商支持OSGI这门技术,我们既可以看到OSGI技术的重要性。所以将来OSGI是将来非常重要的技术?br /><br />但是OSGI仍然脱离不了框架的支持,因为OSGI本身也使用了很多spring等框架的基本控件(因为要实现AOP依赖注入等功?,但是哪个项目又不去依赖第三方jar呢?<br /><br /><br /><br /><span style="font-size: 18px;"><strong class="yibqv">2.OSGI技术对我们项目的开发有什么帮助?</strong></span><br /><br /><strong class="yibqv">(1)项目展示</strong><br />接下来我们同过项目代码来展示一下OSGI的魅?<br />我们先不要去急着理解如何使用OSGI,我们通过一个项目先来看一下OSGI的效果?br />(以下工程代码是网上教学视频中的样例,源码我这里是没有?<br />(提前说一?我们要学习的重点就是我们这个购物网站如何结合OSGI技术,使得项目更加的灵活可控,而购物网站本身并不是重点?<br /><br /><br />首先在Eclipse中先打开我们的单服务器版本的项目:<br /><img src="//img.blog.csdn.net/20160310173347989?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />启动成功:<br /><p style="margin: 0px; padding: 0px;"><img src="//img.blog.csdn.net/20160310173401567?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /></p><p style="margin: 0px; padding: 0px;"><img src="//img.blog.csdn.net/20160310173411895?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /></p><br /><br />这是一个Web项目,我们打开浏览器看一下效?<br /><img src="//img.blog.csdn.net/20160310173429161?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />可以看出是一个网上购物的项目?br /><br />我们来看一下我们基于OSGI技术的项目和我们一般的项目有什么区别?br />首先介绍一下这个项目的模块:<br /><br /><strong class="yibqv">1.大类展示</strong><br /><img src="//img.blog.csdn.net/20160310173537333?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br /><strong class="yibqv">2.小类展示(大类的子产品)</strong><br /><img src="//img.blog.csdn.net/20160310173552836?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />点进去之后就是产品的具体信息<br /><img src="//img.blog.csdn.net/20160310173601523?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br /><br /><strong class="yibqv">3.购物?/strong><br />没买东西是空?<br /><img src="//img.blog.csdn.net/20160310173611224?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />买完之后:<br /><img src="//img.blog.csdn.net/20160310173619274?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br /><br /><strong class="yibqv">4.商品管理(上架、下?</strong><br /><img src="//img.blog.csdn.net/20160310173629587?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br /><br />可以看到,这个项目和我们平常开发的项目没有什么不?我知道界面很简? =),重点是它的启动和加载过程?br /><br /><br /><strong class="yibqv">(2)关于服务?/strong><br />我们是通过动态加载,也就?#8220;热部?#8221;来启动我们的项目的。就是说,我们这个项目把它放在Web容器中之后,我们可以将某些功能给它拿下来,而且拿下来的时候不会对其他模块造成影响?br /><br />我们以前运行tomcat的时候,启动一下服务器,将Web项目一次性装载完毕,控制台会出现类似这种信息:<br /><img src="//img.blog.csdn.net/20160310173643287?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br />但是我们启动这个项目的时候并不是这样:<br /><img src="//img.blog.csdn.net/20160310173703556?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br />那么我们没有用tomcat和jBoss,那是如何部署和启动Web项目的呢?不可能没有Web服务器中间件的啊?这里告诉大家,OSGI技术里面也是内嵌了一个Web服务器的,就是jetty?br /><br /><br /><p style="margin: 0px; padding: 0px;">我们打开这个项目的Run Configuration配置窗口,看一下运行这个项目所需要的插件?</p><p style="margin: 0px; padding: 0px;"><img src="//img.blog.csdn.net/20160310173803120?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /></p>可以看到,除了一些Web项目需要的jar包,还是有jetty的存在的。所以用到的服务器是jetty,不再是tomcat?br /><br /><br />大家可能还是比较熟悉tomcat,对于jetty不是太熟悉,那么我们简单介绍一下jetty:<br />jetty也是一个比较优秀的Web容器,在某些性能方面要比tomcat强大的多(如高并发,长连接)。而且它的整个结构比tomcat轻巧很多(tomcat更臃?,具体区别大家可以去网上自己看一下?br /><br /><br /><strong class="yibqv">(3)运行模式和插?/strong><br />我们接下来正式看一下此项目在OSGI下的运行模式:<br />我们在启动的时候,加载了四个模块,分别?<br /><img src="//img.blog.csdn.net/20160310173817834?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />按照模块化的思想他们就是四个对应的功能模块?br />他们对应的四个功能模块的工程代码我们可以在Eclipse中看?<br /><img src="//img.blog.csdn.net/20160310173838100?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br /><br />我们看一下我们的启动配置(依然打开是Run Configuration配置窗口):<br /><p style="margin: 0px; padding: 0px;"><img src="//img.blog.csdn.net/20160310173851028?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /></p><p style="margin: 0px; padding: 0px;"><img src="//img.blog.csdn.net/20160310173908287?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /></p>配置分为“WorkSpace”?#8220;Target Platform”,分别是我们工作空间(我们自己写的项目模块和工具类)的插件和运行平台(一些依赖jar的配?的插件,两者结合启动我们的项目就会正常运行?br /><br />我们启动项目之后,在控制台输入指?#8220;ss”,就会出现我们所有加载的插件的运行情?<br /><img src="//img.blog.csdn.net/20160310173922491?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br />一启动的时候,它会首先加载Eclipse的OSGI插件(Eclipse本身也是一种OSGI的容??br /><br />我们打开我们的Eclipse安装目录,然后找到plugins文件夹,可以看到Eclipse所有的插件:<br /><img src="//img.blog.csdn.net/20160310173950670?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />可以看到有文件夹形式的,有jar形式的插件?br /><br />我们怎么去理解插件呢?br />插件其实就是被开发工具或OSGI容器管理和配置起来的jar包? <br /><br />我们随便打开一个文件夹类型的插件,可以看到:<br /><img src="//img.blog.csdn.net/20160310174004498?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />可以看到里面除了lib之外还有其它东西,然后有一?#8220;OSGI-INF”文件夹。且不管它是什么,这都足以说明我们的Eclipse就是一个OSGI容器?br /><br /><strong class="yibqv">(4)热部署和热启?/strong><br />我们接下来回到重点,在我们启动的过程中,我们不停止运行,然后去停掉其中的一个模?<br /><br />假如我们要停?#8220;管理”模块:<br /><img src="//img.blog.csdn.net/20160310174017304?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />也就是停掉id?2的插?br /><br />结果:<br /><p style="margin: 0px; padding: 0px;"><img src="//img.blog.csdn.net/20160310174029225?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /></p><br />然后刷新我们的网站主页面:<br /><img src="//img.blog.csdn.net/20160310174125101?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />发现我们?#8220;管理”模块消失?<br /><br />这个模块的消失并不是javascript的技术,而是一种服务器技术,我们是通过服务器内部把它动态卸载掉的?br /><br />我们的管理模块去掉之后,网站的其它功能不受任何影响。至此我们的服务器没有进行任何的暂停或关闭?br /><br />我们再停?#8220;购物?#8221;模块:<br /><img src="//img.blog.csdn.net/20160310174849760?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />效果:<br /><img src="//img.blog.csdn.net/20160310174743931?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />其它模块依旧不受影响?br /><br />我们关闭了两个模块,现在输入ss看一下所有插件和模块的运行情?<br /><img src="//img.blog.csdn.net/20160310174908917?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br />可以看到我们的两个模块处于RESOLVED状态,也就是待解决状态?br /><br />当然我们也可以将我们的模块在服务器开启状态下部署上去:<br />如我们启动购物车模块:<br /><img src="//img.blog.csdn.net/20160310174936589?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br />发现购物车回来了:<br /><img src="//img.blog.csdn.net/20160310174946605?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /><br />这就是所谓的热部署,即是这个项目把它放在Web容器中之后,我们可以将某些功能给它拿下来,而且拿下来的时候不会对其他模块造成影响?br /><br /><br />通过购物网站这个项目让大家真实的感受一下OSGI这个技术在项目开发和管理的一些强大的功能?br /><br /><p style="margin: 0px; padding: 0px;">想进一步了解更多关于OSGI的知识可以查看以后的总结文章?/p><p style="margin: 0px; padding: 0px;"><strong class="yibqv"><span style="color: #ff0000;">转载请注明出处:<a target="_blank" style="color: #ca0000; text-decoration-line: none;">//blog.csdn.net/acmman/article/details/50848595</a></span></strong></p></div><div tracking-ad="" bdshare-button-style0-16"="" data-mod="popu_172" data-bd-bind="1502330276160" style="zoom: 1; font-family: Arial, Console, Verdana, "Courier New"; font-size: 12px; background-color: #ffffff; float: right;"><a data-cmd="more" target="_blank" style="color: #333333; text-decoration-line: none; float: left; padding-left: 17px; line-height: 16px; height: 16px; background-repeat: no-repeat; cursor: pointer; margin: 6px 6px 6px 0px; background-image: url("//bdimg.share.baidu.com/static/api/img/share/icons_0_16.png?v=d754dcc0.png") !important; background-position: 0px 0px !important;"></a><a data-cmd="qzone" title="分享到QQ空间" target="_blank" style="color: #ca0000; text-decoration-line: none; float: left; padding-left: 17px; line-height: 16px; height: 16px; background-image: url("../img/share/icons_0_16.png?v=91362611.png"); background-repeat: no-repeat; cursor: pointer; margin: 6px 6px 6px 0px; background-position: 0px -52px !important;"></a><a data-cmd="tsina" title="分享到新浪微? target="_blank" style="color: #ca0000; text-decoration-line: none; float: left; padding-left: 17px; line-height: 16px; height: 16px; background-image: url("../img/share/icons_0_16.png?v=91362611.png"); background-repeat: no-repeat; cursor: pointer; margin: 6px 6px 6px 0px; background-position: 0px -104px !important;"></a><a data-cmd="tqq" title="分享到腾讯微? target="_blank" style="color: #ca0000; text-decoration-line: none; float: left; padding-left: 17px; line-height: 16px; height: 16px; background-image: url("../img/share/icons_0_16.png?v=91362611.png"); background-repeat: no-repeat; cursor: pointer; margin: 6px 6px 6px 0px; background-position: 0px -260px !important;"></a><a data-cmd="renren" title="分享到人人网" target="_blank" style="color: #ca0000; text-decoration-line: none; float: left; padding-left: 17px; line-height: 16px; height: 16px; background-image: url("../img/share/icons_0_16.png?v=91362611.png"); background-repeat: no-repeat; cursor: pointer; margin: 6px 6px 6px 0px; background-position: 0px -208px !important;"></a><a data-cmd="weixin" title="分享到微? target="_blank" style="color: #ca0000; text-decoration-line: none; float: left; padding-left: 17px; line-height: 16px; height: 16px; background-image: url("../img/share/icons_0_16.png?v=91362611.png"); background-repeat: no-repeat; cursor: pointer; margin: 6px 6px 6px 0px; background-position: 0px -1612px !important;"></a></div><div id="digg" articleid="50848595" style="clear: both; width: 182px; margin: 0px auto; padding-top: 30px; padding-bottom: 15px; text-align: center; font-family: Arial, Console, Verdana, "Courier New"; font-size: 12px; background-color: #ffffff;"><dl id="btnDigg" digg_disable"="" style="display: inline-block; float: left; width: 72px; height: 72px; overflow: hidden; margin: 0px 2px; background: #999999; color: #ffffff; cursor: pointer;"><dt style="margin: 0px; padding: 12px 0px 3px; font-stretch: normal; font-size: 27px; line-height: 30px; font-family: "Microsoft YaHei";">?/dt><dd style="margin: 0px; font-stretch: normal; line-height: 22px; font-family: Arial;">20</dd></dl><dl id="btnBury" digg_disable"="" style="display: inline-block; float: left; width: 72px; height: 72px; overflow: hidden; margin: 0px 2px; background: #999999; color: #ffffff; cursor: pointer;"><dt style="margin: 0px; padding: 12px 0px 3px; font-stretch: normal; font-size: 27px; line-height: 30px; font-family: "Microsoft YaHei";">?/dt></dl></div><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/432733.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2017-08-10 15:57 <a href="//www.ot7t.com.cn/xiaomage234/archive/2017/08/10/432733.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《Spring Boot极简教程》第5?Spring Boot自动配置原理【转?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432717.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Wed, 02 Aug 2017 08:35:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432717.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/432717.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432717.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/432717.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/432717.html</trackback:ping><description><![CDATA[from://www.jianshu.com/p/ccadc2bdb6d7<br /><div class="yibqv"><div class="yibqv"><div data-note-content=""><h1>浙江福彩快乐12:??Spring Boot自动配置原理</h1> <h2 class="yibqv">5.1 SpringBoot的核心组件模?/h2> <p>首先,我们来简单统计一下SpringBoot核心工程的源码java文件数量?/p> <p>我们cd到spring-boot-autoconfigure工程根目录下。执?/p> <pre gams"=""><code>$ tree | grep -c .java$</code></pre> <table> <thead> <tr> <th>模块</th> <th>java文件?/th> </tr> </thead> <tbody> <tr> <td>spring-boot</td> <td>551</td> </tr> <tr> <td>spring-boot-actuator</td> <td>423</td> </tr> <tr> <td>spring-boot-autoconfigure</td> <td>783</td> </tr> <tr> <td>spring-boot-devtools</td> <td>169</td> </tr> <tr> <td>spring-boot-cli</td> <td>180</td> </tr> <tr> <td>spring-boot-tools</td> <td>355</td> </tr> </tbody> </table> <p>我们可以看到?83个java文件。spring-boot核心工程?51个java文件。从上面的java文件数量大致可以看出,SpringBoot技术框架的核心组成部分?/p> <pre mel"=""><code>spring-boot-autoconfigure spring-boot spring-boot-tools</code></pre> <p>我们把SpringBoot源码导入IntelliJ IDEA,查看artifact的全部依赖关系?/p> <p>IDEA有个Maven Projects窗口,一般在右侧能够找到,如果没有可以从菜单栏打开:View>Tool Windows>Maven Projects;</p> <p>选择要分析的maven module(idea的module相当于eclipse的project),右击show dependencies,会出来该module的全部依赖关系图,非常清晰细致?/p> <p>例如,spring-boot-starter-freemarker的依赖图分析如下?/p> <div class="yibqv"> <img src="//upload-images.jianshu.io/upload_images/1233356-928607fa053a7199.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/1233356-928607fa053a7199.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="cursor: zoom-in;" alt="" /><br /><div class="yibqv"></div> </div> <p>在spring-boot-build 的pom中,我们可以看到?/p> <pre crystal"=""><code> <modules> <module>spring-boot-dependencies</module> <module>spring-boot-parent</module> <module>spring-boot-tools</module> <module>spring-boot</module> <module>spring-boot-test</module> <module>spring-boot-autoconfigure</module> <module>spring-boot-test-autoconfigure</module> <module>spring-boot-actuator</module> <module>spring-boot-devtools</module> <module>spring-boot-docs</module> <module>spring-boot-starters</module> <module>spring-boot-actuator-docs</module> <module>spring-boot-cli</module> </modules></code></pre> <p>其中,在spring-boot-dependencies中,SpringBoot项目维护了一份庞大依赖。这些依赖的版本都是经过实践,测试通过,不会发生依赖冲突的。就这样一个事情,就大大减少了Spring开发过程中,出现jar包冲突的概率。spring-boot-parent依赖spring-boot-dependencies?/p> <p>下面我们简要介绍一下SpringBoot子modules?/p> <h4>spring-boot</h4> <p>SpringBoot核心工程?/p> <h4>spring-boot-starters</h4> <p>是SpringBoot的启动服务工程?/p> <h4>spring-boot-autoconfigure</h4> <p>是SpringBoot实现自动配置的核心工程?/p> <h4>spring-boot-actuator</h4> <p>提供SpringBoot应用的外围支撑性功能?比如?/p> <ul class="yibqv"> <li class="yibqv">Endpoints,SpringBoot应用状态监控管?/li> <li class="yibqv">HealthIndicator,SpringBoot应用健康指示?/li> <li class="yibqv">提供metrics支持</li> <li class="yibqv">提供远程shell支持</li> </ul> <h4>spring-boot-tools</h4> <p>提供了SpringBoot开发者的常用工具集。诸如,spring-boot-gradle-plugin,spring-boot-maven-plugin就是这个工程里面的?/p> <h4>spring-boot-cli</h4> <p>是Spring Boot命令行交互工具,可用于使用Spring进行快速原型搭建。你可以用它直接运行Groovy脚本。如果你不喜欢Maven或Gradle,Spring提供了CLI(Command Line Interface)来开发运行Spring应用程序。你可以使用它来运行Groovy脚本,甚至编写自定义命令?/p> <h2 class="yibqv">5.2 SpringBoot Starters</h2> <p>Spring boot中的starter概念是非常重要的机制,能够抛弃以前繁杂的配置,统一集成进starter,应用者只需要引入starter jar包,spring boot就能自动扫描到要加载的信息?/p> <p>starter让我们摆脱了各种依赖库的处理,需要配置各种信息的困扰。Spring Boot会自动通过classpath路径下的类发现需要的Bean,并织入bean?/p> <p>例如,如果你想使用Spring和用JPA访问数据库,你只要依?spring-boot-starter-data-jpa 即可?/p> <p>目前,github上spring-boot项目的最新的starter列表<a target="_blank">spring-boot/spring-boot-starters</a>如下?/p> <pre mel"=""><code>spring-boot-starter spring-boot-starter-activemq spring-boot-starter-actuator spring-boot-starter-amqp spring-boot-starter-aop spring-boot-starter-artemis spring-boot-starter-batch spring-boot-starter-cache spring-boot-starter-cloud-connectors spring-boot-starter-data-cassandra spring-boot-starter-data-couchbase spring-boot-starter-data-elasticsearch spring-boot-starter-data-jpa spring-boot-starter-data-ldap spring-boot-starter-data-mongodb spring-boot-starter-data-mongodb-reactive spring-boot-starter-data-neo4j spring-boot-starter-data-redis spring-boot-starter-data-rest spring-boot-starter-data-solr spring-boot-starter-freemarker spring-boot-starter-groovy-templates spring-boot-starter-hateoas spring-boot-starter-integration spring-boot-starter-jdbc spring-boot-starter-jersey spring-boot-starter-jetty spring-boot-starter-jooq spring-boot-starter-jta-atomikos spring-boot-starter-jta-bitronix spring-boot-starter-jta-narayana spring-boot-starter-log4j2 spring-boot-starter-logging spring-boot-starter-mail spring-boot-starter-mobile spring-boot-starter-mustache spring-boot-starter-parent spring-boot-starter-reactor-netty spring-boot-starter-security spring-boot-starter-social-facebook spring-boot-starter-social-linkedin spring-boot-starter-social-twitter spring-boot-starter-test spring-boot-starter-thymeleaf spring-boot-starter-tomcat spring-boot-starter-undertow spring-boot-starter-validation spring-boot-starter-web spring-boot-starter-web-services spring-boot-starter-webflux spring-boot-starter-websocket</code></pre> <p>(源代码目录执行shell:l|awk '{print $9}'?l|awk '{print $9}'|grep -c 'starter')</p> <p>?2个。每个starter工程里面的pom描述有相应的介绍。具体的说明,参考官网文?[1]。关于这些starters的使用例子,可以参?a target="_blank">spring-boot/spring-boot-samples</a></p> <p>比如说,spring-boot-starter是:</p> <blockquote><p>Core starter, including auto-configuration support, logging and YAML</p></blockquote> <p>这是Spring Boot的核心启动器,包含了自动配置、日志和YAML。它的项目依赖图如下?/p> <div class="yibqv"> <img src="//upload-images.jianshu.io/upload_images/1233356-84c9847c7ccdbda7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/1233356-84c9847c7ccdbda7.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="cursor: zoom-in;" alt="" /><br /><div class="yibqv"></div> </div> <div class="yibqv"> <img src="//upload-images.jianshu.io/upload_images/1233356-20374baaeb3d6086.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/1233356-20374baaeb3d6086.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="cursor: zoom-in;" alt="" /><br /><div class="yibqv"></div> </div> <p>可以看出,这些starter只是配置,真正做自动化配置的代码的是在spring-boot-autoconfigure里面。同时spring-boot-autoconfigure依赖spring-boot工程,这个spring-boot工程是SpringBoot的核心?/p> <p>SpringBoot会基于你的classpath中的jar包,试图猜测和配置您可能需要的bean?/p> <p>例如,如果你的classpath中有tomcat-embedded.jar,你可能会想要一个TomcatEmbeddedServletContainerFactory Bean (SpringBoot通过获取EmbeddedServletContainerFactory来启动对应的web服务器。常用的两个实现类是TomcatEmbeddedServletContainerFactory和JettyEmbeddedServletContainerFactory)?/p> <p>其他的所有基于Spring Boot的starter都依赖这个spring-boot-starter。比如说spring-boot-starter-actuator的依赖树,如下图?/p> <div class="yibqv"> <img src="//upload-images.jianshu.io/upload_images/1233356-5754dcdfcf085c48.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/1233356-5754dcdfcf085c48.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="cursor: zoom-in;" alt="" /><br /><div class="yibqv"></div> </div> <h2 class="yibqv">5.3 @EnableAutoConfiguration自动配置原理</h2> <p>通过@EnableAutoConfiguration启用Spring应用程序上下文的自动配置,这个注解会导入一个EnableAutoConfigurationImportSelector的类,而这个类会去读取一个spring.factories下key为EnableAutoConfiguration对应的全限定名的值?/p> <p>这个spring.factories里面配置的那些类,主要作用是告诉Spring Boot这个stareter所需要加载的那些xxxAutoConfiguration类,也就是你真正的要自动注册的那些bean或功能。然后,我们实现一个spring.factories指定的类,标上@Configuration注解,一个starter就定义完了?/p> <p>如果想从自己的starter种读取应用的starter工程的配置,只需要在入口类上加上如下注解即可?/p> <pre css"=""><code>@EnableConfigurationProperties(MyProperties.class)</code></pre> <h3>读取spring.factories文件的实?/h3> <p>是通过org.springframework.core.io.support.SpringFactoriesLoader实现?/p> <p>SpringFactoriesLoader的实现类似于SPI(Service Provider Interface,在java.util.ServiceLoader的文?里有比较详细的介绍。java SPI提供一种服务发现机制,为某个接口寻找服务实现的机制。有点类似IOC的思想,就是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要[3])?/p> <p>SpringFactoriesLoader会加载classpath下所有JAR文件里面的META-INF/spring.factories文件?/p> <p>其中加载spring.factories文件的代码在loadFactoryNames方法?</p> <pre haxe"=""><code>public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"; .... public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); try { Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); List<String> result = new ArrayList<>(); while (urls.hasMoreElements()) { URL url = urls.nextElement(); Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url)); String factoryClassNames = properties.getProperty(factoryClassName); result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames))); } return result; } catch (IOException ex) { throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex); } }</code></pre> <p>通过org.springframework.boot.autoconfigure.AutoConfigurationImportSelector里面的getCandidateConfigurations方法,获取到候选类的名字List<String>。该方法代码如下?/p> <pre lasso"=""><code> protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames( getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you " + "are using a custom packaging, make sure that file is correct."); return configurations; }</code></pre> <p>其中,getSpringFactoriesLoaderFactoryClass()方法直接返回的是EnableAutoConfiguration.class, 代码如下?/p> <pre fortran"=""><code> protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; }</code></pre> <p>所以,getCandidateConfigurations方法里面的这段代码:</p> <pre dart"=""><code>List<String> configurations = SpringFactoriesLoader.loadFactoryNames( getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());</code></pre> <p>会过滤出key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的全限定名对应的值。全限定名都使用如下命名方法?/p> <pre stylus"=""><code>包名.外部类名 包名.外部类名$内部类名 e.g: org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration</code></pre> <p>SpringBoot中的META-INF/spring.factories(完整路径:spring-boot/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories)中关于EnableAutoConfiguration的这段配置如下:</p> <pre stata"=""><code># Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\ org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\ org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\ org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\ org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\ org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\ org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\ org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\ org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.ReactiveMongoDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.mongo.ReactiveMongoRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\ org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\ org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\ org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\ org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\ org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\ org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\ org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\ org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\ org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\ org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\ org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\ org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\ org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\ org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\ org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\ org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\ org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\ org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\ org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\ org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\ org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\ org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\ org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\ org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\ org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\ org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\ org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\ org.springframework.boot.autoconfigure.mongo.ReactiveMongoAutoConfiguration,\ org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\ org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\ org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\ org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\ org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\ org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\ org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\ org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\ org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\ org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\ org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\ org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\ org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\ org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\ org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\ org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\ org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\ org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\ org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerAutoConfiguration,\ org.springframework.boot.autoconfigure.web.reactive.WebFluxAnnotationAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\ org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\ org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration</code></pre> <p>当然了,这些AutoConfiguration不是所有都会加载的,会根据AutoConfiguration上的@ConditionalOnClass等条件,再进一步判断是否加载。我们下文通过FreeMarkerAutoConfiguration实例来分析整个自动配置的过程?/p> <h2 class="yibqv">5.4 FreeMarkerAutoConfiguration自动配置的实例分?/h2> <p>我们首先看spring-boot-starter-freemarker工程,目录结构如下:</p> <pre stylus"=""><code>. ├── pom.xml ├── spring-boot-starter-freemarker.iml └── src └── main └── resources └── META-INF └── spring.provides 4 directories, 3 files</code></pre> <p>我们可以看出,这个工程没有任何Java代码,只有两个文件:pom.xml跟spring.provides。starter本身在你的应用程序中实际上是空的?</p> <p>其中?br />spring.provides文件</p> <pre avrasm"=""><code>provides: freemarker,spring-context-support</code></pre> <p>主要是给这个starter起个好区分的名字?/p> <p>Spring Boot 通过starter对项目的依赖进行统一管理. starter利用了maven的传递依赖解析机?把常用库聚合在一? 组成了针对特定功能而定制的依赖starter?/p> <p>我们可以使用IDEA提供的maven依赖图分析的功能(如下图),得到spring-boot-starter-freemarker依赖的module?/p> <div class="yibqv"> <img src="//upload-images.jianshu.io/upload_images/1233356-bb4a9d7e8061ee83.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/1233356-bb4a9d7e8061ee83.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="cursor: zoom-in;" alt="" /><br /><div class="yibqv">IDEA提供的maven依赖图分?/div> </div> <div class="yibqv"> <img src="//upload-images.jianshu.io/upload_images/1233356-28ff27d41a7ddeef.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/1233356-28ff27d41a7ddeef.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="cursor: zoom-in;" alt="" /><br /><div class="yibqv">spring-boot-starter-freemarker依赖的module</div> </div> <p>从上面的依赖图,我们可以清晰看出其间依赖关系?/p> <p>当Spring Boot Application中自动配置EnableAutoConfiguration的相关类执行完毕之后,Spring Boot会进一步解析对应类的配置信息。如果我们配置了spring-boot-starter-freemarker ,maven就会通过这个starter所依赖的spring-boot-autoconfigure,自动传递到spring-boot-autoconfigure工程中?/p> <p>我们来简单分析一下spring-boot-autoconfigure工程的架构?/p> <p>其中,FreeMarker的自动配置类是org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration?/p> <p>下面我们来简要分析一下FreeMarkerAutoConfiguration这个类?/p> <p>在FreeMarkerAutoConfiguration类上面有四行注解?/p> <pre less"=""><code>@Configuration @ConditionalOnClass({ freemarker.template.Configuration.class, FreeMarkerConfigurationFactory.class }) @AutoConfigureAfter(WebMvcAutoConfiguration.class) @EnableConfigurationProperties(FreeMarkerProperties.class) public class FreeMarkerAutoConfiguration { ... }</code></pre> <p>其中?br />?)@Configuration,是org.springframework.context.annotation包里面的注解。这么说吧,用@Configuration注解该类,等?与XML中配置beans;用@Bean标注方法等价于XML中配置bean?/p> <p>?)@ConditionalOnClass,org.springframework.boot.autoconfigure.condition包里面的注解。意思是当类路径下有指定的类的条件下,才会去注册被标注的类为一个bean。在上面的代码中的意思就是,当类路径中有freemarker.template.Configuration.class,FreeMarkerConfigurationFactory.class两个类的时候,才会实例化FreeMarkerAutoConfiguration这个Bean?/p> <p>?)@AutoConfigureAfter,org.springframework.boot.autoconfigure包里面的注解。这个通过注解的名字意思就可以知道,当WebMvcAutoConfiguration.class这个类实例化完毕,才能实例化FreeMarkerAutoConfiguration(有个先后顺序)。SpringBoot使用@ AutoConfigureBefore、@AutoConfigureAfter注解来定义这些配置类的载入顺序?/p> <p>?)@EnableConfigurationProperties,表示启动对FreeMarkerProperties.class的内嵌配置支持,自动将FreeMarkerProperties注册为一个bean。这个FreeMarkerProperties类里面就是关于FreeMarker属性的配置?/p> <pre processing"=""><code>@ConfigurationProperties(prefix = "spring.freemarker") public class FreeMarkerProperties extends AbstractTemplateViewResolverProperties { public static final String DEFAULT_TEMPLATE_LOADER_PATH = "classpath:/templates/"; public static final String DEFAULT_PREFIX = ""; public static final String DEFAULT_SUFFIX = ".ftl"; /** * Well-known FreeMarker keys which will be passed to FreeMarker's Configuration. */ private Map<String, String> settings = new HashMap<>(); /** * Comma-separated list of template paths. */ private String[] templateLoaderPath = new String[] { DEFAULT_TEMPLATE_LOADER_PATH }; /** * Prefer file system access for template loading. File system access enables hot * detection of template changes. */ private boolean preferFileSystemAccess = true; public FreeMarkerProperties() { super(DEFAULT_PREFIX, DEFAULT_SUFFIX); } public Map<String, String> getSettings() { return this.settings; } public void setSettings(Map<String, String> settings) { this.settings = settings; } public String[] getTemplateLoaderPath() { return this.templateLoaderPath; } public boolean isPreferFileSystemAccess() { return this.preferFileSystemAccess; } public void setPreferFileSystemAccess(boolean preferFileSystemAccess) { this.preferFileSystemAccess = preferFileSystemAccess; } public void setTemplateLoaderPath(String... templateLoaderPaths) { this.templateLoaderPath = templateLoaderPaths; } }</code></pre> <p>综上,当?)(2)两个条件满足时,才会继续(3)(4)的动作,同时注册FreeMarkerAutoConfiguration这个Bean。该类的结构如下图:</p> <div class="yibqv"> <img src="//upload-images.jianshu.io/upload_images/1233356-ac415fb54e391999.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/1233356-ac415fb54e391999.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="cursor: zoom-in;" alt="" /><br /><div class="yibqv"></div> </div> <p>我们来看其内部类FreeMarkerWebConfiguration的代码:</p> <pre scala"=""><code> @Configuration @ConditionalOnClass(Servlet.class) @ConditionalOnWebApplication(type = Type.SERVLET) public static class FreeMarkerWebConfiguration extends FreeMarkerConfiguration { @Bean @ConditionalOnMissingBean(FreeMarkerConfig.class) public FreeMarkerConfigurer freeMarkerConfigurer() { FreeMarkerConfigurer configurer = new FreeMarkerConfigurer(); applyProperties(configurer); return configurer; } @Bean public freemarker.template.Configuration freeMarkerConfiguration( FreeMarkerConfig configurer) { return configurer.getConfiguration(); } @Bean @ConditionalOnMissingBean(name = "freeMarkerViewResolver") @ConditionalOnProperty(name = "spring.freemarker.enabled", matchIfMissing = true) public FreeMarkerViewResolver freeMarkerViewResolver() { FreeMarkerViewResolver resolver = new FreeMarkerViewResolver(); this.properties.applyToViewResolver(resolver); return resolver; } @Bean @ConditionalOnMissingBean @ConditionalOnEnabledResourceChain public ResourceUrlEncodingFilter resourceUrlEncodingFilter() { return new ResourceUrlEncodingFilter(); } }</code></pre> <p>其中?br />?)@ConditionalOnWebApplication(type = Type.SERVLET)?是当该应用是基于Servlet的Web应用时?/p> <p>?)@ConditionalOnMissingBean(name = "freeMarkerViewResolver"),是当Spring容器中不存在freeMarkerViewResolver的Bean时?/p> <p>?)@ConditionalOnProperty(name = "spring.freemarker.enabled", matchIfMissing = true),指定的spring.freemarker.enabled属性是否有。如果没有(IfMissing),设为true?/p> <p>当(1)(2)(3)三个条件都满足,则注册freeMarkerViewResolver这个Bean?/p> <p>我们也可以自定义我们自己的my-starter,以及实现对应的@MyEnableAutoConfiguration。SpringBoot有很多第三方starter,其自动配置的原理基本都是这样,比如mybatis-spring-boot-starter的MybatisAutoConfiguration,阅读源?a target="_blank">https://github.com/mybatis/spring-boot-starter[4]</a>?/p> <p>上面文字描述了这么多,再用一张形象生动的图来说明[5]?/p> <div class="yibqv"> <img src="//upload-images.jianshu.io/upload_images/1233356-a464868b4a17bfc1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/1233356-a464868b4a17bfc1.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="cursor: zoom-in;" alt="" /><br /><div class="yibqv">SpringBoot Autoconfigure 工作原理?/div> </div> <h2 class="yibqv">5.5 spring.factories与定义应用程序的初始化行?/h2> <p>上面说了这么多,讲的都是读取properties文件中key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的全限定名对应的值。SpringBoot内部还有许多其他的key用于过滤得到需要加载的类?/p> <pre mipsasm"=""><code># Initializers org.springframework.context.ApplicationContextInitializer=\ org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\ org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer # Application Listeners org.springframework.context.ApplicationListener=\ org.springframework.boot.autoconfigure.BackgroundPreinitializer # Auto Configuration Import Listeners org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\ org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener # Auto Configuration Import Filters org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\ org.springframework.boot.autoconfigure.condition.OnClassCondition # Failure analyzers org.springframework.boot.diagnostics.FailureAnalyzer=\ org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\ org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\ org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer # Template availability providers org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\ org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\ org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\ org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\ org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\ org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider</code></pre> <p>这些key仍然是定义在spring-boot/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories文件中?/p> <p>还有对应的用于测试的自动配置,在<br />spring-boot/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring.factories文件中定义?/p> <p>另外,我们使用spring.factories里还可以定制应用程序的初始化行为。这样我们就可以在应用程序载入前操纵Spring的应用程序上下文ApplicationContext?</p> <p>例如,可以使用ConfigurableApplicationContext类的addApplicationListener()方法,在应用上下文ApplicationContext中创建监听器?</p> <p>自动配置运行日志报告功能就是这么实现的。我们来看在spring.factories中,Initializers一段的配置?/p> <pre livescript"=""><code># Initializers org.springframework.context.ApplicationContextInitializer=\ org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\ org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer</code></pre> <p>其中,AutoConfigurationReportLoggingInitializer监听到系统事件时,比如上下文刷新ContextRefreshedEvent或应用程序启动故障ApplicationFailedEvent之类的事件,Spring Boot可以做一些事情。这里说的代码在AutoConfigurationReportLoggingInitializer.AutoConfigurationReportListener里面。关于支持的事件类型supportsEventType的如下:</p> <pre java"=""><code> private class AutoConfigurationReportListener implements GenericApplicationListener { ... @Override public boolean supportsEventType(ResolvableType resolvableType) { Class<?> type = resolvableType.getRawClass(); if (type == null) { return false; } return ContextRefreshedEvent.class.isAssignableFrom(type) || ApplicationFailedEvent.class.isAssignableFrom(type); } @Override public boolean supportsSourceType(Class<?> sourceType) { return true; } @Override public void onApplicationEvent(ApplicationEvent event) { AutoConfigurationReportLoggingInitializer.this.onApplicationEvent(event); } }</code></pre> <p>要以调试模式启动应用程序,可以使?Ddebug标识,或者在application.properties文件这添加属性debug= true。这样,当我们以调试模式启动应用程序时,SpringBoot就可以帮助我们创建自动配置的运行报告。对于每个自动配置,通过报告我们可以看到它启动或失败的原因?这个报告内容格式大致如下?/p> <pre asciidoc"=""><code>========================= AUTO-CONFIGURATION REPORT ========================= Positive matches: ----------------- DataSourceAutoConfiguration matched: - @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition) DataSourceAutoConfiguration#dataSourceInitializer matched: - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer; SearchStrategy: all) did not find any beans (OnBeanCondition) DataSourceAutoConfiguration.PooledDataSourceConfiguration matched: - AnyNestedCondition 2 matched 0 did not; NestedCondition on DataSourceAutoConfiguration.PooledDataSourceCondition.PooledDataSourceAvailable PooledDataSource found supported DataSource; NestedCondition on DataSourceAutoConfiguration.PooledDataSourceCondition.ExplicitType @ConditionalOnProperty (spring.datasource.type) matched (DataSourceAutoConfiguration.PooledDataSourceCondition) - @ConditionalOnMissingBean (types: javax.sql.DataSource,javax.sql.XADataSource; SearchStrategy: all) did not find any beans (OnBeanCondition) ... Exclusions: ----------- None Unconditional classes: ---------------------- org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration</code></pre> <p>除了SpringBoot官方提供的starter外,还有社区贡献的很多常用的第三方starter,列表可参考[2]?/p> <p>另外,国内很多公司使用RPC框架dubbo,关于SpringBoot集成dubbo,可参考:<a target="_blank">https://github.com/linux-china/spring-boot-dubbo?/a></p> <p>参考资料:</p> <p>1.<a target="_blank">//docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-starter</a><br />2.<a target="_blank">https://github.com/spring-projects/spring-boot/tree/master/spring-boot-starters</a><br />3.<a target="_blank">//www.cnblogs.com/javaee6/p/3714719.html</a><br />4.<a target="_blank">https://github.com/mybatis/spring-boot-starter</a><br />5.<a target="_blank">https://afoo.me/posts/2015-07-09-how-spring-boot-works.html</a></p> </div> <div class="yibqv"> <a href="/nb/10443788"> <em ic-search-notebook"=""></em> Spring Boot极简教程(??)</a></div></div><br /><br />作者:华夏商周秦汉唐宋元明清中华民?br />链接://www.jianshu.com/p/ccadc2bdb6d7<br />來源:简?br />著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处?/div><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/432717.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2017-08-02 16:35 <a href="//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432717.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java注解(Annotation)原理详解【转?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432713.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Wed, 02 Aug 2017 03:15:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432713.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/432713.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432713.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/432713.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/432713.html</trackback:ping><description><![CDATA[     摘要: from://blog.csdn.net/lylwo317/article/details/52163304序言注解在Java中到底是什么样的东西?具体是如何实现的?nbsp;本文将一层一层深入探究注解的实现原理。为了尽可能的将分析的过程呈现出来,所以文章包含了大量的截图和代码。(ps:如果图片看不清楚,请将网页放大来看,chrome可以通过ctrl+鼠标滚轮放大)前期准备知识方面开?..  <a href='//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432713.html'>阅读全文</a><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/432713.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2017-08-02 11:15 <a href="//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432713.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入理解Java:注解(Annotation?-注解处理?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432712.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Wed, 02 Aug 2017 03:07:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432712.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/432712.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432712.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/432712.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/432712.html</trackback:ping><description><![CDATA[<div id="cnblogs_post_body" style="margin: 0px 0px 20px; word-break: break-word; color: #333333; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13.3333px; background-color: #ffffff;"><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了。使用注解的过程中,很重要的一部分就是创建于使用注解处理器。Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处理器?/p><hr style="margin: 0px; padding: 0px;" /><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><strong style="margin: 0px; padding: 0px;">注解处理器类?java.lang.reflect.AnnotatedElement)?/strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">  Java使用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父接口。除此之外,Java在java.lang.reflect 包下新增了AnnotatedElement接口,该接口代表程序中可以接受注解的程序元素,该接口主要有如下几个实现类?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">  Class:类定义<br style="margin: 0px; padding: 0px;" />  Constructor:构造器定义<br style="margin: 0px; padding: 0px;" />  Field:累的成员变量定?br style="margin: 0px; padding: 0px;" />  Method:类的方法定?br style="margin: 0px; padding: 0px;" />  Package:类的包定义</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">  java.lang.reflect 包下主要包含一些实现反射功能的工具类,实际上,java.lang.reflect 包所有提供的反射API扩充了读取运行时Annotation信息的能力。当一个Annotation类型被定义为运行时的Annotation后,该注解才能是运行时可见,当class文件被装载时被保存在class文件中的Annotation才会被虚拟机读取?br style="margin: 0px; padding: 0px;" />  AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通过反射获取了某个类的AnnotatedElement对象之后,程序就可以调用该对象的如下四个个方法来访问Annotation信息?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">  方法1?lt;T extends Annotation> T getAnnotation(Class<T> annotationClass): 返回改程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null?br style="margin: 0px; padding: 0px;" />  方法2:Annotation[] getAnnotations():返回该程序元素上存在的所有注解?br style="margin: 0px; padding: 0px;" />  方法3:boolean is AnnotationPresent(Class<?extends Annotation> annotationClass):判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.<br style="margin: 0px; padding: 0px;" />  方法4:Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">  一个简单的注解处理器:  </p><div style="margin: 5px 0px; color: #000000; font-size: 12px !important;"><div style="margin: 5px 0px 0px;"><span style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.5 !important;"><a title="复制代码" style="margin: 0px; padding: 0px; border: none !important;"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 900px; border: none !important;" /></a></span></div><pre style="margin-top: 0px; margin-bottom: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "Courier New" !important;"><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*********注解声明**************</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * 水果名称注解 * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@author</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> peida * </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> @<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">interface</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> FruitName { String value() </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">default</span> ""<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">; } </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * 水果颜色注解 * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@author</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> peida * </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> @<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">interface</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> FruitColor { </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * 颜色枚举 * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@author</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> peida * </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">enum</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> Color{ BULE,RED,GREEN}; </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * 颜色属? * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@return</span> <span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> Color fruitColor() </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">default</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> Color.GREEN; } </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * 水果供应者注? * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@author</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> peida * </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> @<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">interface</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> FruitProvider { </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * 供应商编? * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@return</span> <span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">int</span> id() <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">default</span> -1<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">; </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * 供应商名? * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@return</span> <span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> String name() <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">default</span> ""<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">; </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * 供应商地址 * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@return</span> <span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> String address() <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">default</span> ""<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">; } </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*********注解使用**************</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> Apple { @FruitName(</span>"Apple"<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">) </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">private</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> String appleName; @FruitColor(fruitColor</span>=<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">Color.RED) </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">private</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> String appleColor; @FruitProvider(id</span>=1,name="陕西红富士集?,address="陕西省西安市延安?9号红富士大厦"<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">) </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">private</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> String appleProvider; </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">void</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> setAppleColor(String appleColor) { </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">this</span>.appleColor =<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> appleColor; } </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> String getAppleColor() { </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">return</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> appleColor; } </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">void</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> setAppleName(String appleName) { </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">this</span>.appleName =<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> appleName; } </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> String getAppleName() { </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">return</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> appleName; } </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">void</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> setAppleProvider(String appleProvider) { </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">this</span>.appleProvider =<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> appleProvider; } </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> String getAppleProvider() { </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">return</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> appleProvider; } </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">void</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> displayName(){ System.out.println(</span>"水果的名字是:苹?<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">); } } </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*********注解处理?*************</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> FruitInfoUtil { </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">static</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">void</span> getFruitInfo(Class<?><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> clazz){ String strFruitName</span>=" 水果名称?<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">; String strFruitColor</span>=" 水果颜色?<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">; String strFruitProvicer</span>="供应商信息:"<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">; Field[] fields </span>=<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> clazz.getDeclaredFields(); </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">for</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">(Field field :fields){ </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">if</span>(field.isAnnotationPresent(FruitName.<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span>)<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">){ FruitName fruitName </span>= (FruitName) field.getAnnotation(FruitName.<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">); strFruitName</span>=strFruitName+<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">fruitName.value(); System.out.println(strFruitName); } <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">else</span> </span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">if</span>(field.isAnnotationPresent(FruitColor.<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span>)<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">){ FruitColor fruitColor</span>= (FruitColor) field.getAnnotation(FruitColor.<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">); strFruitColor</span>=strFruitColor+<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">fruitColor.fruitColor().toString(); System.out.println(strFruitColor); } <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">else </span></span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">if</span>(field.isAnnotationPresent(FruitProvider.<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span>)<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">){ FruitProvider fruitProvider</span>= (FruitProvider) field.getAnnotation(FruitProvider.<span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">); strFruitProvicer</span>=" 供应商编号:"+fruitProvider.id()+" 供应商名称:"+fruitProvider.name()+" 供应商地址?+<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">fruitProvider.address(); System.out.println(strFruitProvicer); } } } } </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*********输出结果**************</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> FruitRun { </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">/**</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> * </span><span style="margin: 0px; padding: 0px; color: #808080; line-height: 1.5 !important;">@param</span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;"> args </span><span style="margin: 0px; padding: 0px; color: #008000; line-height: 1.5 !important;">*/</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">public</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">static</span> <span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">void</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> main(String[] args) { FruitInfoUtil.getFruitInfo(Apple.</span><span style="margin: 0px; padding: 0px; color: #0000ff; line-height: 1.5 !important;">class</span><span style="margin: 0px; padding: 0px; line-height: 1.5 !important;">); } } </span>====================================<span style="margin: 0px; padding: 0px; line-height: 1.5 !important;"> 水果名称:Apple 水果颜色:RED 供应商编号:</span>1 供应商名称:陕西红富士集?供应商地址:陕西省西安市延安路89号红富士大厦</pre><div style="margin: 5px 0px 0px;"><span style="margin: 0px; padding: 0px 5px 0px 0px; line-height: 1.5 !important;"><a title="复制代码" style="margin: 0px; padding: 0px; border: none !important;"><img src="//common.cnblogs.com/images/copycode.gif" alt="复制代码" style="margin: 0px; padding: 0px; max-width: 900px; border: none !important;" /></a></span></div></div><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;">   Java注解的基础知识点(见下面导图)基本都过了一遍,下一篇我们通过设计一个基于注解的简单的ORM框架,来综合应用和进一步加深对注解的各个知识点的理解和运用?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"><img src="//images.cnitblog.com/blog/34483/201304/25200814-475cf2f3a8d24e0bb3b4c442a4b44734.jpg" alt="" style="margin: 0px; padding: 0px; border: 0px; max-width: 900px;" /></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"> </p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px;"> </p></div><div id="MySignature" style="margin: 0px; color: #333333; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13.3333px; background-color: #ffffff;"><p style="margin: 12px 0px 0px; padding: 0px;"><br style="margin: 0px; padding: 0px;" /><a target="_blank" style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom: 1px dotted #333333;"></a></p></div><div style="margin: 0px; clear: both; color: #333333; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13.3333px; background-color: #ffffff;"></div><div id="blog_post_info_block" style="margin: 20px 0px 0px; color: #333333; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13.3333px; background-color: #ffffff;"><div id="BlogPostCategory" style="margin: 0px 0px 10px;">分类: <a target="_blank" style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom: 1px dotted #333333;">java</a></div><div id="EntryTag" style="margin: 20px 0px 0px; font-size: 9pt; color: gray;">标签: <a style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom: 1px dotted #333333;">深入理解Java</a>, <a style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom: 1px dotted #333333;">Java注解</a>, <a style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom: 1px dotted #333333;">Annotation</a>, <a style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom: 1px dotted #333333;">注解处理?/a>, <a style="margin: 0px; padding: 0px; text-decoration: none; color: #000000; border-bottom: 1px dotted #333333;">AnnotatedElement</a></div></div><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/432712.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2017-08-02 11:07 <a href="//www.ot7t.com.cn/xiaomage234/archive/2017/08/02/432712.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jvm 打印所有XX参数及值[转] - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/archive/2017/07/28/432701.html小马?/dc:creator>小马?/author>Fri, 28 Jul 2017 03:01:00 GMT//www.ot7t.com.cn/xiaomage234/archive/2017/07/28/432701.html//www.ot7t.com.cn/xiaomage234/comments/432701.html//www.ot7t.com.cn/xiaomage234/archive/2017/07/28/432701.html#Feedback0//www.ot7t.com.cn/xiaomage234/comments/commentRss/432701.html//www.ot7t.com.cn/xiaomage234/services/trackbacks/432701.html//blog.csdn.net/coslay/article/details/43458907
  1. 我们需要知道的是找到默认值的方法,掌握默认值的大概量级,在不同的版本下哪些是常用的默认参数,哪些是必须设置的参数,哪些是可以选择的、尽量不要去碰的设置?nbsp; 
  1. 参数设置同一个类型会有多种参数,而且都有默认值,大家不要混用噢,混用的结果很多时候难以预料,虽然在某种情况下可能得到了一个测试结果,但如果你没有真正了解JVM的内核源码,是不可能知道所有细节的,即测试结果不能当成任何场景下的一个结论,只能作为一种参考?nbsp; 

本篇文章基于Java 6?/span>update 21oder 21之后)版本, HotSpot JVM 提供给了两个新的参数,在JVM启动后,在命令行中可以输出所?/span>XX参数和值?/span>

  1. -XX:+PrintFlagsFinal and -XX:+PrintFlagsInitial  

让我们现在就了解一下新参数的输出。以 -client 作为参数?-XX:+PrintFlagsFinal   的结果是一个按字母排序?90个参数表格(注意,每个release版本参数的数量会不一样)

  1. $ java -client -XX:+PrintFlagsFinal Benchmark  
  2. [Global flags]  
  3. uintx AdaptivePermSizeWeight               = 20               {product}  
  4. uintx AdaptiveSizeDecrementScaleFactor     = 4                {product}  
  5. uintx AdaptiveSizeMajorGCDecayTimeScale    = 10               {product}  
  6. uintx AdaptiveSizePausePolicy              = 0                {product}[...]  
  7. uintx YoungGenerationSizeSupplementDecay   = 8                {product}  
  8. uintx YoungPLABSize                        = 4096             {product}  
  9.  bool ZeroTLAB                             = false            {product}  
  10.  intx hashCode                             = 0                {product}  

(校对注:你可以尝试在命令行输入上面的命令,亲自实现下)

表格的每一行包括五列,来表示一个XX参数。第一列表示参数的数据类型,第二列是名称,第四列为值,第五列是参数的类别。第三列”=”表示第四列是参数的默认值,?#8221;:=” 表明了参数被用户或者JVM赋值了?/p>

注意对于这个例子我只是用了Benchmark类,因为这个系列前面的章节也是用的这个类。甚至没有一个主类的情况下你能得到相同的输出,通过运行Java 带另外的参数 -version.现在让我们检查下 server VM提供了多少个参数。我们也能指定参?code>-XX:+UnlockExperimentalVMOptions ?code>-XX:+UnlockDiagnosticVMOptions ;来解锁任何额外的隐藏参数?/code>

  1. $ java -server -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal Benchmark  
724个参数,让我们看一眼那些已经被赋值的参数?/span>
  1. $ java -server -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal Benchmark | grep ":"  
  2. uintx InitialHeapSize                     := 57505088         {product}  
  3. uintx MaxHeapSize                         := 920649728        {product}  
  4. uintx ParallelGCThreads                   := 4                {product}  
  5.  bool PrintFlagsFinal                     := true             {product}  
  6.  bool UseParallelGC                       := true             {product}  

(校对注:这个命令非常有用)我们仅设置一个自己的参数 -XX:+PrintFlagsFinal。其他参数通过server VM基于系统设置的,以便以合适的堆大小和GC设置运行?/p>

如果我们只想看下所有XX参数的默认值,能够用一个相关的参数?XX:+PrintFlagsInitial  ??nbsp;-XX:+PrintFlagsInitial, 只是展示了第三列?#8220;=”的数据(也包括那些被设置其他值的参数)?/p>

然而,注意当与-XX:+PrintFlagsFinal 对比的时候,一些参数会丢失,大概因为这些参数是动态创建的?/p>

研究表格的内容是很有意思的,通过比较client和server VM的行为,很明显了解哪些参数会影响其他的参数。有兴趣的读者,可以看一下这篇不错文?a target="_blank" style="color: #4ec103; text-decoration: none; outline: none;">Inspecting HotSpot JVM Options。这个文章主要解释了第五列的参数类别?/p>

-XX:+PrintCommandLineFlags

让我们看下另外一个参数,事实上这个参数非常有? -XX:+PrintCommandLineFlags。这个参数让JVM打印出那些已经被用户或者JVM设置过的详细的XX参数的名称和值?/p>

换句话说,它列举?nbsp;-XX:+PrintFlagsFinal的结果中第三列有":="的参数。以这种方式?/code>我们可以?XX:+PrintCommandLineFlags作为快捷方式来查看修改过的参数。看下面的例子?/p>

  1. $ java -server -XX:+PrintCommandLineFlags Benchmark   

  1. -XX:InitialHeapSize=57505088 -XX:MaxHeapSize=920081408 -XX:ParallelGCThreads=4 -XX:+PrintCommandLineFlags -XX:+UseParallelGC  

现在如果我们每次启动java 程序的时候设?-XX:+PrintCommandLineFlags 并且输出到日志文件上,这样会记录下我们设置的JVM 参数对应用程序性能的影响。类似于 -showversion(?Part1),我建议 –XX:+PrintCommandLineFlags 这个参数应该总是设置在JVM启动的配置项里。因为你从不知道你什么时候会需要这些信息?/p>

奇怪的是在这个例子中,通过 -XX:+PrintCommandLineFlags 列出堆的最大值会比通过-XX:+PrintFlagsFinal列举出的相应值小一点。如果谁知道两者之间不同的原因,请告诉我?/p>

转载自://ifeve.com/useful-jvm-flags-part-3-printing-all-xx-flags-and-their-values/



   Java程序员有时候需要了解JVM相关的参数,不管是出于好奇或者工作需要?a title="Oracle知识? target="_blank" style="color: #df3434; text-decoration: none; font-weight: bold;">Oracle的文?中列出了一些,?a target="_blank" style="color: #ca0000; text-decoration: none;">点击这里),单并不是全部,而且有些参数的设置会默认启用或者关闭其他一些参数,而在某些情况下设置某个参数是不会生效的。还有些时候你想让JVM做某些事情,但是你不知道那个参数可以用。下面介绍一些办法用以列出所有参数,这样你在研究或者Google的时候也比较有明确的目标?/p>

    如果你想查看一下线上正在运行的JVM到底设置了那些参数,生效的是那些,可能用到的方法?/p>

    1. ?a title="Linux知识? target="_blank" style="color: #df3434; text-decoration: none; font-weight: bold;">Linux下用ps命令找到启动Java应用时的参数

  1. ps -ef | grep "your java app name"    

    这个命令会打出你启动Java应用时传给java命令的所有参数,你可以看到里面的JVM参数?/p>

    2.直接看启动脚本,或者参数配?/p>

    你未必能找到所有设置这JVM参数的地方,容易遗漏?br />

    一般来讲以上两种办法都需要对JVM了如指掌或者非常熟悉,至少对特定的参数?/p>

    

    其实JVM中有一个参?XX:+PrintFlagsFinal,可以打印出几乎所有的JVM支持的参数以及他们的默认值。如果你想要查看你的Java应用到底使用了那些参数,只要在启动的时候加上这个参数就可以了?/p>

    1.查看你使用的JDK支持的参?/p>

  1. java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version    

    2.打印Java应用启用的JVM参数

  1. java -XX:+PrintFlagsFinal -classpath=/path/to/your/libs MainClass    

    3.如果你的Java应用已经是运行状态了,你想查看某个JVM参数生效没有可以使用jinfo这个工具?strong>比如说大名鼎鼎的G1垃圾回收器,在JDK7update3中不论是客户?-client)还是服务?-server)模式下都不是默认启动的?/strong>

    jinfo是随JDK一起发布的,使用时先用jps找到Java应用的pid。直接运行jinfo可以查看使用说明?/p>

  1. jinfo -flag UseParallelOldGC 31072    

    3.如果你的Java应用已经是运行状态了,你想查看某个JVM参数生效没有可以使用jinfo这个工具?strong>比如说大名鼎鼎的G1垃圾回收器,在JDK7update3中不论是客户?-client)还是服务?-server)模式下都不是默认启动的?/strong>

    jinfo是随JDK一起发布的,使用时先用jps找到Java应用的pid。直接运行jinfo可以查看使用说明?/p>

  1. jinfo -flag UseParallelOldGC 31072  <span style="color: rgb(0, 204, 0); line-height: 18px; font-family: Consolas, 'Courier New', Courier, mono, serif; background-color: inherit;"> </span>  
  1. -XX:+UseParallelOldGC    
    JDK中实用的工具还很多,可以逐个的体验一?{JAVA_HOME}/bin目录中的每个命令,有惊喜?/span>


参考://blog.csdn.net/redhat456/article/details/7360249

?/dt>
0


]]>
杂谈GC【转?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2017/07/27/432697.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Thu, 27 Jul 2017 06:33:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2017/07/27/432697.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/432697.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2017/07/27/432697.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/432697.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/432697.html</trackback:ping><description><![CDATA[from://www.jianshu.com/p/2750c7c202ef<br /><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">上周有幸给部门的小伙伴分享了一些JVM相关的知识,在整个做PPT的过程中,也是对一个领域的碎片知识的整理,本文将针对虚拟机GC相关的一些内容进行整理,本文不会涉及到G1收集器?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">在Hotspot VM实现中,主要有两大类GC</p><ol style="box-sizing: border-box; margin-top: 0px; margin-bottom: 20px; word-break: break-word; padding: 0px; margin-left: 22px; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;"><li style="box-sizing: border-box; line-height: 30px; margin-bottom: 10px;"><span style="box-sizing: border-box; font-weight: 700;">Partial GC</span>:并不会堆整个GC堆进行收?ul style="box-sizing: border-box; margin-top: 15px; margin-bottom: 20px; padding: 0px; word-break: break-word; margin-left: 22px;"><li style="box-sizing: border-box; line-height: 30px; margin-bottom: 10px;">young gc:只收集 young gen 的GC</li><li style="box-sizing: border-box; line-height: 30px; margin-bottom: 10px;">old gc:只收集 old gen 的GC,只有CMS?concurrent collection</li><li style="box-sizing: border-box; line-height: 30px; margin-bottom: 10px;">mixed GC:收集整?young gen 以及部分 old gen 的GC,只有G1</li></ul></li><li style="box-sizing: border-box; line-height: 30px; margin-bottom: 10px;"><span style="box-sizing: border-box; font-weight: 700;">Full GC</span>:收集整个堆,包括young gen、old gen、perm gen(如果存在的话)?/li></ol><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">其实在各种文章或书上还可以看到Minor GC、Major GC的字眼,其中minor GC和young gc对应,而Major GC通常是和Full GC是等价的,由于HotSpot VM发展了这么多年,外界对各种名词的解读已经完全混乱了,所以Major GC有时也可能是指old gc,在下定论之前一定要先问清楚?/p><h3>单线程、并行、并?/h3><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">在GC收集器实现中,分为了单线程、并行和并发?br style="box-sizing: border-box;" /><span style="box-sizing: border-box; font-weight: 700;">单线程收集器</span>:如 Serial GC,这个比较好理解,即垃圾收集过程中只有单一线程在进行收集工作,实现也最简单?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;"><span style="box-sizing: border-box; font-weight: 700;">并行收集?/span>:如Parallel GC,每次运行时,不管是YGC,还是FGC,会 stop-the-world,暂停所有的用户线程,并采用多个线程同时进行垃圾收集?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;"><span style="box-sizing: border-box; font-weight: 700;">并发收集?/span>:如CMS GC,在新生代进行垃圾收集时和并行收集器类似,都是并行收集(当然具体算法中,你也可以设置成采用单线程进行收集),而且都会stop-the-world,主要的区别在于老年代的收集上,CMS在老年代进行垃圾收集时,大部分时间可以和用户线程并发执行的,只有小部分的时间stop-the-world,这就是它的优势,可以大大降低应用的暂停时间,当然也是有劣势的?/p><h3>算法组合</h3><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">Hotspot VM实现的几种GC算法组合中,其中CMS GC使用最广,因为现在都是大内存时代?/p><h4>1、Serial GC</h4><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">Serial generational collector (-XX:+UseSerialGC)<br style="box-sizing: border-box;" />是全局范围的Full GC,这种算法组合是最早出现的,当年的Java堆内存大小都还不大,使用Serial GC进行单线程收集,还感觉不出来GC耗时导致应用暂停的问?/p><h4>2、Parallel GC</h4><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">Parallel for young space, serial for old space generational collector (-XX:+UseParallelGC).<br style="box-sizing: border-box;" />Parallel for young and old space generational collector (-XX:+UseParallelOldGC)<br style="box-sizing: border-box;" />当Java堆慢慢变大时,发现已经无法忍受GC耗时带来的应用暂停了,出现了Parallel GC,采用多线程的方式进行垃圾收集,很明显可以提升垃圾收集效率?/p><h4>3、CMS GC</h4><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">Concurrent mark sweep with serial young space collector (-XX:+UseConcMarkSweepGC<br style="box-sizing: border-box;" />–XX:-UseParNewGC)<br style="box-sizing: border-box;" />Concurrent mark sweep with parallel young space collector (-XX:+UseConcMarkSweepGC)<br style="box-sizing: border-box;" />当Java堆达到更大时,比?G,使用Parallel GC带来的应用暂停已经很明显了,所有又出现?CMS GC,这是目前我看到线上环境使用的比较多的GC策略,在参数中添?code style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 12px; color: #657b83; background-color: #f6f6f6; border-radius: 4px; padding: 2px 4px; border: none; white-space: pre-wrap;">-XX:+UseConcMarkSweepGC</code>,对?young gen,会自动选用 ParNewGC,不需要额外添?nbsp;<code style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 12px; color: #657b83; background-color: #f6f6f6; border-radius: 4px; padding: 2px 4px; border: none; white-space: pre-wrap;">-XX:+UseParNewGC</code>?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">CMS虽然好,因为它的特殊算法,大部分的收集过程可以和用户线程并发执行,大大降低应用的暂停时间,不过也会带来负面影响,在收集完 old gen 之后,CMS并不会做整理过程,会产生空间碎片,如果这些碎片空间得不到利用,就会造成空间的浪费,整个过程中可能发?concurrent mode failure,导致一次真正意义的 full gc,采用单线程对整个堆(young+old+perm?使用MSC(Mark-Sweep-Compact)进行收集,这个过程意味着很慢很慢很慢,而且这个碎片问题是无法预测的.</p><h4>4、G1 GC</h4><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">G1 garbage collector (-XX:+UseG1GC),本文不对G1进行介绍</p><h3>触发条件</h3><h4>young gc</h4><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">对于 young gc,触发条件似乎要简单很多,?eden 区的内存不够时,就会触发young gc,我们看看在 eden 区给对象分配一块内存是怎样一个过程,画了一个简单的流程图,我一直觉得一个好的示意图可以让一个枯燥的过程变得更有意思?/p><div style="box-sizing: border-box; padding-bottom: 25px; width: 700px; margin-left: -40px; text-align: center; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;"><img src="//upload-images.jianshu.io/upload_images/2184951-b2c677f3d53a2d93.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" data-original-src="//upload-images.jianshu.io/upload_images/2184951-b2c677f3d53a2d93.png?imageMogr2/auto-orient/strip%7CimageView2/2" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 100%; height: auto; cursor: zoom-in; transition: all 0.25s ease-in-out;" alt="" /></div><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">?eden 区分配空间内存不足时有两种情况,为对象分配内存、为TLAB分配内存,总之就是内存不够,需要进行一?young gc 为eden区腾出空间为后续的内存申请做准备,然后由一个用户线程通知VM Thread,接下去要执行一?young gc?/p><h4>full gc</h4><h5>1、old gen 空间不足</h5><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">当创建一个大对象、大数组时,eden 区不足以分配这么大的空间,会尝试在old gen 中分配,如果这时 old gen 空间也不足时,会触发 full gc,为了避免上述导致的 full gc,调优时应尽量让对象?young gc 时就能够被回收,还有不要创建过大的对象和数组?/p><h5>2、统计得到的 young gc 晋升?old gen的对象平均总大小大于old gen 的剩余空?/h5><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">当准备触发一?young gc时,会判断这?young gc 是否安全,这里所谓的安全是当前老年代的剩余空间可以容纳之前 young gc 晋升对象的平均大小,或者可以容?young gen 的全部对象,如果结果是不安全的,就不会执行这?young gc,转而执行一?full gc</p><h5>3、perm gen 空间不足</h5><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">如果有perm gen的话,当系统中要加载的类、反射的类和调用的方法较多,而且perm gen没有足够空间时,也会触发一?full gc</p><h5>4、ygc出现 promotion failure</h5><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">promotion failure 发生?young gc 阶段,即 cms ?ParNewGC,当对象的gc年龄达到阈值时,或?eden ?to 区放不下时,会把该对象复制到 old gen,如?old gen 空间不足时,会发?promotion failure,并接下去触发full gc</p><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">在GC日志中,有时会看?concurrent mode failure 关键字,这是因为什么原因导致的问题? 对这一块的理解,很多文章都是说因为 concurrent mode failure 导致触发full gc,其实应该反过来,是full gc 导致?concurrent mode failure,在cms gc的算法实现中,通常说的cms是由一个后台线程定时触发的,默认每2秒检查一次old gen的内存使用率,当 old gen 的内存使用率达到<code style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 12px; color: #657b83; background-color: #f6f6f6; border-radius: 4px; padding: 2px 4px; border: none; white-space: pre-wrap;">-XX:CMSInitiatingOccupancyFraction</code>设置的值时,会触发一?cms gc,对 old gen 进行并发收集,而真正的 full gc 是通过 vm thread线程触发的,而且在判断当前ygc会失败的情况下触发full gc,如上一次ygc出现了promotion failure,如果执?full gc 时,发现后台线程正在执行 cms gc,就会导?concurrent mode failure?/p><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">对于以上这些情况?code style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 12px; color: #657b83; background-color: #f6f6f6; border-radius: 4px; padding: 2px 4px; border: none; white-space: pre-wrap;">CMSInitiatingOccupancyFraction</code>参数的设置就显得尤为重要,设置的太大的话,发生CMS时的剩余空间太小,在ygc的时候容易发生promotion failure,导?concurrent mode failure 发生的概率就增大,如果设置太小的话,会导?cms gc 的频率会增加,所以需要根据应用的需求对该参数进行调优?/p><h5>5、执?nbsp;<code style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: #657b83; background-color: #f6f6f6; border-radius: 4px; padding: 2px 4px; border: none; white-space: pre-wrap;">System.gc()</code>?code style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: #657b83; background-color: #f6f6f6; border-radius: 4px; padding: 2px 4px; border: none; white-space: pre-wrap;">jmap -histo:live <pid></code>?code style="box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: #657b83; background-color: #f6f6f6; border-radius: 4px; padding: 2px 4px; border: none; white-space: pre-wrap;">jmap -dump ...</code></h5><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">参考资?br style="box-sizing: border-box;" /><a target="_blank" style="box-sizing: border-box; background-color: transparent; color: #3194d0; text-decoration: none; cursor: pointer;">Major GC和Full GC的区别是什么?触发条件?/a></p><p style="box-sizing: border-box; margin: 0px 0px 25px; word-break: break-word; color: #2f2f2f; font-family: -apple-system, "SF UI Text", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif; font-size: 16px; background-color: #ffffff;">个人公众?/p><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/432697.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2017-07-27 14:33 <a href="//www.ot7t.com.cn/xiaomage234/archive/2017/07/27/432697.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入浅出 JIT 编译?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2017/06/08/432592.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Thu, 08 Jun 2017 09:27:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2017/06/08/432592.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/432592.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2017/06/08/432592.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/432592.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/432592.html</trackback:ping><description><![CDATA[from://blog.csdn.net/liaodehong/article/details/51605457<br /><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">本文将深入浅出地讲解 JIT 编译器在 JVM 中的运作原理,使读者能够更好的理解 <a title="Java 知识? target="_blank" style="text-decoration: none; color: #df3434; font-weight: bold;">Java</a> 底层机制并且为读者在 Java 性能优化领域打开更广的视野?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;"></p><h2 class="yibqv"><a name="t0" target="_blank" style="color: rgb(12, 137, 207);"></a>JIT 简?/h2><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;"></p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">JIT ?just in time 的缩? 也就是即时编译编译器。使用即时编译器技术,能够加?Java 程序的执行速度。下面,就对该编译器技术做个简单的讲解?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">首先,我们大家都知道,通常通过 javac 将程序源代码编译,转换成 java 字节码,JVM 通过解释字节码将其翻译成对应的机器指令,逐条读入,逐条解释翻译。很显然,经过解释执行,其执行速度必然会比可执行的二进制字节码程序慢很多。为了提高执行速度,引入了 JIT 技术?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">在运行时 JIT 会把翻译过的机器码保存起来,以备下次使用,因此从理论上来说,采用?JIT 技术可以接近以前纯编译技术。下面我们看看,JIT 的工作过程?/p><h3><a name="t1" target="_blank" style="color: rgb(12, 137, 207);"></a>JIT 编译过程</h3><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">?JIT 编译启用时(默认是启用的),JVM 读入.class 文件解释后,将其发给 JIT 编译器。JIT 编译器将字节码编译成本机机器代码,下图展示了该过程?/p><h5><a name="t2" target="_blank" style="color: rgb(12, 137, 207);"></a>?1. JIT 工作原理?/h5><img alt="?1. JIT 工作原理? src="https://www.ibm.com/developerworks/cn/java/j-lo-just-in-time/img001.png" width="576" style="border: none; max-width: 100%; max-height: 100%; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;" /><p ibm-back-to-top"="" style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;"><a target="_blank" style="text-decoration: none; color: #745285; margin: 0px; padding: 0px 0px 0px 16px; border-width: 0px; border-bottom-style: none; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; display: inline; line-height: 1.065em; font-weight: bold;">回页?/a></p><h2 class="yibqv"><a name="t3" target="_blank" style="color: rgb(12, 137, 207);"></a>Hot Spot 编译</h2><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">?JVM 执行代码时,它并不立即开始编译代码。这主要有两个原因:</p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">首先,如果这段代码本身在将来只会被执行一次,那么从本质上看,编译就是在浪费精力。因为将代码翻译?java 字节码相对于编译这段代码并执行代码来说,要快很多?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">当然,如果一段代码频繁的调用方法,或是一个循环,也就是这段代码被多次执行,那么编译就非常值得了。因此,编译器具有的这种权衡能力会首先执行解释后的代码,然后再去分辨哪些方法会被频繁调用来保证其本身的编译。其实说简单点,就?JIT 在起作用,我们知道,对于 Java 代码,刚开始都是被编译器编译成字节码文件,然后字节码文件会被交?JVM 解释执行,所以可以说 Java 本身是一种半编译半解释执行的语言。Hot Spot VM 采用?JIT compile 技术,将运行频率很高的字节码直接编译为机器指令执行以提高性能,所以当字节码被 JIT 编译为机器码的时候,要说它是编译执行的也可以。也就是说,运行时,部分代码可能?JIT 翻译为目标机器指令(?method 为翻译单位,还会保存起来,第二次执行就不用翻译了)直接执行?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">第二个原因是最优化,当 JVM 执行某一方法或遍历循环的次数越多,就会更加了解代码结构,那么 JVM 在编译代码的时候就做出相应的优化?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">我们将在后面讲解这些优化策略,这里,先举一个简单的例子:我们知?equals() 这个方法存在于每一?nbsp;<a title="Java 知识? target="_blank" style="text-decoration: none; color: #df3434; font-weight: bold;">Java </a>Object 中(因为是从 Object class 继承而来)而且经常被覆写。当解释器遇?b = obj1.equals(obj2) 这样一句代码,它则会查?obj1 的类型从而得知到底运行哪一?equals() 方法。而这个动态查询的过程从某种程度上说是很耗时的?/p><h3><a name="t4" target="_blank" style="color: rgb(12, 137, 207);"></a>寄存器和主存</h3><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">其中一个最重要的优化策略是编译器可以决定何时从主存取值,何时向寄存器存值。考虑下面这段代码?/p><h5><a name="t5" target="_blank" style="color: rgb(12, 137, 207);"></a>清单 1. 主存 or 寄存器测试代?/h5><div style="color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;"><pre name="code" style="white-space: pre-wrap; word-wrap: break-word; margin-top: 0px; border: 1px solid #cccccc; outline: 0px; font-size: 11px; vertical-align: baseline; width: 780px; font-family: "Andale Mono", "Lucida Console", Monaco, Liberation, fixed, monospace; overflow: auto; color: #000000; clear: right; margin-bottom: 6px !important; padding: 5px 10px 5px 3px !important; background-color: #f7f7f7 !important;">public class RegisterTest { private int sum; public void calculateSum(int n) { for (int i = 0; i < n; ++i) { sum += i; } } }</pre></div><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">在某些时刻,sum 变量居于主存之中,但是从主存中检索值是开销很大的操作,需要多次循环才可以完成操作。正如上面的例子,如果循环的每一次都是从主存取值,性能是非常低的。相反,编译器加载一个寄存器?sum 并赋予其初始值,利用寄存器里的值来执行循环,并将最终的结果从寄存器返回给主存。这样的优化策略则是非常高效的。但是线程的同步对于这种操作来说是至关重要的,因为一个线程无法得知另一个线程所使用的寄存器里变量的值,线程同步可以很好的解决这一问题,有关于线程同步的知识,我们将在后续文章中进行讲解?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">寄存器的使用是编译器的一个非常普遍的优化?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">回到之前的例子,JVM 注意到每次运行代码时,obj1 都是 java.lang.String 这种类型,那?JVM 生成的被编译后的代码则是直接调用 String.equals() 方法。这样代码的执行将变得非常快,因为不仅它是被编译过的,而且它会跳过查找该调用哪个方法的步骤?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">当然过程并不是上面所述这样简单,如果下次执行代码时,obj1 不再?String 类型了,JVM 将不得不再生成新的字节码。尽管如此,之后执行的过程中,还是会变的更快,因为同样会跳过查找该调用哪个方法的步骤。这种优化只会在代码被运行和观察一段时间之后发生。这也就是为什?JIT 编译器不会理解编译代码而是选择等待然后再去编译某些代码片段的第二个原因?/p><p ibm-back-to-top"="" style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;"><a target="_blank" style="text-decoration: none; color: #745285; margin: 0px; padding: 0px 0px 0px 16px; border-width: 0px; border-bottom-style: none; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; display: inline; line-height: 1.065em; font-weight: bold;">回页?/a></p><h2 class="yibqv"><a name="t6" target="_blank" style="color: rgb(12, 137, 207);"></a>初级调优:客户模式或服务器模?/h2><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">JIT 编译器在运行程序时有两种编译模式可以选择,并且其会在运行时决定使用哪一种以达到最优性能。这两种编译模式的命名源自于命令行参数(eg: -client 或?-server)。JVM Server 模式?client 模式启动,最主要的差别在于:-server 模式启动时,速度较慢,但是一旦运行起来后,性能将会有很大的提升。原因是:当虚拟机运行在-client 模式的时候,使用的是一个代号为 C1 的轻量级编译器,?server 模式启动的虚拟机采用相对重量级代号为 C2 的编译器。C2 ?C1 编译器编译的相对彻底,服务起来之后,性能更高?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">通过 java -version 命令行可以直接查看当前系统使用的?client 还是 server 模式。例如:</p><h5><a name="t7" target="_blank" style="color: rgb(12, 137, 207);"></a>?2. 查看编译模式</h5><img alt="?2. 查看编译模式" src="https://www.ibm.com/developerworks/cn/java/j-lo-just-in-time/img002.png" width="624" style="border: none; max-width: 100%; max-height: 100%; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;" /><p ibm-back-to-top"="" style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;"><a target="_blank" style="text-decoration: none; color: #745285; margin: 0px; padding: 0px 0px 0px 16px; border-width: 0px; border-bottom-style: none; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; display: inline; line-height: 1.065em; font-weight: bold;">回页?/a></p><h2 class="yibqv"><a name="t8" target="_blank" style="color: rgb(12, 137, 207);"></a>中级编译器调?/h2><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">大多数情况下,优化编译器其实只是选择合适的 JVM 以及为目标主机选择合适的编译器(-cient?server 或是-xx:+TieredCompilation)。多层编译经常是长时运行应用程序的最佳选择,短暂应用程序则选择毫秒级性能?client 编译器?/p><h3><a name="t9" target="_blank" style="color: rgb(12, 137, 207);"></a>优化代码缓存</h3><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">?JVM 编译代码时,它会将汇编指令集保存在代码缓存。代码缓存具有固定的大小,并且一旦它被填满,JVM 则不能再编译更多的代码?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">我们可以很容易地看到如果代码缓存很小所具有的潜在问题。有些热点代码将会被编译,而其他的则不会被编译,这个应用程序将会以运行大量的解释代码来结束?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">这是当使?client 编译器模式或分层编译时很频繁的一个问题。当使用普?server 编译器模式时,编译合格的类的数量将被填入代码缓存,通常只有少量的类会被编译。但是当使用 client 编译器模式时,编译合格的类的数量将会高很多?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">?Java 7 版本,分层编译默认的代码缓存大小经常是不够的,需要经常提高代码缓存大小。大型项目若使用 client 编译器模式,则也需要提高代码缓存大小?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">现在并没有一个好的机制可以确定一个特定的应用到底需要多大的代码缓存。因此,当需要提高代码缓存时,这将是一种凑巧的操作,一个通常的做法是将代码缓存变成默认大小的两倍或四倍?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">可以通过 –XX:ReservedCodeCacheSize=Nflag(N 就是之前提到的默认大小)来最大化代码缓存大小。代码缓存的管理类似?JVM 中的内存管理:有一个初始大小(?XX:InitialCodeCacheSize=N 来声明)。代码缓存的大小从初始大小开始,随着缓存被填满而逐渐扩大。代码缓存的初始大小是基于芯?a title="大型网站架构知识? target="_blank" style="text-decoration: none; color: #df3434; font-weight: bold;">架构</a>(例?Intel 系列机器,client 编译器模式下代码缓存大小起始?160KB,server 编译器模式下代码缓存大小则起始于 2496KB)以及使用的编译器的。重定义代码缓存的大小并不会真正影响性能,所以设?ReservedCodeCacheSize 的大小一般是必要的?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">再者,如果 JVM ?32 位的,那么运行过程大小不能超?4GB。这包括?Java 堆,JVM 自身所有的代码空间(包括其本身的库和线程栈),应用程序分配的任何的本地内存,当然还有代码缓存?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">所以说代码缓存并不是无限的,很多时候需要为大型应用程序来调优(或者甚至是使用分层编译的中型应用程序)。比?64 位机器,为代码缓存设置一个很大的值并不会对应用程序本身造成影响,应用程序并不会内存溢出,这些额外的内存预定一般都是被<a title="操作系统知识? target="_blank" style="text-decoration: none; color: #df3434; font-weight: bold;">操作系统</a>所接受的?/p><h3><a name="t10" target="_blank" style="color: rgb(12, 137, 207);"></a>编译阈?/h3><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">?JVM 中,编译是基于两个计数器的:一个是方法被调用的次数,另一个是方法中循环被回弹执行的次数。回弹可以有效的被认为是循环被执行完成的次数,不仅因为它是循环的结尾,也可能是因为它执行到了一个分支语句,例如 continue?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">?JVM 执行一?Java 方法,它会检查这两个计数器的总和以决定这个方法是否有资格被编译。如果有,则这个方法将排队等待编译。这种编译形式并没有一个官方的名字,但是一般被叫做标准编译?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">但是如果方法里有一个很长的循环或者是一个永远都不会退出并提供了所有逻辑的程序会怎么样呢?这种情况下,JVM 需要编译循环而并不等待方法被调用。所以每执行完一次循环,分支计数器都会自增和自检。如果分支计数器计数超出其自身阈值,那么这个循环(并不是整个方法)将具有被编译资格?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">这种编译叫做栈上替换(OSR),因为即使循环被编译了,这也是不够的:JVM 必须有能力当循环正在运行时,开始执行此循环已被编译的版本。换句话说,当循环的代码被编译完成,?JVM 替换了代码(前栈),那么循环的下个迭代执行最新的被编译版本则会更加快?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">标准编译是被-XX:CompileThreshold=Nflag 的值所触发。Client 编译器模式下,N 默认的?1500,?Server 编译器模式下,N 默认的值则?10000。改?CompileThreshold 标志的值将会使编译器相对正常情况下提前(或推迟)编译代码。在性能领域,改?CompileThreshold 标志是很被推荐且流行的方法。事实上,您可能知道 Java 基准经常使用此标志(比如:对于很?server 编译器来说,经常在经?8000 次迭代后改变次标志)?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">我们已经知道 client 编译器和 server 编译器在最终的性能上有很大的差别,很大程度上是因为编译器在编译一个特定的方法时,对于两种编译器可用的信息并不一样。降低编译阈值,尤其是对?server 编译器,承担着不能使应用程序运行达到最佳性能的风险,但是经过<a title="软件测试知识? target="_blank" style="text-decoration: none; color: #df3434; font-weight: bold;">测试</a>应用程序我们也发现,将阈值从 8000 变成 10000,其实有着非常小的区别和影响?/p><h3><a name="t11" target="_blank" style="color: rgb(12, 137, 207);"></a>检查编译过?/h3><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">中级优化的最后一点其实并不是优化本身,而是它们并不能提高应用程序的性能。它们是 JVM(以及其他工具)的各个标志,并可以给出编译工作的可见性。它们中最重要的就?-XX:+PrintCompilation(默认状态下?false)?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">如果 PrintCompilation 被启用,每次一个方法(或循环)被编译,JVM 都会打印出刚刚编译过的相关信息。不同的 Java 版本输出形式不一样,我们这里所说的是基?Java 7 版本的?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">编译日志中大部分的行信息都是下面的形式:</p><h5><a name="t12" target="_blank" style="color: rgb(12, 137, 207);"></a>清单 2. 日志形式</h5><div style="color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;"><pre name="code" style="white-space: pre-wrap; word-wrap: break-word; margin-top: 0px; border: 1px solid #cccccc; outline: 0px; font-size: 11px; vertical-align: baseline; width: 780px; font-family: "Andale Mono", "Lucida Console", Monaco, Liberation, fixed, monospace; overflow: auto; color: #000000; clear: right; margin-bottom: 6px !important; padding: 5px 10px 5px 3px !important; background-color: #f7f7f7 !important;">timestamp compilation_id attributes (tiered_level) method_name size depot</pre></div><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">这里 timestamp 是编译完成时的时间戳,compilation_id 是一个内部的任务 ID,且通常情况下这个数字是单调递增的,但有时候对?server 编译器(或任何增加编译阈值的时候),您可能会看到失序的编译 ID。这表明编译线程之间有些快有些慢,但请不要随意推断认为是某个编译器任务莫名其妙的非常慢?/p><h3><a name="t13" target="_blank" style="color: rgb(12, 137, 207);"></a>?jstat 命令检查编?/h3><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">要想看到编译日志,则需要程序以-XX:+PrintCompilation flag 启动。如果程序启动时没有 flag,您可以通过 jstat 命令得到有限的可见性信息?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">Jstat 有两个选项可以提供编译器信息。其中,-compile 选项提供总共有多少方法被编译的总结信息(下?6006 是要被检查的程序的进?ID):</p><h5><a name="t14" target="_blank" style="color: rgb(12, 137, 207);"></a>清单 3 进程详情</h5><div style="color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;"><pre name="code" style="white-space: pre-wrap; word-wrap: break-word; margin-top: 0px; border: 1px solid #cccccc; outline: 0px; font-size: 11px; vertical-align: baseline; width: 780px; font-family: "Andale Mono", "Lucida Console", Monaco, Liberation, fixed, monospace; overflow: auto; color: #000000; clear: right; margin-bottom: 6px !important; padding: 5px 10px 5px 3px !important; background-color: #f7f7f7 !important;">% jstat -compiler 6006 CompiledFailedInvalid TimeFailedTypeFailedMethod 206 0 0 1.97 0</pre></div><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">注意,这里也列出了编译失败的方法的个数信息,以及编译失败的最后一个方法的名称?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">另一种选择,您可以使用-printcompilation 选项得到最后一个被编译的方法的编译信息。因?jstat 命令有一个参数选项用来重复其操作,您可以观察每一次方法被编译的情况。举个例子:</p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">Jstat ?6006 ?ID 进程?1000 毫秒执行一次: %jstat –printcompilation 6006 1000,具体的输出信息在此不再描述?/p><p ibm-back-to-top"="" style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;"><a target="_blank" style="text-decoration: none; color: #745285; margin: 0px; padding: 0px 0px 0px 16px; border-width: 0px; border-bottom-style: none; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; display: inline; line-height: 1.065em; font-weight: bold;">回页?/a></p><h2 class="yibqv"><a name="t15" target="_blank" style="color: rgb(12, 137, 207);"></a>高级编译器调?/h2><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">这一节我们将介绍编译工作剩下的细节,并且过程中我们会探讨一些额外的调优策略。调优的存在很大程度上帮助了 JVM 工程师诊?JVM 自身的行为。如果您对编译器的工作原理很感兴趣,这一节您一定会喜欢?/p><h3><a name="t16" target="_blank" style="color: rgb(12, 137, 207);"></a>编译线程</h3><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">从前文中我们知道,当一个方法(或循环)拥有编译资格时,它就会排队并等待编译。这个队列是由一个或很多个后台线程组成。这也就是说编译是一个异步的过程。它允许程序在代码正在编译时被继续执行。如果一个方法被标准编译方式所编译,那么下一个方法调用则会执行已编译的方法。如果一个循环被栈上替换方式所编译,那么下一次循环迭代则会执行新编译的代码?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">这些队列并不会严格的遵守先进先出原则:哪一个方法的调用计数器计数更高,哪一个就拥有优先权。所以即使当一个程序开始执行,并且有大量的代码需要编译,这个优先权顺序将帮助并保证最重要的代码被优先编译(这也是为什么编?ID ?PrintComilation 的输出结果中有时会失序的另一个原因)?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">当使?client 编译器时,JVM 启动一个编译线程,?server 编译器有两个这样的线程。当分层编译生效时,JVM 会基于某些复杂方程式默认启动多个 client ?server 线程,涉及双日志在目标平台上?CPU 数量。如下图所示:</p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">分层编译?C1 ?C2 编译器线程默认数量:</p><h5><a name="t17" target="_blank" style="color: rgb(12, 137, 207);"></a>?3. C1 ?C2 编译器默认数?/h5><img alt="?3. C1 C2 编译器默认数? src="https://www.ibm.com/developerworks/cn/java/j-lo-just-in-time/img003.png" width="435" style="border: none; max-width: 100%; max-height: 100%; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;" /><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">编译器线程的数量可以通过-XX:CICompilerCount=N flag 进行调节设置。这个数量是 JVM 将要执行队列所用的线程总数。对于分层编译,三分之一的(至少一个)线程被用于执?client 编译器队列,剩下的(也是至少一个)被用来执?server 编译器队列?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">在何时我们应该考虑调整这个值呢?如果一个程序被运行在单 CPU 机器上,那么只有一个编译线程会更好一些:因为对于某个线程来说,其?CPU 的使用是有限的,并且在很多情况下越少的线程竞争资源会使其运行性能更高。然而,这个优势仅仅局限于初始预热阶段,之后,这些具有编译资格的方法并不会真的引起 CPU 争用。当一个股票批处理应用程序运行在单 CPU 机器上并且编译器线程被限制成只有一个,那么最初的计算过程将比一般情况下?10%(因为它没有被其他线程进?CPU 争用)。迭代运行的次数越多,最初的性能收益就相对越少,直到所有的热点方法被编译完性能收益也随之终止?/p><p ibm-back-to-top"="" style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;"><a target="_blank" style="text-decoration: none; color: #745285; margin: 0px; padding: 0px 0px 0px 16px; border-width: 0px; border-bottom-style: none; outline: 0px; vertical-align: baseline; font-family: Arial, sans-serif; display: inline; line-height: 1.065em; font-weight: bold;">回页?/a></p><h2 class="yibqv"><a name="t18" target="_blank" style="color: rgb(12, 137, 207);"></a>结束?/h2><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">本文详细介绍?JIT 编译器的工作原理。从优化的角度讲,最简单的选择就是使用 server 编译器的分层编译技术,这将解决大约 90%左右的与编译器直接相关的性能问题。最后,请保证代码缓存的大小设置的足够大,这样编译器将会提供最高的编译性能?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: "microsoft yahei"; font-size: 15px; background-color: #ffffff;">转载?a target="_blank" style="text-decoration: none; color: #0c89cf;">点击打开链接</a></p><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/432592.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2017-06-08 17:27 <a href="//www.ot7t.com.cn/xiaomage234/archive/2017/06/08/432592.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>浅谈对JIT编译器的理解 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/archive/2017/06/08/432591.html小马?/dc:creator>小马?/author>Thu, 08 Jun 2017 09:26:00 GMT//www.ot7t.com.cn/xiaomage234/archive/2017/06/08/432591.html//www.ot7t.com.cn/xiaomage234/comments/432591.html//www.ot7t.com.cn/xiaomage234/archive/2017/06/08/432591.html#Feedback0//www.ot7t.com.cn/xiaomage234/comments/commentRss/432591.html//www.ot7t.com.cn/xiaomage234/services/trackbacks/432591.htmlfrom://www.cnblogs.com/insistence/p/5901457.html

1. 什么是Just In Time编译?

Hot Spot 编译

?JVM 执行代码时,它并不立即开始编译代码。这主要有两个原因:

首先,如果这段代码本身在将来只会被执行一次,那么从本质上看,编译就是在浪费精力。因为将代码翻译?java 字节码相对于编译这段代码并执行代码来说,要快很多?/p>

?然,如果一段代码频繁的调用方法,或是一个循环,也就是这段代码被多次执行,那么编译就非常值得了。因此,编译器具有的这种权衡能力会首先执行解释后的代 码,然后再去分辨哪些方法会被频繁调用来保证其本身的编译。其实说简单点,就?JIT 在起作用,我们知道,对于 Java 代码,刚开始都是被编译器编译成字节码文件,然后字节码文件会被交?JVM 解释执行,所以可以说 Java 本身是一种半编译半解释执行的语言。Hot Spot VM 采用?JIT compile 技术,将运行频率很高的字节码直接编译为机器指令执行以提高性能,所以当字节码被 JIT 编译为机器码的时候,要说它是编译执行的也可以。也就是说,运行时,部分代码可能?JIT 翻译为目标机器指令(?method 为翻译单位,还会保存起来,第二次执行就不用翻译了)直接执行?/p>

第二个原因是最优化,当 JVM 执行某一方法或遍历循环的次数越多,就会更加了解代码结构,那么 JVM 在编译代码的时候就做出相应的优化?/p>

?们将在后面讲解这些优化策略,这里,先举一个简单的例子:我们知?equals() 这个方法存在于每一?Java Object 中(因为是从 Object class 继承而来)而且经常被覆写。当解释器遇?b = obj1.equals(obj2) 这样一句代码,它则会查?obj1 的类型从而得知到底运行哪一?equals() 方法。而这个动态查询的过程从某种程度上说是很耗时的?/p>

在主流商用JVM(HotSpot、J9)中,Java程序一开始是通过解释器(Interpreter?/strong>进行解释执行的。当JVM发现某个方法或代码块运行特别频繁时,就会把这些代码认定为“热点代码(Hot Spot Code?/strong>”,然后JVM会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为:即时编译器(Just In Time Compiler,JIT?/p>

JIT编译器是“动态编译器”的一种,相对?#8220;静态编译器”则是指的比如:C/C++的编译器

JIT并不是JVM的必须部分,JVM规范并没有规定JIT必须存在,更没有限定和指导JIT。但是,JIT性能的好坏、代码优化程度的高低却是衡量一款JVM是否优秀的最关键指标之一,也是虚拟机中最核心且最能体现虚拟机技术水平的部分?/p>


2. 编译器与解释?/h1>

首先,不是所有JVM都采用编译器和解释器并存的架构,但主流商用虚拟机,都同时包含这两部分?/p>

2.1 配合过程

  1. 当程序需要迅速启动然后执行的时候,解释器可以首先发挥作?/strong>,编译器不运行从而省去编译时间,立即执行程序

  2. 在程序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获得更高的执行效率

  3. 当程序运行环境中内存资源限制较大(如部分嵌入式系统中),可以使用解释执行来节约内存;反之,则可以使用编译执行来提升效率?/p>

  4. 同时,解释器还可以作为编译器(C2才会激进优化)激进优化时的一?#8220;逃生?/strong>”,让编译器根据概率选择一些大多数时候都能提升运行速度的优化手段,当激进优化假设不成立。如:加载了新类后,类型继承结构出现变化,出?#8220;罕见陷阱(Uncommon Trap?#8221;时,可以通过逆优化(Deoptimization?strong style="margin: 0px; padding: 0px;">退回到解释状?/strong>继续执行 
    (部分没有解释器的虚拟机,也会采用不进行激进优化的C1编译器担?#8220;逃生?#8221;的角?

    这里写图片描? style=

2.2 解释?- Interpreter

Interpreter解释执行class文件,好像JavaScript执行引擎一?/p>

特殊的例子:

  • 最早的Sun Classic VM只有Interpreter
  • BEA JRockit VM则只有Compiler,但它主要面向服务端应用,部署在其上的应用不重点关注启动时间

2.3 编译?- Compiler

只说HotSpot JVM

1. C1和C2?/h3>

HotSpot虚拟机内置了两个即时编译器,分别称为Client Compiler和Server Compiler,习惯上将前者称为C1,后者称为C2

2. 使用C1还是C2?/h3>

HotSpot默认采用解释器和其中一?/strong>编译器直接配合的方式工作,使用那个编译器取决于虚拟机运行的模?/strong>,HotSpot会根据自身版本和宿主机器硬件性能自动选择模式,用户也可以使用“-client”?#8221;-server”参数去指?/p>

  1. 混合模式(Mixed Mode?nbsp;
    默认的模?/strong>,如上面描述的这种方式就是mixed mode

  2. 解释模式(Interpreted Mode?nbsp;
    可以使用参数“-Xint”,在此模式下全部代码解释执行

  3. 编译模式(Compiled Mode?nbsp;
    参数“-Xcomp”,此模式优先采用编译,但?strong style="margin: 0px; padding: 0px;">无法编译时也会解?/strong>(在最新的HotSpot中此参数被取消)

    可以看到,我的JVM现在是mixed mode 
    这里写图片描? style=

重要?#8595;

在JDK1.7?.7仅包括Server模式)之后,HotSpot就不是默?#8220;采用解释器和其中一?/strong>编译?#8221;配合的方式了,而是采用了分层编译,分层编译时C1和C2有可能同时工?/p>


3. 分层编译

3.1 为什么要分层编译?/h2>

由于编译器compile本地代码需要占用程序时间,要编译出优化程度更高的代码所花费的时间可能更长,且此时解释器还要替编译器收集性能监控信息,这对解释执行的速度也有影响

所以,为了在程序启动响应时间与运行效率之间达到最佳平衡,HotSpot在JDK1.6中出现了分层编译(Tiered Compilation)的概念并在JDK1.7的Server模式JVM中作为默认策略被开?/p>

3.2 编译?tier(或者叫级别?/h2>

分层编译根据编译器编译、优化的规模与耗时,划分了不同的编译层次(不只以下3种),包括:

  • ?层,程序解释执行?strong style="margin: 0px; padding: 0px;">没有编译),解释器不开启性能监控功能,可触发?层编译?/p>

  • ?层,也称C1编译,将字节码编译为本地代码,进行简单、可靠的优化,如有必要将加入性能监控的逻辑

  • ?层(?层以上),也称为C2编译,也是将字节码编译为本地代码,但是会启用一些编译耗时较长的优化,甚至?/strong>根据性能监控信息进行一些不可靠?strong style="margin: 0px; padding: 0px;">激进优?/strong>

实施分层编译后,C1和C2将会同时工作,许多代码会?strong style="margin: 0px; padding: 0px;">多次编译,用C1获取更高的编译速度,用C2来获取更好的编译质量,且在解释执行的时候解释器也无须再承担收集性能监控信息的任?/p>


4. 编译对象与触发条?/h1>

1. 谁被编译了?

编译对象就是之前说的“热点代码”,它有两类:

  1. 被多次调用的方法 
    • 一个方法被多次调用,理应称为热点代码,这种编译也是虚拟机中标准的JIT编译方式
  2. 被多次执行的循环?/strong> 
    • 编译动作由循环体出发,但编译对象依然会以整个方法为对?/strong>?/li>
    • 这种编译方式由于编译发生在方法执行过程中,因此形象的称为:栈上替换(On Stack Replacement- OSR编译,即方法栈帧还在栈上,方法就被替换了?/li>

2. 触发条件

1. 综述

上面的方法和循环体都?#8220;多次”,那么多少算多?换个说法就是编译的触发条件?/p>

判断一段代码是不是热点代码,是不是需要触发JIT编译,这样的行为称为:热点探测(Hot Spot Detection),有几种主流的探测方式?/p>

  1. 基于计数器的热点探测(Counter Based Hot Spot Detection?nbsp;
    虚拟机会为每个方法(或每个代码块)建立计数器,统计执行次数,如果超过阀值那么就是热点代码。缺点是维护计数器开销?/p>

  2. 基于采样的热点探测(Sample Based Hot Spot Detection?nbsp;
    虚拟机会周期性检查各个线程的栈顶,如果某个方法经常出现在栈顶,那么就是热点代码。缺点是不精确?/p>

  3. 基于踪迹的热点探测(Trace Based Hot Spot Detection?nbsp;
    Dalvik中的JIT编译器使用这种方?/p>

2. HotSpot

HotSpot使用的是?种,因此它为每个方法准备了两类计数器:方法调用计数器(Invocation Counter)和回边计数器(Back Edge Counter?/p>

  1. 方法计数?/p>

    • 默认阀值,在Client模式下是1500次,Server?0000次,可以通过参数“-XX:CompileThreshold”来设?/p>

    • 当一个方法被调用时会首先检查是否存在被JIT编译过得版本,如果存在则使用此本地代码来执行;如果不存在,则将方法计数器+1,然后判?#8220;方法计数器和回边计数器之?#8221;是否超过阀值,如果是则会向编译器提交一个方法编译请?/p>

    • 默认情况下,执行引擎并不会同步等待上面的编译完成,而是会继续解释执行。当编译完成后,此方法的调用入口地址会被系统自动改写为新的本地代码地址

    • 还有一点,热度是会衰减的,也就是说不是仅仅+,也?,热度衰减动作是在虚拟机的GC执行时顺便进行的

  2. 回边计数?/p>

    • 回边,顾名思义,只有执行到大括?#8221;}”时才?1

    • 默认阀值,Client?3995,Server?0700

    • 它的调用逻辑和方法计数器差不多,只不过遇到回边指令时+1、超过阀值时会提交OSR编译请求以及这里没有热度衰减


5. 编译过程

编译过程是在后台线程(daemon)中完成的,可以通过参数“-XX:-BackgroundCompilation”来禁止后台编译,但此时执行线程就会同步等待编译完成才会执行程?/p>

  1. Client Compiler 
    C1编译器是一个简单快速的三段式编译器,主要关?#8220;局部性能优化”,放弃许多耗时较长的全局优化手段 
    过程:class -> 1. 高级中间代码 -> 2. 低级中间代码 -> 3. 机器代码
  2. Server Compiler 
    C2是专门面向服务器应用的编译器,是一个充分优化过的高级编译器,几乎能达到GNU C++编译器使?O2参数时的优化强度?/li>

使用参数“-XX:+PrintCompilation”会让虚拟机在JIT时把方法名称打印出来,如图: 
这里写图片描? style=


6. Java和C/C++的编译器对比

这里不是比Java和C/C++谁快这种大坑问题,只是比较编译器(我认为开发效率上Java快,执行效率上C/C++快)

这种对比代表了经典的即时编译器与静态编译期的对比,其实总体来说Java编译器有优有劣。主要就是动态编译时间压力大能做的优化少,还要做一些动态校验。而静态编译器无法实现一些开发上很有用的动态特?/p>

]]>Java JIT性能调优【转?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2017/06/08/432590.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Thu, 08 Jun 2017 08:48:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2017/06/08/432590.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/432590.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2017/06/08/432590.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/432590.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/432590.html</trackback:ping><description><![CDATA[from://www.tuicool.com/articles/r6Z7vaj<br /><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">JVM自动监控这所有方法的执行,如果某个方法是热点方法,JVM就计划把该方法的字节码代码编译成本地机器代码,编译成机器代码的过程是在独立线程中执行的,不会影响程序的执行,这个过程就是JIT(just in time)?/p><h2 class="yibqv">JIT针对下面的几种方式进行优?/h2><ul style="padding: 0px; margin: 0px 0px 0.75em 25px; list-style-type: none; font-size: 16px; line-height: 1.7em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;"><li style="line-height: 1.7em; list-style-type: disc;">把bytecode编译成本地代?/li><li style="line-height: 1.7em; list-style-type: disc;">单态调度(monomorphic dispatch),当个对象的类和其父类间有方法重写时,JVM调用对象的方法可以通过对象的类型路径来判断应该调用父类的方法还是子类的方法,对此JIT进行优化,这种优化是C++所不具备的,C++中需要查找虚函数表?/li><li style="line-height: 1.7em; list-style-type: disc;">循环展开(loop unrolling?/li><li style="line-height: 1.7em; list-style-type: disc;">类型锐化</li><li style="line-height: 1.7em; list-style-type: disc;">逃逸分析(escape analysis?/li><li style="line-height: 1.7em; list-style-type: disc;">移除无用代码(这个现在IDE会提示我们的,比如:intellij idea?/li><li style="line-height: 1.7em; list-style-type: disc;">Intrinsics</li><li style="line-height: 1.7em; list-style-type: disc;">分支预测</li><li style="line-height: 1.7em; list-style-type: disc;">方法内联(inlining,对性能的提升很大),默认情况,<= 35字节码的方法可以进行内联,通过这个来修改内联方法的最大值:-XX:MaxInlineSize=,通过-XX:FreqInlineSize=来设置频繁调用方法的临界?/li></ul><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">这些优化方法通常是层层依赖的,所以当JIT优化后的代码被JVM应用,就会开始尝试进行更上一层次的优化。因此我们写代码的时候,应该尽量往这些优化方式上面靠?/p><h2 class="yibqv">输出JIT编译过的方法</h2><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">在JVM启动参数中添加如下的启动参数?/p><pre less"="" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: #444444; border-radius: 4px; margin-top: 0px; margin-bottom: 0.75em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; background-color: #f6f6f6; border: none; overflow-x: auto;"><span style="color: #333333; font-weight: 700;">-XX</span>:+PrintCompilation </pre><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">输出内容类似这样?/p><pre css"="" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: #444444; border-radius: 4px; margin-top: 0px; margin-bottom: 0.75em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; background-color: #f6f6f6; border: none; overflow-x: auto;">31    23 <span style="color: #333333; font-weight: 700;">s</span>!    <span style="color: #333333; font-weight: 700;">sun</span><span style="color: #880000;">.misc</span><span style="color: #880000;">.URLClassPath</span><span style="color: #bc6060;">::getLoader</span> (136 <span style="color: #333333; font-weight: 700;">bytes</span>) </pre><ul style="padding: 0px; margin: 0px 0px 0.75em 25px; list-style-type: none; font-size: 16px; line-height: 1.7em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;"><li style="line-height: 1.7em; list-style-type: disc;">?? 31:为JVM启动后到该方法被编译相隔的时间,单位为毫?/li><li style="line-height: 1.7em; list-style-type: disc;">?? 23:编译ID,用来跟踪一个方法的编译、优化、深度优?/li><li style="line-height: 1.7em; list-style-type: disc;">?? s!:s是指该方法是synchronized,感叹号是指该方法有对异常的处理</li><li style="line-height: 1.7em; list-style-type: disc;">?? sun.misc.URLClassPath::getLoader:被编译的方?/li><li style="line-height: 1.7em; list-style-type: disc;">?? (136 bytes):方法的字节大小</li></ul><h2 class="yibqv">输出JIT编译的细节信?/h2><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">通过添加参数-XX:+PrintCompilation,可以看到的信息其实并不具体,比如:那些方法进行了内联,内联后的二进制代码是怎么样的都没有。而要输出JIT编译的细节信息,就需要在JVM启动参数中添加这个参数:</p><pre hljs="" less"="" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: #444444; border-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; background-color: #f6f6f6; border: none; overflow-x: auto;"><span style="color: #333333; font-weight: 700;">-XX</span>:+LogCompilation <span style="color: #333333; font-weight: 700;">-XX</span>:+UnlockDiagnosticVMOptions <span style="color: #333333; font-weight: 700;">-XX</span>:+TraceClassLoading <span style="color: #333333; font-weight: 700;">-XX</span>:+PrintAssembly </pre><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">输出的编译信息,默认情况是在启动JVM的目录下一个名为:hotspot_pid<PID>.log的文?/p><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">如果想指定文件路径和文件名的话,可以再添加一个启动参数:</p><pre yaml"="" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: #444444; border-radius: 4px; margin-top: 0px; margin-bottom: 0.75em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; background-color: #f6f6f6; border: none; overflow-x: auto;">-XX:LogFile=<pathto file<span style="color: #880000;">> </span></pre><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">输出的是一个很大的xml文件,可能有几百兆,内容大致如下?/p><pre hljs="" vim"="" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: #444444; border-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; background-color: #f6f6f6; border: none; overflow-x: auto;"><nmethodcompile_id=<span style="color: #880000;">'2'</span> <span style="color: #333333; font-weight: 700;">compiler</span>=<span style="color: #880000;">'C1'</span> level=<span style="color: #880000;">'3'</span> entry=<span style="color: #880000;">'0x00000001023fe240'</span> size=<span style="color: #880000;">'1224'</span> address=<span style="color: #880000;">'0x00000001023fe0d0'</span> relocation_offset=<span style="color: #880000;">'288'</span> insts_offset=<span style="color: #880000;">'368'</span> stub_offset=<span style="color: #880000;">'880'</span> scopes_data_offset=<span style="color: #880000;">'1032'</span> scopes_pcs_offset=<span style="color: #880000;">'1104'</span> dependencies_offset=<span style="color: #880000;">'1200'</span> nul_chk_table_offset=<span style="color: #880000;">'1208'</span> method=<span style="color: #880000;">'java/lang/String hashCode ()I'</span> bytes=<span style="color: #880000;">'55'</span> <span style="color: #397300;">count</span>=<span style="color: #880000;">'512'</span> backedge_count=<span style="color: #880000;">'8218'</span> iicount=<span style="color: #880000;">'512'</span> stamp=<span style="color: #880000;">'0.350'</span>/> </pre><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">而且内容很难读懂,建议使用JITWatch?nbsp;<a rel="nofollow,noindex" target="_blank" style="color: #949494; text-decoration: none; transition: 0.25s; outline: none 0px; border-bottom: 1px dashed #949494; font-style: italic; font-weight: bold;">https://github.com/AdoptOpenJDK/jitwatch/</a> )的可视化界面来查看JIT编译的细节信息。同时JITWatch还可以给出很多优化建议,给我们有效的优化代码提供参考,详见下文?/p><h2 class="yibqv">JIT编译模式</h2><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">C1: 通常用于那种快速启动的GUI应用,对应启动参数:-client</p><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">C2: 通常用于长时间允许的服务端应用,对应启动参数:-server</p><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">分层编译模式(tiered compilation):这是自从Java SE 7以后的新特性,可通过添加启动参数来开启:</p><pre less"="" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: #444444; border-radius: 4px; margin-top: 0px; margin-bottom: 0.75em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; background-color: #f6f6f6; border: none; overflow-x: auto;"><span style="color: #333333; font-weight: 700;">-XX</span>:+TieredCompilation </pre><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">这个特性在应用启动阶段使用C1模式以达到快速启动的效果,一旦应用程序运行起来以后,C2模式将取代C1模式,以进行更深度的优化。在Java SE 8中,这个特性是默认的?/p><h2 class="yibqv">JITWatch</h2><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">前面也提到了,JITWatch可以通过可视化界面来帮助我们分析JVM输出的JIT编译输出日志,还可以帮助我们静态分析jar中的代码是否符合JIT编译优化的条件,还可以以曲线图形的方式展示JIT编译的整个过程中的一些指标,非常好用的工具?/p><h3>下载</h3><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">JITWatch需要在github上把代码clone下来,然后用maven来运行,地址为: <a rel="nofollow,noindex" target="_blank" style="color: #949494; text-decoration: none; transition: 0.25s; outline: none 0px; border-bottom: 1px dashed #949494; font-style: italic; font-weight: bold;">https://github.com/AdoptOpenJDK/jitwatch/</a></p><h3>运行JITWwatch</h3><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">在代码根目录下执?nbsp;<code style="padding: 2px 4px; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; border-radius: 3px; background-color: #f7f7f9; border: none; font-weight: 600; font-size: 14px;">launchUI.sh?/code> Linux/Mac)或?nbsp;<code style="padding: 2px 4px; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; border-radius: 3px; background-color: #f7f7f9; border: none; font-weight: 600; font-size: 14px;">launchUI.bat(windows?/code></p><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">如果你使用maven,也可以在代码根目录下这样运行(其他运行方式,请参考JITWatch的github首页?/p><pre less"="" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: #444444; border-radius: 4px; margin-top: 0px; margin-bottom: 0.75em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; background-color: #f6f6f6; border: none; overflow-x: auto;"><span style="color: #333333; font-weight: 700;">mvncleancompileexec</span>:java </pre><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">如果你使用的是mac,而且idk版本是jdk7,且运行mvn clean compile exec:java时出现下面的错误和异常时?nbsp;</p><pre hljs="" css"="" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: #444444; border-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; background-color: #f6f6f6; border: none; overflow-x: auto;"><span style="color: #333333; font-weight: 700;">Causedby</span>: <span style="color: #333333; font-weight: 700;">java</span><span style="color: #880000;">.lang</span><span style="color: #880000;">.NullPointerException</span> <span style="color: #333333; font-weight: 700;">atcom</span><span style="color: #880000;">.sun</span><span style="color: #880000;">.t2k</span><span style="color: #880000;">.MacFontFinder</span><span style="color: #880000;">.initPSFontNameToPathMap</span>(<span style="color: #333333; font-weight: 700;">MacFontFinder</span><span style="color: #880000;">.java</span><span style="color: #bc6060;">:339)</span> <span style="color: #333333; font-weight: 700;">atcom</span><span style="color: #880000;">.sun</span><span style="color: #880000;">.t2k</span><span style="color: #880000;">.MacFontFinder</span><span style="color: #880000;">.getFontNamesOfFontFamily</span>(<span style="color: #333333; font-weight: 700;">MacFontFinder</span><span style="color: #880000;">.java</span><span style="color: #bc6060;">:390)</span> <span style="color: #333333; font-weight: 700;">atcom</span><span style="color: #880000;">.sun</span><span style="color: #880000;">.t2k</span><span style="color: #880000;">.T2KFontFactory</span><span style="color: #880000;">.getFontResource</span>(<span style="color: #333333; font-weight: 700;">T2KFontFactory</span><span style="color: #880000;">.java</span><span style="color: #bc6060;">:233)</span> <span style="color: #333333; font-weight: 700;">atcom</span><span style="color: #880000;">.sun</span><span style="color: #880000;">.t2k</span><span style="color: #880000;">.LogicalFont</span><span style="color: #880000;">.getSlot0Resource</span>(<span style="color: #333333; font-weight: 700;">LogicalFont</span><span style="color: #880000;">.java</span><span style="color: #bc6060;">:184)</span> <span style="color: #333333; font-weight: 700;">atcom</span><span style="color: #880000;">.sun</span><span style="color: #880000;">.t2k</span><span style="color: #880000;">.LogicalFont</span><span style="color: #880000;">.getSlotResource</span>(<span style="color: #333333; font-weight: 700;">LogicalFont</span><span style="color: #880000;">.java</span><span style="color: #bc6060;">:228)</span> <span style="color: #333333; font-weight: 700;">atcom</span><span style="color: #880000;">.sun</span><span style="color: #880000;">.t2k</span><span style="color: #880000;">.CompositeStrike</span><span style="color: #880000;">.getStrikeSlot</span>(<span style="color: #333333; font-weight: 700;">CompositeStrike</span><span style="color: #880000;">.java</span><span style="color: #bc6060;">:86)</span> <span style="color: #333333; font-weight: 700;">atcom</span><span style="color: #880000;">.sun</span><span style="color: #880000;">.t2k</span><span style="color: #880000;">.CompositeStrike</span><span style="color: #880000;">.getMetrics</span>(<span style="color: #333333; font-weight: 700;">CompositeStrike</span><span style="color: #880000;">.java</span><span style="color: #bc6060;">:132)</span> <span style="color: #333333; font-weight: 700;">atcom</span><span style="color: #880000;">.sun</span><span style="color: #880000;">.javafx</span><span style="color: #880000;">.font</span><span style="color: #880000;">.PrismFontUtils</span><span style="color: #880000;">.getFontMetrics</span>(<span style="color: #333333; font-weight: 700;">PrismFontUtils</span><span style="color: #880000;">.java</span><span style="color: #bc6060;">:31)</span> <span style="color: #333333; font-weight: 700;">atcom</span><span style="color: #880000;">.sun</span><span style="color: #880000;">.javafx</span><span style="color: #880000;">.font</span><span style="color: #880000;">.PrismFontLoader</span><span style="color: #880000;">.getFontMetrics</span>(<span style="color: #333333; font-weight: 700;">PrismFontLoader</span><span style="color: #880000;">.java</span><span style="color: #bc6060;">:466)</span> <span style="color: #333333; font-weight: 700;">atjavafx</span><span style="color: #880000;">.scene</span><span style="color: #880000;">.text</span><span style="color: #880000;">.Text</span>.<<span style="color: #333333; font-weight: 700;">init</span>>(<span style="color: #333333; font-weight: 700;">Text</span><span style="color: #880000;">.java</span><span style="color: #bc6060;">:153)</span> <span style="color: #333333; font-weight: 700;">atcom</span><span style="color: #880000;">.sun</span><span style="color: #880000;">.javafx</span><span style="color: #880000;">.scene</span><span style="color: #880000;">.control</span><span style="color: #880000;">.skin</span><span style="color: #880000;">.Utils</span>.<<span style="color: #333333; font-weight: 700;">clinit</span>>(<span style="color: #333333; font-weight: 700;">Utils</span><span style="color: #880000;">.java</span><span style="color: #bc6060;">:52)</span> ... 13 <span style="color: #333333; font-weight: 700;">more</span>   <span style="color: #bc6060;">[ERROR]</span> <span style="color: #333333; font-weight: 700;">Failedto</span> <span style="color: #333333; font-weight: 700;">executegoalorg</span><span style="color: #880000;">.codehaus</span><span style="color: #880000;">.mojo</span><span style="color: #bc6060;">:exec-maven-plugin</span><span style="color: #bc6060;">:1.5.0</span><span style="color: #bc6060;">:java</span> (<span style="color: #333333; font-weight: 700;">default-cli</span>) <span style="color: #333333; font-weight: 700;">onprojectjitwatch-ui</span>: <span style="color: #333333; font-weight: 700;">Anexceptionoccuredwhile</span> <span style="color: #333333; font-weight: 700;">executingtheJavaclass</span>. <span style="color: #333333; font-weight: 700;">null</span>: <span style="color: #333333; font-weight: 700;">InvocationTargetException</span>: <span style="color: #333333; font-weight: 700;">Exceptionin</span> <span style="color: #333333; font-weight: 700;">Applicationstartmethod</span>: <span style="color: #333333; font-weight: 700;">ExceptionInInitializerError</span>: <span style="color: #333333; font-weight: 700;">NullPointerException</span> <span style="color: #333333; font-weight: 700;">-</span>> <span style="color: #bc6060;">[Help 1]</span> </pre><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">请在org.adoptopenjdk.jitwatch.launch.LaunchUI类的main函数开头处添加下面的代码(或者直接使用我fork修改好的 <a target="_blank" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; outline: none 0px; border-bottom: 1px dashed #949494; font-style: italic; font-weight: bold;">JITWatch</a> ):</p><pre hljs="" dart"="" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: #444444; border-radius: 4px; margin-top: 0px; margin-bottom: 1.5em; line-height: 1.5em; word-break: break-all; word-wrap: break-word; background-color: #f6f6f6; border: none; overflow-x: auto;"><span style="color: #333333; font-weight: 700;">final</span> Class<?> macFontFinderClass = Class.forName(<span style="color: #880000;">"com.sun.t2k.MacFontFinder"</span>); <span style="color: #333333; font-weight: 700;">final</span> java.lang.reflect.FieldpsNameToPathMap = macFontFinderClass.getDeclaredField(<span style="color: #880000;">"psNameToPathMap"</span>); psNameToPathMap.setAccessible(<span style="color: #333333; font-weight: 700;">true</span>); <span style="color: #333333; font-weight: 700;">if</span> (psNameToPathMap.<span style="color: #333333; font-weight: 700;">get</span>(<span style="color: #333333; font-weight: 700;">null</span>) == <span style="color: #333333; font-weight: 700;">null</span>) {     psNameToPathMap.<span style="color: #333333; font-weight: 700;">set</span>(         <span style="color: #333333; font-weight: 700;">null</span>, <span style="color: #333333; font-weight: 700;">new</span> java.util.HashMap<<span style="color: #397300;">String</span>, <span style="color: #397300;">String</span>>()); } <span style="color: #333333; font-weight: 700;">final</span> java.lang.reflect.FieldallAvailableFontFamilies = macFontFinderClass.getDeclaredField(<span style="color: #880000;">"allAvailableFontFamilies"</span>); allAvailableFontFamilies.setAccessible(<span style="color: #333333; font-weight: 700;">true</span>); <span style="color: #333333; font-weight: 700;">if</span> (allAvailableFontFamilies.<span style="color: #333333; font-weight: 700;">get</span>(<span style="color: #333333; font-weight: 700;">null</span>) == <span style="color: #333333; font-weight: 700;">null</span>) {     allAvailableFontFamilies.<span style="color: #333333; font-weight: 700;">set</span>(         <span style="color: #333333; font-weight: 700;">null</span>, <span style="color: #333333; font-weight: 700;">new</span> <span style="color: #397300;">String</span>[] {}); } </pre><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;">然后重新运行即可看到JITWatch的界面?/p><h2 class="yibqv"><strong class="yibqv">Reference</strong></h2><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;"><a target="_blank" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; outline: none 0px; border-bottom: 1px dashed #949494; font-style: italic; font-weight: bold;">//www.oracle.com/technetwork/articles/java/architect-evans-pt1-2266278.html</a></p><p style="margin: 0px 0px 0.75em; font-size: 16px; line-height: 1.7em; text-indent: 1em; color: #333333; font-family: "Helvetica Neue", Helvetica, Tahoma, Arial, STXihei, "Microsoft YaHei", 微软雅黑, sans-serif; background-color: #fefefe;"><a target="_blank" rel="nofollow,noindex" style="color: #949494; text-decoration: none; transition: 0.25s; outline: none 0px; outline-offset: -2px; border-bottom: 1px dashed #949494; font-style: italic; font-weight: bold;">https://www.chrisnewland.com/images/jitwatch/HotSpot_Profiling_Using_JITWatch.pdf</a></p><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/432590.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2017-06-08 16:48 <a href="//www.ot7t.com.cn/xiaomage234/archive/2017/06/08/432590.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何线程安全的使?HashMap【转?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2017/06/02/432572.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Fri, 02 Jun 2017 09:57:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2017/06/02/432572.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/432572.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2017/06/02/432572.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/432572.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/432572.html</trackback:ping><description><![CDATA[     摘要: from://yemengying.com/2016/05/07/threadsafe-hashmap/ 2016-05-07 JAVAHASHMAP HASHMAP, JAVA文章目录1. 为什么HashMap是线程不安全?.1. HashMap的内部存储结?.2. HashMap的自动扩容机?.3. ...  <a href='//www.ot7t.com.cn/xiaomage234/archive/2017/06/02/432572.html'>阅读全文</a><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/432572.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2017-06-02 17:57 <a href="//www.ot7t.com.cn/xiaomage234/archive/2017/06/02/432572.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 8系列之重新认识HashMap - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/archive/2017/06/02/432571.html小马?/dc:creator>小马?/author>Fri, 02 Jun 2017 09:56:00 GMT//www.ot7t.com.cn/xiaomage234/archive/2017/06/02/432571.html//www.ot7t.com.cn/xiaomage234/comments/432571.html//www.ot7t.com.cn/xiaomage234/archive/2017/06/02/432571.html#Feedback0//www.ot7t.com.cn/xiaomage234/comments/commentRss/432571.html//www.ot7t.com.cn/xiaomage234/services/trackbacks/432571.html

摘要

HashMap是Java程序员使用频率最高的用于映射(键值对)处理的数据类型。随着JDK(Java Developmet Kit)版本的更新,JDK1.8对HashMap底层的实现进行了优化,例如引入红黑树的数据结构和扩容的优化等。本文结合JDK1.7和JDK1.8的区别,深入探讨HashMap的结构实现和功能原理?br style="padding: 0px; margin: 0px;" />

简?/strong>

Java为数据结构中的映射定义了一个接口java.util.Map,此接口主要有四个常用的实现类,分别是HashMap、Hashtable、LinkedHashMap和TreeMap,类继承关系如下图所示:

java.util.map类图

下面针对各个实现类的特点做一些说明:

(1) HashMap:它根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的?HashMap最多只允许一条记录的键为null,允许多条记录的值为null。HashMap非线程安全,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致。如果需要满足线程安全,可以?Collections的synchronizedMap方法使HashMap具有线程安全的能力,或者使用ConcurrentHashMap?/p>

(2) Hashtable:Hashtable是遗留类,很多映射的常用功能与HashMap类似,不同的是它承自Dictionary类,并且是线程安全的,任一时间只有一个线程能写Hashtable,并发性不如ConcurrentHashMap,因为ConcurrentHashMap引入了分段锁。Hashtable不建议在新代码中使用,不需要线程安全的场合可以用HashMap替换,需要线程安全的场合可以用ConcurrentHashMap替换?/p>

(3) LinkedHashMap:LinkedHashMap是HashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的,也可以在构造时带参数,按照访问次序排序?/p>

(4) TreeMap:TreeMap实现SortedMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。如果使用排序的映射,建议使用TreeMap。在使用TreeMap时,key必须实现Comparable接口或者在构造TreeMap传入自定义的Comparator,否则会在运行时抛出java.lang.ClassCastException类型的异常?/p>

对于上述四种Map类型的类,要求映射中的key是不可变对象。不可变对象是该对象在创建后它的哈希值不会被改变。如果对象的哈希值发生变化,Map对象很可能就定位不到映射的位置了?/p>

通过上面的比较,我们知道了HashMap是Java的Map家族中一个普通成员,鉴于它可以满足大多数场景的使用条件,所以是使用频度最高的一个。下文我们主要结合源码,从存储结构、常用方法分析、扩容以及安全性等方面深入讲解HashMap的工作原理?/p>

内部实现

搞清楚HashMap,首先需要知道HashMap是什么,即它的存储结?字段;其次弄明白它能干什么,即它的功能实?方法。下面我们针对这两个方面详细展开讲解?/p>

存储结构-字段

从结构实现来讲,HashMap是数?链表+红黑树(JDK1.8增加了红黑树部分)实现的,如下如所示?/p>

hashMap内存结构? heigth=

这里需要讲明白两个问题:数据底层具体存储的是什么?这样的存储方式有什?优点呢?

(1) 从源码可知,HashMap类中有一个非常重要的字段,就?Node[] table,即哈希桶数组,明显它是一个Node的数组。我们来看Node[JDK1.8]是何物?/k,v>

static class Node<K,V> implements Map.Entry<K,V> {         final int hash;    //用来定位数组索引位置         final K key;         V value;         Node<K,V> next;   //链表的下一个node          Node(int hash, K key, V value, Node<K,V> next) { ... }         public final K getKey(){ ... }         public final V getValue() { ... }         public final String toString() { ... }         public final int hashCode() { ... }         public final V setValue(V newValue) { ... }         public final boolean equals(Object o) { ... } } 

Node是HashMap的一个内部类,实现了Map.Entry接口,本质是就是一个映?键值对)。上图中的每个黑色圆点就是一个Node对象?/p>

(2) HashMap就是使用哈希表来存储的。哈希表为解决冲突,可以采用开放地址法和链地址法等来解决问题,Java中HashMap采用了链地址法。链地址法,简单来说,就是数组加链表的结合。在每个数组元素上都一个链表结构,当数据被Hash后,得到数组下标,把数据放在对应下标元素的链表上。例如程序执行下面代码:

    map.put("美团","小美"); 

系统将调?美团"这个key的hashCode()方法得到其hashCode 值(该方法适用于每个Java对象),然后再通过Hash算法的后两步运算(高位运算和取模运算,下文有介绍)来定位该键值对的存储位置,有时两个key会定位到相同的位置,表示发生了Hash碰撞。当然Hash算法计算结果越分散均匀,Hash碰撞的概率就越小,map的存取效率就会越高?/p>

如果哈希桶数组很大,即使较差的Hash算法也会比较分散,如果哈希桶数组数组很小,即使好的Hash算法也会出现较多碰撞,所以就需要在空间成本和时间成本之间权衡,其实就是在根据实际情况确定哈希桶数组的大小,并在此基础上设计好的hash算法减少Hash碰撞。那么通过什么方式来控制map使得Hash碰撞的概率又小,哈希桶数组(Node[] table)占用空间又少呢?答案就是好的Hash算法和扩容机制?/k,v>

在理解Hash和扩容流程之前,我们得先了解下HashMap的几个字段。从HashMap的默认构造函数源码可知,构造函数就是对下面几个字段进行初始化,源码如下?/p>

     int threshold;             // 所能容纳的key-value对极?      final float loadFactor;    // 负载因子      int modCount;        int size; 

首先,Node[] table的初始化长度length(默认值是16),Load factor为负载因?默认值是0.75),threshold是HashMap所能容纳的最大数据量的Node(键值对)个数。threshold = length * Load factor。也就是说,在数组定义好长度之后,负载因子越大,所能容纳的键值对个数越多?/k,v>

结合负载因子的定义公式可知,threshold就是在此Load factor和length(数组长度)对应下允许的最大元素数目,超过这个数目就重新resize(扩容),扩容后的HashMap容量是之前容量的两倍。默认的负载因子0.75是对空间和时间效率的一个平衡选择,建议大家不要修改,除非在时间和空间比较特殊的情况下,如果内存空间很多而又对时间效率要求很高,可以降低负载因子Load factor的值;相反,如果内存空间紧张而对时间效率要求不高,可以增加负载因子loadFactor的值,这个值可以大??/p>

size这个字段其实很好理解,就是HashMap中实际存在的键值对数量。注意和table的长度length、容纳最大键值对数量threshold的区别。而modCount字段主要用来记录HashMap内部结构发生变化的次数,主要用于迭代的快速失败。强调一点,内部结构发生变化指的是结构发生变化,例如put新键值对,但是某个key对应的value值被覆盖不属于结构变化?/p>

在HashMap中,哈希桶数组table的长度length大小必须?的n次方(一定是合数),这是一种非常规的设计,常规的设计是把桶的大小设计为素数。相对来说素数导致冲突的概率要小于合数,具体证明可以参?a style="padding: 0px; margin: 0px; text-decoration: none; color: #32d3c3;">//blog.csdn.net/liuqiyao_01/article/details/14475159,Hashtable初始化桶大小?1,就是桶大小设计为素数的应用(Hashtable扩容后不能保证还是素数)。HashMap采用这种非常规设计,主要是为了在取模和扩容时做优化,同时为了减少冲突,HashMap定位哈希桶索引位置时,也加入了高位参与运算的过程?/p>

这里存在一个问题,即使负载因子和Hash算法设计的再合理,也免不了会出现拉链过长的情况,一旦出现拉链过长,则会严重影响HashMap的性能。于是,在JDK1.8版本中,对数据结构做了进一步的优化,引入了红黑树。而当链表长度太长(默认超?)时,链表就转换为红黑树,利用红黑树快速增删改查的特点提高HashMap的性能,其中会用到红黑树的插入、删除、查找等算法。本文不再对红黑树展开讨论,想了解更多红黑树数据结构的工作原理可以参?a style="padding: 0px; margin: 0px; text-decoration: none; color: #32d3c3;">//blog.csdn.net/v_july_v/article/details/6105630?/p>

功能实现-方法

HashMap的内部功能实现很多,本文主要从根据key获取哈希桶数组索引位置、put方法的详细执行、扩容过程三个具有代表性的点深入展开讲解?/p>

1. 确定哈希桶数组索引位?/h3>

不管增加、删除、查找键值对,定位到哈希桶数组的位置都是很关键的第一步。前面说过HashMap的数据结构是数组和链表的结合,所以我们当然希望这个HashMap里面的元素位置尽量分布均匀些,尽量使得每个位置上的元素数量只有一个,那么当我们用hash算法求得这个位置的时候,马上就可以知道对应位置的元素就是我们要的,不用遍历链表,大大优化了查询的效率。HashMap定位数组索引位置,直接决定了hash方法的离散性能。先看看源码的实?方法一+方法?:

方法一?static final int hash(Object key) {   //jdk1.8 & jdk1.7      int h;      // h = key.hashCode() 为第一?取hashCode?     // h ^ (h >>> 16)  为第二步 高位参与运算      return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } 方法二: static int indexFor(int h, int length) {  //jdk1.7的源码,jdk1.8没有这个方法,但是实现原理一样的      return h & (length-1);  //第三?取模运算 } 

这里的Hash算法本质上就是三步:取key的hashCode值、高位运算、取模运?/strong>?/p>

对于任意给定的对象,只要它的hashCode()返回值相同,那么程序调用方法一所计算得到的Hash码值总是相同的。我们首先想到的就是把hash值对数组长度取模运算,这样一来,元素的分布相对来说是比较均匀的。但是,模运算的消耗还是比较大的,在HashMap中是这样做的:调用方法二来计算该对象应该保存在table数组的哪个索引处?/p>

这个方法非常巧妙,它通过h & (table.length -1)来得到该对象的保存位,而HashMap底层数组的长度总是2的n次方,这是HashMap在速度上的优化。当length总是2的n次方时,h& (length-1)运算等价于对length取模,也就是h%length,但?amp;?具有更高的效率?/p>

在JDK1.8的实现中,优化了高位运算的算法,通过hashCode()的高16位异或低16位实现的?h = k.hashCode()) ^ (h >>> 16),主要是从速度、功效、质量来考虑的,这么做可以在数组table的length比较小的时候,也能保证考虑到高低Bit都参与到Hash的计算中,同时不会有太大的开销?/p>

下面举例说明下,n为table的长度?/p>

hashMap哈希算法例图

2. 分析HashMap的put方法

HashMap的put方法执行过程可以通过下图来理解,自己有兴?可以去对比源码更清楚地研究学习?/p>

hashMap put方法执行流程? heigth=

①.判断键值对数组table[i]是否为空或为null,否则执行resize()进行扩容?/p>

②.根据键值key计算hash值得到插入的数组索引i,如果table[i]==null,直接新建节点添加,转向⑥,如果table[i]不为空,转向③?/p>

③.判断table[i]的首个元素是否和key一样,如果相同直接覆盖value,否则转?#9315;,这里的相同指的是hashCode以及equals?/p>

④.判断table[i] 是否为treeNode,即table[i] 是否是红黑树,如果是红黑树,则直接在树中插入键值对,否则转?#9316;?/p>

⑤.遍历table[i],判断链表长度是否大?,大?的话把链表转换为红黑树,在红黑树中执行插入操作,否则进行链表的插入操作;遍历过程中若发现key已经存在直接覆盖value即可?/p>

⑥.插入成功后,判断实际存在的键值对数量size是否超多了最大容量threshold,如果超过,进行扩容?/p>

JDK1.8HashMap的put方法源码如下:

 1 public V put(K key, V value) {  2     // 对key的hashCode()做hash  3     return putVal(hash(key), key, value, false, true);  4 }  5   6 final V putVal(int hash, K key, V value, boolean onlyIfAbsent,  7                boolean evict) {  8     Node<K,V>[] tab; Node<K,V> p; int n, i;  9     // 步骤①:tab为空则创?10     if ((tab = table) == null || (n = tab.length) == 0) 11         n = (tab = resize()).length; 12     // 步骤②:计算index,并对null做处? 13     if ((p = tab[i = (n - 1) & hash]) == null)  14         tab[i] = newNode(hash, key, value, null); 15     else { 16         Node<K,V> e; K k; 17         // 步骤③:节点key存在,直接覆盖value 18         if (p.hash == hash && 19             ((k = p.key) == key || (key != null && key.equals(k)))) 20             e = p; 21         // 步骤④:判断该链为红黑?22         else if (p instanceof TreeNode) 23             e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); 24         // 步骤⑤:该链为链表 25         else { 26             for (int binCount = 0; ; ++binCount) { 27                 if ((e = p.next) == null) { 28                     p.next = newNode(hash, key,value,null);                         //链表长度大于8转换为红黑树进行处理 29                     if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st   30                         treeifyBin(tab, hash); 31                     break; 32                 }                     // key已经存在直接覆盖value 33                 if (e.hash == hash && 34                     ((k = e.key) == key || (key != null && key.equals(k))))  35                            break; 36                 p = e; 37             } 38         } 39          40         if (e != null) { // existing mapping for key 41             V oldValue = e.value; 42             if (!onlyIfAbsent || oldValue == null) 43                 e.value = value; 44             afterNodeAccess(e); 45             return oldValue; 46         } 47     }  48     ++modCount; 49     // 步骤⑥:超过最大容?就扩?50     if (++size > threshold) 51         resize(); 52     afterNodeInsertion(evict); 53     return null; 54 } 

3. 扩容机制

扩容(resize)就是重新计算容量,向HashMap对象里不停的添加元素,而HashMap对象内部的数组无法装载更多的元素时,对象就需要扩大数组的长度,以便能装入更多的元素。当然Java里的数组是无法自动扩容的,方法是使用一个新的数组代替已有的容量小的数组,就像我们用一个小桶装水,如果想装更多的水,就得换大水桶?/p>

我们分析下resize的源码,鉴于JDK1.8融入了红黑树,较复杂,为了便于理解我们仍然使用JDK1.7的代码,好理解一些,本质上区别不大,具体区别后文再说?/p>

 1 void resize(int newCapacity) {   //传入新的容量  2     Entry[] oldTable = table;    //引用扩容前的Entry数组  3     int oldCapacity = oldTable.length;           4     if (oldCapacity == MAXIMUM_CAPACITY) {  //扩容前的数组大小如果已经达到最?2^30)? 5         threshold = Integer.MAX_VALUE; //修改阈值为int的最大?2^31-1),这样以后就不会扩容? 6         return;  7     }  8    9     Entry[] newTable = new Entry[newCapacity];  //初始化一个新的Entry数组 10     transfer(newTable);                         //!!将数据转移到新的Entry数组?11     table = newTable;                           //HashMap的table属性引用新的Entry数组 12     threshold = (int)(newCapacity * loadFactor);//修改阈?13 } 

这里就是使用一个容量更大的数组来代替已有的容量小的数组,transfer()方法将原有Entry数组的元素拷贝到新的Entry数组里?/p>

 1 void transfer(Entry[] newTable) {  2     Entry[] src = table;                   //src引用了旧的Entry数组  3     int newCapacity = newTable.length;  4     for (int j = 0; j < src.length; j++) { //遍历旧的Entry数组  5         Entry<K,V> e = src[j];             //取得旧Entry数组的每个元? 6         if (e != null) {  7             src[j] = null;//释放旧Entry数组的对象引用(for循环后,旧的Entry数组不再引用任何对象? 8             do {  9                 Entry<K,V> next = e.next; 10                 int i = indexFor(e.hash, newCapacity); //!!重新计算每个元素在数组中的位?11                 e.next = newTable[i]; //标记[1] 12                 newTable[i] = e;      //将元素放在数组上 13                 e = next;             //访问下一个Entry链上的元?14             } while (e != null); 15         } 16     } 17 } 

newTable[i]的引用赋给了e.next,也就是使用了单链表的头插入方式,同一位置上新元素总会被放在链表的头部位置;这样先放在一个索引上的元素终会被放到Entry链的尾部(如果发生了hash冲突的话),这一点和Jdk1.8有区别,下文详解。在旧数组中同一条Entry链上的元素,通过重新计算索引位置后,有可能被放到了新数组的不同位置上?/p>

下面举个例子说明下扩容过程。假设了我们的hash算法就是简单的用key mod 一下表的大小(也就是数组的长度)。其中的哈希桶数组table的size=2?所以key = 3??,put顺序依次?5??。在mod 2以后都冲突在table[1]这里了。这里假设负载因?loadFactor=1,即当键值对的实际大小size 大于 table的实际大小时进行扩容。接下来的三个步骤是哈希桶数?resize?,然后所有的Node重新rehash的过程?/p>

jdk1.7扩容例图

下面我们讲解下JDK1.8做了哪些优化。经过观测可以发现,我们使用的是2次幂的扩?指长度扩为原??,所以,元素的位置要么是在原位置,要么是在原位置再移?次幂的位置。看下图可以明白这句话的意思,n为table的长度,图(a)表示扩容前的key1和key2两种key确定索引位置的示例,图(b)表示扩容后key1和key2两种key确定索引位置的示例,其中hash1是key1对应的哈希与高位运算结果?/p>

hashMap 1.8 哈希算法例图1

元素在重新计算hash之后,因为n变为2倍,那么n-1的mask范围在高位多1bit(红色),因此新的index就会发生这样的变化:

hashMap 1.8 哈希算法例图2

因此,我们在扩充HashMap的时候,不需要像JDK1.7的实现那样重新计算hash,只需要看看原来的hash值新增的那个bit?还是0就好了,?的话索引没变,是1的话索引变成“原索?oldCap”,可以看看下图为16扩充?2的resize示意图:

jdk1.8 hashMap扩容例图

这个设计确实非常的巧妙,既省去了重新计算hash值的时间,而且同时,由于新增的1bit?还是1可以认为是随机的,因此resize的过程,均匀的把之前的冲突的节点分散到新的bucket了。这一块就是JDK1.8新增的优化点。有一点注意区别,JDK1.7中rehash的时候,旧链表迁移新链表的时候,如果在新表的数组索引位置相同,则链表元素会倒置,但是从上图可以看出,JDK1.8不会倒置。有兴趣的同学可以研究下JDK1.8的resize源码,写的很赞,如下:

 1 final Node<K,V>[] resize() {  2     Node<K,V>[] oldTab = table;  3     int oldCap = (oldTab == null) ? 0 : oldTab.length;  4     int oldThr = threshold;  5     int newCap, newThr = 0;  6     if (oldCap > 0) {  7         // 超过最大值就不再扩充了,就只好随你碰撞去? 8         if (oldCap >= MAXIMUM_CAPACITY) {  9             threshold = Integer.MAX_VALUE; 10             return oldTab; 11         } 12         // 没超过最大值,就扩充为原来??13         else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && 14                  oldCap >= DEFAULT_INITIAL_CAPACITY) 15             newThr = oldThr << 1; // double threshold 16     } 17     else if (oldThr > 0) // initial capacity was placed in threshold 18         newCap = oldThr; 19     else {               // zero initial threshold signifies using defaults 20         newCap = DEFAULT_INITIAL_CAPACITY; 21         newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY); 22     } 23     // 计算新的resize上限 24     if (newThr == 0) { 25  26         float ft = (float)newCap * loadFactor; 27         newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ? 28                   (int)ft : Integer.MAX_VALUE); 29     } 30     threshold = newThr; 31     @SuppressWarnings({"rawtypes"?unchecked"}) 32         Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap]; 33     table = newTab; 34     if (oldTab != null) { 35         // 把每个bucket都移动到新的buckets?36         for (int j = 0; j < oldCap; ++j) { 37             Node<K,V> e; 38             if ((e = oldTab[j]) != null) { 39                 oldTab[j] = null; 40                 if (e.next == null) 41                     newTab[e.hash & (newCap - 1)] = e; 42                 else if (e instanceof TreeNode) 43                     ((TreeNode<K,V>)e).split(this, newTab, j, oldCap); 44                 else { // 链表优化重hash的代码块 45                     Node<K,V> loHead = null, loTail = null; 46                     Node<K,V> hiHead = null, hiTail = null; 47                     Node<K,V> next; 48                     do { 49                         next = e.next; 50                         // 原索?51                         if ((e.hash & oldCap) == 0) { 52                             if (loTail == null) 53                                 loHead = e; 54                             else 55                                 loTail.next = e; 56                             loTail = e; 57                         } 58                         // 原索?oldCap 59                         else { 60                             if (hiTail == null) 61                                 hiHead = e; 62                             else 63                                 hiTail.next = e; 64                             hiTail = e; 65                         } 66                     } while ((e = next) != null); 67                     // 原索引放到bucket?68                     if (loTail != null) { 69                         loTail.next = null; 70                         newTab[j] = loHead; 71                     } 72                     // 原索?oldCap放到bucket?73                     if (hiTail != null) { 74                         hiTail.next = null; 75                         newTab[j + oldCap] = hiHead; 76                     } 77                 } 78             } 79         } 80     } 81     return newTab; 82 } 

线程安全?/strong>

在多线程使用场景中,应该尽量避免使用线程不安全的HashMap,而使用线程安全的ConcurrentHashMap。那么为什么说HashMap是线程不安全的,下面举例子说明在并发的多线程使用场景中使用HashMap可能造成死循环。代码例子如?便于理解,仍然使用JDK1.7的环??/p>

public class HashMapInfiniteLoop {        private static HashMap<Integer,String> map = new HashMap<Integer,String>(2?.75f);       public static void main(String[] args) {           map.put(5?"C");            new Thread("Thread1") {               public void run() {                   map.put(7, "B");                   System.out.println(map);               };           }.start();           new Thread("Thread2") {               public void run() {                   map.put(3, "A);                   System.out.println(map);               };           }.start();             }   } 

其中,map初始化为一个长度为2的数组,loadFactor=0.75,threshold=2*0.75=1,也就是说当put第二个key的时候,map就需要进行resize?/p>

通过设置断点让线?和线?同时debug到transfer方法(3.3小节代码?的首行。注意此时两个线程已经成功添加数据。放开thread1的断点至transfer方法?#8220;Entry next = e.next;” 这一行;然后放开线程2的的断点,让线程2进行resize。结果如下图?/k,v>

jdk1.7 hashMap死循环例?

注意,Thread1?e 指向了key(3),而next指向了key(7),其在线程二rehash后,指向了线程二重组后的链表?/p>

线程一被调度回来执行,先是执行 newTalbe[i] = e?然后是e = next,导致了e指向了key(7),而下一次循环的next = e.next导致了next指向了key(3)?/p>

jdk1.7 hashMap死循环例?

jdk1.7 hashMap死循环例?

e.next = newTable[i] 导致 key(3).next 指向?key(7)。注意:此时的key(7).next 已经指向了key(3)?环形链表就这样出现了?/p>

jdk1.7 hashMap死循环例?

于是,当我们用线程一调用map.get(11)时,悲剧就出现了——Infinite Loop?/p>

JDK1.8与JDK1.7的性能对比

HashMap中,如果key经过hash算法得出的数组索引位置全部不相同,即Hash算法非常好,那样的话,getKey方法的时间复杂度就是O(1),如果Hash算法技术的结果碰撞非常多,假如Hash算极其差,所有的Hash算法结果得出的索引位置一样,那样所有的键值对都集中到一个桶中,或者在一个链表中,或者在一个红黑树中,时间复杂度分别为O(n)和O(lgn)?鉴于JDK1.8做了多方面的优化,总体性能优于JDK1.7,下面我们从两个方面用例子证明这一点?/p>

Hash较均匀的情?/h2>

为了便于测试,我们先写一个类Key,如下:

class Key implements Comparable<Key> {      private final int value;      Key(int value) {         this.value = value;     }      @Override     public int compareTo(Key o) {         return Integer.compare(this.value, o.value);     }      @Override     public boolean equals(Object o) {         if (this == o) return true;         if (o == null || getClass() != o.getClass())             return false;         Key key = (Key) o;         return value == key.value;     }      @Override     public int hashCode() {         return value;     } } 

这个类复写了equals方法,并且提供了相当好的hashCode函数,任何一个值的hashCode都不会相同,因为直接使用value当做hashcode。为了避免频繁的GC,我将不变的Key实例缓存了起来,而不是一遍一遍的创建它们。代码如下:

public class Keys {      public static final int MAX_KEY = 10_000_000;     private static final Key[] KEYS_CACHE = new Key[MAX_KEY];      static {         for (int i = 0; i < MAX_KEY; ++i) {             KEYS_CACHE[i] = new Key(i);         }     }      public static Key of(int value) {         return KEYS_CACHE[value];     } } 

现在开始我们的试验,测试需要做的仅仅是,创建不同size的HashMap??0?00?.....10000000),屏蔽了扩容的情况,代码如下:

   static void test(int mapSize) {          HashMap<Key, Integer> map = new HashMap<Key,Integer>(mapSize);         for (int i = 0; i < mapSize; ++i) {             map.put(Keys.of(i), i);         }          long beginTime = System.nanoTime(); //获取纳秒         for (int i = 0; i < mapSize; i++) {             map.get(Keys.of(i));         }         long endTime = System.nanoTime();         System.out.println(endTime - beginTime);     }      public static void main(String[] args) {         for(int i=10;i<= 1000 0000;i*= 10){             test(i);         }     } 

在测试中会查找不同的值,然后度量花费的时间,为了计算getKey的平均时间,我们遍历所有的get方法,计算总的时间,除以key的数量,计算一个平均值,主要用来比较,绝对值可能会受很多环境因素的影响。结果如下:

性能比较?.png

通过观测测试结果可知,JDK1.8的性能要高于JDK1.7 15%以上,在某些size的区域上,甚至高?00%。由于Hash算法较均匀,JDK1.8引入的红黑树效果不明显,下面我们看看Hash不均匀的的情况?/p>

Hash极不均匀的情?/h2>

假设我们又一个非常差的Key,它们所有的实例都返回相同的hashCode值。这是使用HashMap最坏的情况。代码修改如下:

class Key implements Comparable<Key> {      //...      @Override     public int hashCode() {         return 1;     } } 

仍然执行main方法,得出的结果如下表所示:

性能比较?.png

从表中结果中可知,随着size的变大,JDK1.7的花费时间是增长的趋势,而JDK1.8是明显的降低趋势,并且呈现对数增长稳定。当一?链表太长的时候,HashMap会动态的将它替换成一个红黑树,这?的话会将时间复杂度从O(n)降为O(logn)。hash算法均匀和不均匀所花费的时间明显也不相同,这两种情况的相对比较,可以说明一个好的hash算法的重要性?/p>      测试环境:处理器?.2 GHz Intel Core i7,内存为16 GB 1600 MHz DDR3,SSD硬盘,使用默认的JVM参数,运行在64位的OS X 10.10.1上?h1>小结

(1) 扩容是一个特别耗性能的操作,所以当程序员在使用HashMap的时候,估算map的大小,初始化的时候给一个大致的数值,避免map进行频繁的扩容?/p>

(2) 负载因子是可以修改的,也可以大于1,但是建议不要轻易修改,除非情况非常特殊?/p>

(3) HashMap是线程不安全的,不要在并发的环境中同时操作HashMap,建议使用ConcurrentHashMap?/p>

(4) JDK1.8引入红黑树大程度优化了HashMap的性能?/p>

(5) 还没升级JDK1.8的,现在开始升级吧。HashMap的性能提升仅仅是JDK1.8的冰山一角?/p>

参?/strong>

  1. JDK1.7&JDK1.8 源码?/li>
  2. CSDN博客频道?a style="padding: 0px; margin: 0px; text-decoration: none; color: #32d3c3;">HashMap多线程死循环问题?014?/li>
  3. 红黑联盟?a style="padding: 0px; margin: 0px; text-decoration: none; color: #32d3c3;">Java类集框架之HashMap(JDK1.8)源码剖析?015?/li>
  4. CSDN博客频道?a style="padding: 0px; margin: 0px; text-decoration: none; color: #32d3c3;"> 教你初步了解红黑?/a>?010?/li>
  5. Java Code Geeks?a style="padding: 0px; margin: 0px; text-decoration: none; color: #32d3c3;">HashMap performance improvements in Java 8?014?/li>
  6. Importnew?a style="padding: 0px; margin: 0px; text-decoration: none; color: #32d3c3;">危险!在HashMap中将可变对象用作Key?014?/li>
  7. CSDN博客频道?a style="padding: 0px; margin: 0px; text-decoration: none; color: #32d3c3;">为什么一般hashtable的桶数会取一个素?/a>?013?/li>




]]>一步步优化JVM五:优化延迟或者响应时?2) - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/archive/2016/10/18/431903.html小马?/dc:creator>小马?/author>Tue, 18 Oct 2016 12:24:00 GMT//www.ot7t.com.cn/xiaomage234/archive/2016/10/18/431903.html//www.ot7t.com.cn/xiaomage234/comments/431903.html//www.ot7t.com.cn/xiaomage234/archive/2016/10/18/431903.html#Feedback0//www.ot7t.com.cn/xiaomage234/comments/commentRss/431903.html//www.ot7t.com.cn/xiaomage234/services/trackbacks/431903.html优化CMS(concurrent garbage collection?/strong>
   使用CMS,old代的垃圾回收执行线程会和应用程序的线程最大程度的并发执行。这个提供了一个机会来减少最坏延迟的频率和最坏延迟的时间消耗。CMS没有执行压缩,所以可以避免old代空间的stop-the-world压缩(会让整个应用暂停运行)?/span>

   优化CMS的目标就是避开stop-the-world压缩垃圾回收,然而,这个说比做起来容易。在一些的部署情况下,这个是不可避免的,尤其是当内存分配受限的时候?/span>

   在一些特殊的情况下,CMS比其他类型的垃圾回收需要更多优化,更需要优化young代的空间,以及潜在的优化该什么时候初始化old代的垃圾回收循环?/span>

   当从吞吐量垃圾回收器(Throughput)迁移到CMS的时候,有可能会获得更慢的MinorGC,由于对象从young代转移到old会更?,由于CMS在old代里面分配的内存是一个不连续的列表,相反,吞吐量垃圾回收器只是在本地线程的分配缓?/span>里面指定一个指针。另外,由于old代的垃圾回收线程和应用的线程是尽可能的并发运行的,所以吞吐量会更小一些。然而,最坏的延迟的频率会少很多,由于在old代的不可获取的对象能够在应用运行的过程被垃圾回收,这样可以避免old代的空间溢出?/span>

   使用CMS,如果old代能够使用的空间有限,单线程的stop-the-world压缩垃圾回收会执行。这种情况下,FullGC的时间会比吞吐量垃圾回收器的FullGC时间还要长,导致的结果是,CMS的绝对最差延迟会比吞吐量垃圾回收器的最差延迟严重很多。old代的空间溢出以及运行了stop-the-world垃圾回收必须被应用负责人重视,由于在响应上会有更长的中断。因此,不要让old代运行得溢出就非常重要了。对于从吞吐量垃圾回收器迁移到CMS的一个比较重要的建议就是提升old?0%?0%的容量?/span>

   在优化CMS的时候有几个注意点,首先,对象从young代转移到old代的转移率。其次,CMS重新分配内存的概率。再次,CMS回收对象时候产生的old代的分隔,这个会在可获得的对象中间产生一些空隙,从而导致了分隔空间?/span>

   碎片可以被下面的几种方法寻址。第一办法是压缩old代,压缩old代空间是通过stop-the-world垃圾回收压缩完成的,就像前面所说的那样,stop-the-world垃圾回收会执行很长时间,会严重影响应用的响应时间,应该避开。第二种办法是,对碎片编址,提高old代的空间,这个办法不能完全解决碎片的问题的,但是可以延迟old代压缩的时间。通常来讲,old代越多内存,由于碎片导致需要执行的压缩的时间久越长。努力把old的空间增大的目标是在应用的生命周期中,避免堆碎片导致stop-the-world压缩垃圾回收,换句话说,应用GC最大内存原则。另外一种处理碎片的办法是减少对象从young代移动到old的概率,就是减少MinorGC,应用MinorGC回收原则?/span>

   任期阀值(tenuring threshold)控制了对象该什么时候从young代移动到old代。任期阀值会在后面详细的介绍,它是HotSpot VM基于young代的占用空间来计算的,尤其是survivor(幸存者)空间的占用量。下面详细介绍一下survivor空间以及讨论任期阀值?/span>

survivor空间

   survivor空间是young代的一部分,如下图所示。young代被分成了一个eden区域和两个survivor空间?/span>
   
   两个survivor空间的中一个被标记?#8220;from”,另外一个标记为“to”。新的Java对象被分配到Eden空间。比如说,下面的一条语句:
   
[java] view plain copy
  1. <span style="font-size:14px;">   Map<String,String> map = new HashMap<String,String>();</span>  

   一个新的HashMap对象会被放到eden空间,当eden空间满了的时候,MinorGC就会执行,任何存活的对象,都从eden空间复制?#8220;to” survivor空间,任何在“from” survivor空间里面的存活对象也会被复制?#8220;to” survivor。MinorGC结束的时候,eden空间?#8220;from” survivor空间都是空的?#8220;to” survivor空间里面存储存活的对象,然后,在下次MinorGC的时候,两个survivor空间交换他们的标签,现在是空?#8220;from” survivor标记成为“to”?#8220;to” survivor标记?#8220;from”。因此,在MinorGC结束的时候,eden空间是空的,两个survivor空间中的一个是空的?/span>

   在MinorGC过程,如?#8220;to” survivor空间不够大,不能够存储所有的从eden空间和from suvivor空间复制过来活动对象,溢出的对象会被复制到old代。溢出迁移到old代,会导致old代的空间快速增长,会导致stop-the-world压缩垃圾回收,所以,这里要使用MinorGC回收原则?/span>

   避免survivor空间溢出可以通过指定survivor空间的大小来实现,以使得survivor有足够的空间来让对象存活足够的岁数。高效的岁数控制会导致只有长时间存活的对象转移到old代空间?/span>

   岁数控制是指一个对象保持在young代里面直到无法获取,所以让old代只是存储长时间保存的对象?/span>

   survivor的空间可以大小设置可以用HotSpot命令行参数:-XX:SurvivorRatio=<ratio>

   <ratio>必须是以一个大?的值,-XX:SurvivorRatio=<ratio>表示了每一个survivor的空间和eden空间的比值。下面这个公式可以用来计算survivor空间的大?/span>

   
[html] view plain copy
  1. survivor spave size = -Xmn<value>/(-XX:SurvivorRatio=<ratio>+2)  

   这里有一?2的理由是有两个survivor空间,是一个调节参数。ratio设置的越大,survivor的空间越小。为了说明这个问题,假设young代的大小?Xmn512m而且-XX:SurvivorRatio=6.那么,young代有两个survivor空间且空间大小是64M,那么eden空间的大小是384M?/span>

   同样假如young代的大小?12M,但是修?XX:SurvivorRatio=2,这样的配置会使得每一个survivor空间的大小是128m而eden空间的大小是256M?/span>

   对于一个给定大小young代空间大小,减小ratio参数增加survivor空间的大小而且减少eden空间的大小。反之,增加ratio会导致survivor空间减少而且eden空间增大。减少eden空间会导致MinorGC更加频繁,相反,增加eden空间的大小会导致更小的MinorGC,越多的MinorGC,对象的岁数增长得越快?/span>

   为了更好的优化survivor空间的大小和完善young代空间的大小,需要监控任期阀值,任期阀值决定了对象会再young代保存多久。怎么样来监控和优化任期阀值将在下一节中介绍?/span>
   
任期阀?/strong>

   “任期”是转移的代名词,换句话说,任期阀值意味着对象移动到old代空间里面。HotSpot VM每次MinorGC的时候都会计算任期,以决定对象是否需要移动到old代去。任期阀值就是对象的岁数。对象的岁数是指他存活过的MinorGC次数。当一个对象被分配的时候,它的岁数?。在下次MinorGC的时候之后,如果对象还是存活在young代里面,它的岁数就是1。如果再经历过一次MinorGC,它的岁数变?,依此类推。在young代里面的岁数超过HotSpot VM指定阀值的对象会被移动到old代里面。换句话说,任期阀值决定对象在young代里面保存多久?/span>

   任期阀值的计算依赖于young代里面能够存放的对象数以及MinorGC之后?#8220;to” servivor的空间占用。HotSpot VM有一个选项-XX:MaxTenuringThreshold=<n>,可以用来指定当时对象的岁数超过<n>的时候,HotSpot VM会把对象移动到old代去。内部计算的任期阀值一定不会超过指定的最大任期阀值。最大任期阀值在可以被设定为0-15,不过在Java 5 update 5之前可以设置?-31?/span>

   不推荐把最大任期阀值设定成0或者超?5,这样会导致GC的低效率?/span>

   如果HotSpot VM它无法保持目标survivor 空间的占用量,它会使用一个小于最大值的任期阀值来维持目标survivor空间的占用量,任何比这个任期阀值的大的对象都会被移动到old代。话句话说,当存活对象的量大于目标survivor空间能够接受的量的时候,溢出发生了,溢出会导致对象快速的移动到old代,导致不期望的FullGC。甚至会导致更频繁的stop-the-world压缩垃圾回收。哪些对象会被移动到old代是根据评估对象的岁数和任期阀值来确定的。因此,很有必要监控任期阀值以避免survivor空间溢出,接下来详细讨论?/span>

监控任期阀?/strong>

   为了不被内部计算的任期阀值迷惑,我们可以使用命令选项-XX:MaxTenuringThreshod=<n>来指定最大的任期阀值。为了决定出最大的任期阀值,需要监控任期阀值的分布和对象岁数的分布,通过使用下面的选项实现

 
[html] view plain copy
  1. -XX:+PrintTenuringDistribution  

   -XX:+PrintTenuringDistribution的输出显示在survivor空间里面有效的对象的岁数情况。阅?XX:+PrintTenuringDistribution输出的方式是观察在每一个岁数上面,对象的存活的数量,以及其增减情况,以及HotSpot VM计算的任期阀值是不是等于或者近似于设定的最大任期阀值?/span>

   -XX:+PrintTenuringDistribution在MinorGC的时候产生任期分布信息。它可以同其他选项一同使用,比如-XX:+PrintGCDateStamps?XX:+PrintGCTimeStamps以及-XX:+PringGCDetails。当调整survivor空间大小以获得有效的对象岁数分布,你应该使用-XX:+PrintTenuringDistribution。在生产环境中,它同样非常有用,可以用来判断stop-the-world的垃圾回收是否发生?/span>

   下面是一个输出的例子?/span>

   Desired survivor size 8388608 bytes, new threshold 1 (max 15) 
   - age 1: 16690480 bytes, 16690480 total

   在这里例子中,最大任期阀值被设置?5,(通过max 15表示)。内部计算出来的任期阀值是1,通过threshold 1表示?/span>Desired survivor size 8388608 bytes表示一个survivor的空间大小。目标survivor的占有率是指目标survivor和两个survivor空间总和的比值。怎么样指定期望的survivor空间大小在后面会详细介绍。在第一行下面,会列出一个对象的岁数列表。每行会列出每一个岁数的字节数,在这个例子中,岁数是1的对象有16690480字节,而且每行后面有一个总的字节数,如果有多行输出的话,总字节数是前面的每行的累加数。后面举例说明?/span>

   在前面的例子中,由于期望的survivor大小?/span>8388608)比实际总共survivor字节数(16690480)小,也就是说,survivor空间溢出了,这次MinorGC会有一些对象移动到old代。这个就意味着survivor的空间太小了。另外,设定的最大任期阀值是15,但是实际上JVM使用的是1,也表明了survivor的空间太小了?/span>

   如果发现survivor区域太小,就增大survivor的空间,下面详细介绍如何操作?/span>
   
设定survivor空间

   当修改survivor空间的大小的时候,有一点需要记住。当修改survivor空间大小的时候,如果young代的大小不改变,那么eden空间会减小,进一步会导致更频繁的MinorGC。因此,增加survivor空间的时候,如果young代的空间大小违背了MinorGC频率的需求,eden空间的大小同需要需要增加。换句话说,当survivor空间增加的时候,young代的大小需要增加?/span>

   如果有空间来增加MinorGC的频率,有两种选择,一是拿一些eden空间来增加survivor的空间,二是让young的空间更大一些。常规来讲,更好的选择是如果有可以使用的内存,增加young代的空间会比减少eden的空间更好一些。让eden空间大小保持恒定,MinorGC的频率不会改变,即使调整survivor空间的大小?/span>

   使用-XX:+PrintTenuringDistribution选项,对象的总字节数和目标survivor空间占用可以用来计算survivor空间的大小。重复前面的例子?/span>
   Desired survivor size 8388608 bytes, new threshold 1 (max 15) 
   - age 1: 16690480 bytes, 16690480 total

   存活对象的总字节数?/span>1669048,这个并发垃圾回收器(CMS)的目标survivor默认使用50%的survivor空间。通过这个信息,我们可以知道survivor空间至少应该?3380960字节,大概是32M。这个计算让我们知道对survivor空间的预估值需要计算对象的岁数更高效以及防止溢出。为了更好的预估survivor的可用空间,你应该监控应用稳定运行情况下的任期分布,并且使用所有的额外总存活对象的字节数来作为survivor空间的大小?/span>

   在这个例子,为了让应用计算岁数更加有效,survivor空间需要至少提?2M。前面使用的选项是:

 
[html] view plain copy
  1. -Xmx1536m -Xms1536m -Xmn512m -XX:SurvivorRatio=30  

   那么为了保持MinorGC的频率不发生变化,然后增加survivor空间的大小到32M,那么修改后的选项如下?/span>

 
[html] view plain copy
  1. -Xmx1568m -Xms1568m -Xmn544m -XX:SurvivvorRatio=15  

   当时young代空间增加了,eden空间的大小保持大概相同,且survivor的空间大小增减了。需要注意的时候,-Xmx?Xms?Xmn都增加了32m。另外,-XX:SurvivvorRatio=15让每一个survivor空间的大小都?2m ?44/(15+2) = 32)?/span>

   如果存在不能增加young代空间大小的限制,那么增加survivor空间大小需要以减少eden空间的大小为代价。下面是一个增加survivor空间大小,每一个survivor空间?6m增减加到32m,那么会见减少eden的空间,?80m减少?48m?12-32-32=448?12-16-16=480)?/span>

   
[html] view plain copy
  1. -Xms1536m -Xms1536m -Xmn1512m -XX:SurvivorRatio=14  

   再次强调,减少eden空间大小会增加MinorGC的频率。但是,对象会在young代里面保持更长的时间,由于提升survivor的空间?/span>

   假如运行同样的应用,我们保持eden的空间不变,增加survivor空间的大小,如下面选项?/span>

 
[html] view plain copy
  1. <span style="font-size:14px;"> -Xmx1568m -Xms1568m -Xmn544m -XX:SurvivorRatio=15</span>  

   可以产生如下的任期分?
   Desired survivor size 16777216 bytes, new threshold 15 (max 15)
- age 1: 6115072 bytes, 6115072 total
- age 2: 286672 bytes, 6401744 total
- age 3: 115704 bytes, 6517448 total
- age 4: 95932 bytes, 6613380 total
- age 5: 89465 bytes, 6702845 total
- age 6: 88322 bytes, 6791167 total
- age 7: 88201 bytes, 6879368 total
- age 8: 88176 bytes, 6967544 total
- age 9: 88176 bytes, 7055720 total
- age 10: 88176 bytes, 7143896 total
- age 11: 88176 bytes, 7232072 total
- age 12: 88176 bytes, 7320248 total

   从任期分布的情况来看,survivor空间没有溢出,由于存活的总大小是7320248,但是预期的survivor空间大小?6777216以及任期阀值和最大任期阀值是相等的。这个表明,对象的老化速度是高效的,而且survivor空间没有溢出?/span>

   在这个例子中,由于岁数超?的对象很少,你可能像把最大任期阀值设置为3来测试一下,即设置选项-XX:MaxTenuringThreshhold=3,那么整个选项可以设置为:

 
[html] view plain copy
  1. -Xmx1568m -Xms1658m -Xmn544m -XX:SurvivorRatio=15 -XX:MaxTenuringThreshold=3  

   这个选项设置和之前的选项设置的权衡是,后面这个选择可以避免在MinorGC的时候不必要地把对象?#8220;from” survivor复制?#8220;to” survivor。在应用运行在稳定状态的情况下,观察多次MinorGC任期分布情况,看是否有对象最终移动到old代或者显示的结果还是和前面的结果类似。如果你观察得到和前面的任期分布情况相同,基本没有对象的岁数达到15,也没有survivor的空间溢出,你应该自己设置最大任期阀值以代替JVM默认?5。在这个例子中,没有长时间存活的对象,由于在他们的岁数没有到?5的时候就被垃圾回收了。这些对象在MinorGC中被回收了,而不是移动到old代里面。使用并发垃圾回收(CMS)的时候,对象从young代移动到old代最终会导致old的碎片增加,有可能导致stop-the-world压缩垃圾回收,这些都是不希望出现的。宁可选择让对象在“from” survivor?#8220;to” survivor中复制,也不要太快的移动到old代?br />

   你可能需要重复数次监控任期分布、修改survivor空间大小或者重新配置young代的空间大小直到你对应用由于MinorGC引起的延迟满意为止。如果你发现MinorGC的时间太长,你可以通过减少young代的大小直到你满意为止。尽管,减少young代的大小,会导致更快地移动对象到old代,可能导致更多的碎片,如果CMS的并发垃圾回收能够跟上对象的转移率,这种情况就比不能满足应用的延迟需求更好。如果这步不能满足应用的MinorGC的延迟和频率需求,这个时候就有必要重新审视需求以及修改应用程序了?/span>

   如果满足对MinorGC延迟的需求,包括延迟时间和延迟频率,你可以进入下一步,优化CMS垃圾回收周期的启动,下节详细介绍?/span>


]]>
GC学习笔记 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/archive/2016/10/18/431902.html小马?/dc:creator>小马?/author>Tue, 18 Oct 2016 07:37:00 GMT//www.ot7t.com.cn/xiaomage234/archive/2016/10/18/431902.html//www.ot7t.com.cn/xiaomage234/comments/431902.html//www.ot7t.com.cn/xiaomage234/archive/2016/10/18/431902.html#Feedback0//www.ot7t.com.cn/xiaomage234/comments/commentRss/431902.html//www.ot7t.com.cn/xiaomage234/services/trackbacks/431902.html阅读全文

]]>
JVM 不稳定参?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2016/10/18/431901.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Tue, 18 Oct 2016 03:18:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2016/10/18/431901.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/431901.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2016/10/18/431901.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/431901.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/431901.html</trackback:ping><description><![CDATA[     摘要: from://www.tuicool.com/articles/RNjUfa原文  //286.iteye.com/blog/1924947主题 JVM        -XX 参数被称为不稳定参数,之所以这么叫是因为此类参数的设置很容易引起JVM 性能上的差异,使JVM 存在极大...  <a href='//www.ot7t.com.cn/xiaomage234/archive/2016/10/18/431901.html'>阅读全文</a><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/431901.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2016-10-18 11:18 <a href="//www.ot7t.com.cn/xiaomage234/archive/2016/10/18/431901.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JVM系列?JVM参数设置、分?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2016/10/14/431891.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Fri, 14 Oct 2016 07:06:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2016/10/14/431891.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/431891.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2016/10/14/431891.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/431891.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/431891.html</trackback:ping><description><![CDATA[     摘要: from://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html不管是YGC还是Full GC,GC过程中都会对导致程序运行中中?正确的选择不同的GC策略,调整JVM、GC的参数,可以极大的减少由于GC工作,而导致的程序运行中断方面的问题,进而适当的提高Java程序的工作效率。但是调整GC是以个极为复杂的过程,由于各个程序具...  <a href='//www.ot7t.com.cn/xiaomage234/archive/2016/10/14/431891.html'>阅读全文</a><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/431891.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2016-10-14 15:06 <a href="//www.ot7t.com.cn/xiaomage234/archive/2016/10/14/431891.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>国内:如何解决Maven和SBT下载Jar包太?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2016/08/31/431716.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Wed, 31 Aug 2016 08:22:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2016/08/31/431716.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/431716.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2016/08/31/431716.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/431716.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/431716.html</trackback:ping><description><![CDATA[from://my.oschina.net/u/1244232/blog/546900<br /><br /><div style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; padding: 10px 20px; margin: 15px 0px; line-height: 1.8; word-break: break-all; color: #333333; font-family: "Lantinghei SC", "Open Sans", Arial, "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif; background: #f8f8f8;"><strong style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; font-size: 1.6rem;">摘要</strong><div style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; font-size: 1.4rem; color: #666666;">经过了九个月的实习,尝试了不同的机会,在公司从来没有碰到网络问题,国外网站访问毫无压力。临近毕业,返校写毕业论文,论文必须要有实验的支持,这个时候就免不了下载各种Jar包尝试不同的方法,但是碰到的第一个门槛就是网络访问。为了能够访问网络,下面提供几个常用的国内可以快速访问的远程仓库?/div></div><div style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; font-size: 1.6rem; font-family: "Lantinghei SC", "Open Sans", Arial, "Hiragino Sans GB", "Microsoft YaHei", STHeiti, "WenQuanYi Micro Hei", SimSun, sans-serif; word-wrap: break-word; color: #3d464d; line-height: 30px; margin-top: 30px;"><val data-name="blog_content_type" data-value="markdown" style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></val><val data-name="markedJs" data-value="/dist/www/vendor/think-md/0.1.0/javascripts/marked.js?t=1471280768000" style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></val><div style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><h1 class="yibqv">国内:如何解决Maven和SBT下载Jar包太?/h1><h2 class="yibqv">前言</h2><p style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; margin-bottom: 16px;"><strong style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">最近由于忙着写毕业论文,博客撰写暂时停止一段时间?/strong><br style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;" />经过了九个月的实习,尝试了不同的机会,在公司从来没有碰到网络问题,国外网站访问毫无压力。临近毕业,返校写毕业论文,论文必须要有实验的支持,这个时候就免不了下载各种Jar包尝试不同的方法,但是碰到的第一个门槛就是网络访问。为了能够访问网络,下面提供几个常用的国内可以快速访问的远程仓库?/p><h2 class="yibqv">Maven 远程仓库</h2><pre xml"="" style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; overflow-x: auto; padding: 2px; color: #777777; border-radius: 3px; line-height: 1.4; word-wrap: normal; background: #fdf6e3;"><code xml"="" style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; display: block; overflow-x: auto; padding: 10px; border-radius: 4px; line-height: 1.4; word-wrap: normal; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;"> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirror</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">id</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>ui<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">id</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirrorOf</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>central<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirrorOf</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">name</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>Human Readable Name for this Mirror.<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">name</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">url</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>//uk.maven.org/maven2/<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">url</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirror</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirror</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">id</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>ibiblio<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">id</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirrorOf</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>central<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirrorOf</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">name</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>Human Readable Name for this Mirror.<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">name</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">url</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>//mirrors.ibiblio.org/pub/mirrors/maven2/<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">url</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirror</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirror</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">id</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>jboss-public-repository-group<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">id</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirrorOf</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>central<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirrorOf</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">name</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>JBoss Public Repository Group<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">name</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">url</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>//repository.jboss.org/nexus/content/groups/public/<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">url</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirror</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirror</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">id</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>CN<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">id</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">name</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>OSChina Central<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">name</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">url</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>//maven.oschina.net/content/groups/public/<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">url</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirrorOf</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>central<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirrorOf</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirror</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirror</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">id</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>repo2<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">id</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirrorOf</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>central<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirrorOf</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">name</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>Human Readable Name for this Mirror.<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">name</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">url</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span>//repo2.maven.org/maven2/<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">url</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"></</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #268bd2;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">mirror</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">></span></span> </code></pre><p style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; margin-bottom: 16px;">说明?/p><ol style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; margin: 0px 0px 0px 30px; padding: 8px 15px;"><li style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; padding: 0px; margin: 0px;">上面的地址前面三个只适合maven,sbt的ivy不适合,sbt需要的jar包在里面会找不到,从下面的配置可以看出?/li><li style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; padding: 0px; margin: 0px;">oschina的镜像虽然都适用,但是访问速度真是?/li><li style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; padding: 0px; margin: 0px;">最全面的仓库在校园网完全没办法访问</li></ol><h2 class="yibqv">SBT</h2><p style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; margin-bottom: 16px;">修改SBT的远程仓库地址有很多办法,这里采用直接修改sbt-lauch.jar/sbt/sbt.boot.properties的方?/p><pre ruby"="" style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; overflow-x: auto; padding: 2px; color: #777777; border-radius: 3px; line-height: 1.4; word-wrap: normal; background: #fdf6e3;"><code ruby"="" style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; display: block; overflow-x: auto; padding: 10px; border-radius: 4px; line-height: 1.4; word-wrap: normal; background-image: initial; background-attachment: initial; background-size: initial; background-origin: initial; background-clip: initial; background-position: initial; background-repeat: initial;">[scala] <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">version:</span> ${sbt.scala.version-auto} [app] <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">org:</span> ${sbt.organization-org.scala-sbt} <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">name:</span> sbt <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">version:</span> ${sbt.version-read(sbt.version)[<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #2aa198;">0</span>.<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #2aa198;">13.9</span>]} <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #859900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">class</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">: ${</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">sbt</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">.</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">main</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">.</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">class</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">-</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">sbt</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">.</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">xMain</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">}</span></span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">components:</span> xsbti,extra cross-<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">versioned:</span> ${sbt.cross.versioned-<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #2aa198;">false</span>} <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">resources:</span> ${sbt.extraClasspath-} [repositories] local Local-Maven-<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">Repository:</span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">file:</span>/<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #2aa198;">//</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">D:</span>/Java/java-repositories, [organization]/[<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #859900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">module</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">]/[</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">revision</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">]/[</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">type</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">]</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">s</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">/[</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">artifact</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">](-[</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">classifier</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">]).[</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">ext</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">]</span></span> ibiblio-<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">maven:</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">http:</span>/<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #2aa198;">/maven.ibiblio.org/maven</span>2/ typesafe-<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">ivy:</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">https:</span>/<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #2aa198;">/dl.bintray.com/typesafe</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #2aa198;">/ivy-releases/</span>, [organization]/[<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #859900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">module</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">]/(</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">scala_</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">[</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">scalaVersion</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">]/)(</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">sbt_</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">[</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">sbtVersion</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">]/)[</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">revision</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">]/[</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">type</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">]</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">s</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">/[</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">artifact</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">](-[</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">classifier</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">]).[</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #b58900;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;"><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">ext</span></span></span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent;">] </span></span> maven-central uk-<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">repository:</span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">http:</span>/<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #2aa198;">/uk.maven.org/maven</span>2/ jboss-<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">repository:</span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">http:</span>/<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #2aa198;">/repository.jboss.org/nexus</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #2aa198;">/content/groups</span><span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #2aa198;">/public/</span> [boot] <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">directory:</span> ${sbt.boot.directory-${sbt.global.base-${user.home}/.sbt}/boot/} [ivy] ivy-<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">home:</span> <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">D:</span>/Java/java-repositories <span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">checksums:</span> ${sbt.checksums-sha1,md5} override-build-<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">repos:</span> ${sbt.override.build.repos-<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #2aa198;">false</span>} repository-<span style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; color: #cb4b16;">config:</span> ${sbt.repository.config-${sbt.global.base-${user.home}/.sbt}/repositories} </code></pre><p style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; margin-bottom: 16px;">说明?/p><ol style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; margin: 0px 0px 0px 30px; padding: 8px 15px;"><li style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; padding: 0px; margin: 0px;">repositories 修改远程仓库地址</li><li style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; padding: 0px; margin: 0px;">typesafe-ivy:目的是兼容ivy地址</li><li style="box-sizing: inherit; -webkit-tap-highlight-color: transparent; padding: 0px; margin: 0px;">ivy-home:指的是本地仓库地址,就是jar存在哪里</li></ol></div></div><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/431716.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2016-08-31 16:22 <a href="//www.ot7t.com.cn/xiaomage234/archive/2016/08/31/431716.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Collections Cheat Sheet - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/archive/2016/04/22/430194.html小马?/dc:creator>小马?/author>Fri, 22 Apr 2016 06:46:00 GMT//www.ot7t.com.cn/xiaomage234/archive/2016/04/22/430194.html//www.ot7t.com.cn/xiaomage234/comments/430194.html//www.ot7t.com.cn/xiaomage234/archive/2016/04/22/430194.html#Feedback0//www.ot7t.com.cn/xiaomage234/comments/commentRss/430194.html//www.ot7t.com.cn/xiaomage234/services/trackbacks/430194.htmlJava Collections Cheat Sheet

Java Collections cheat sheet

Every Java program tends to have one thing in common. They’ll all use Java collections! They’re so fundamental, we could not even avoid thinking to omit them from out RebelLabs cheat sheet collection. This is a tough challenge, since there’s so much you need to know about the collections framework, the implementation details, correct use cases, how to choose the right collection type, what can they do and when to turn to the third party libraries as opposed to using the built in collections in the JDK.

However, we never take the easy path, remember, we’ve tackled:

Anyway, no topic as broad as Java collections framework can be fully explained in a single A4 page, but we’ve tried to incorporate the most essential information you will need to reference again and again. The corresponding explanations and details behind the decisions are right here, in this blogpost.

GET ME A JAVA COLLECTIONS CHEAT SHEET!

We’ve also created an interactive flow of questions that you can go through to determine which Java collection you should consider using for your data. Hit Enter to get going or Esc to go back a step:

Continue reading to get a better understanding of the collection classes available in Java and when to use them.

Collections interfaces and implementations in JDK

You might think that the collections framework was always a part of the JDK. Surprise, surprise, that’s not true. Collections are one of the most fundamentals parts of the JDK, or any programming language for that matter, but it’s also one of the hardest aspects of programming to get right. On top of that it’s really challenging to make the collections library simple, coherent, and easy to use (I’m looking at you, Scala). So the Java collections library was introduced to Java in the Java 1.2 in 1998 and has stuck with us since then. Since backwards compatibility is one of the core values of the Java platform, collections haven’t changed a lot since then. However, recently in the Java 8 release, the language evolved enough to provide tools to enhance the collection interfaces without breaking backwards compatibility.

All in all, Java collections is a comprehensive library that contains the utilities to tackle almost any container-like data structure you might need. Let’s dive into which types of collections are available and outline what makes them special and why you might want to use them.

Short description of the most used collections

There are two main approaches to choosing the collection type you need in your code. The first is simple enough, but not always the most effective:

if it fits into an ArrayList, use ArrayList, otherwise you probably need a HashMap.

The other includes having an understanding of the operations you will be needing from the collection, the performance you would expect from them and what kind of data you intend to put into the collection. While the advice above can take you quite far, it’s much better to understand the options available to help you make an informed decision.

Collection interfaces you need to master

There are 4 main types of Java collections available. Naturally, the implementations for each type can be found under the corresponding interfaces. Before we start digging into these, there are 2 main umbrella interfaces you want to know about: Iterable and Collection. Typically you rarely need to think about these, but it’s important to at least understand them. The iterable interface allows one to obtain an iterator and traverse the sequence of elements by calling the next() method. It also makes it possible to iterate through elements with the syntactic sugar of the “for-each” loop:

for(E e: iterable)  

The collection interface extends the Iterable and represents an iterable group of elements which can be added, removed, or checked for presence in the collection. However, the implementations usually implement the more specific interfaces that are designed with the collection implementation in mind. Here are the most used collection interfaces.

List

List is an ordered collection of elements. Some languages call that a sequence, or you can think of if it as an array of varying length. You can add elements to it, in the middle of it, access and replace the elements using an index.

Not surprisingly, the list is one of the most common collections used. However, there’s almost no variety in the used implementations required. Yeah, in school you learned about the dreaded linked lists and how to implement them and how awesome it is to have access to the head and the tail of it. In practice, you are better using the ArrayList 99% of the time.

The reason for that is quite simple, it consumes less memory, it is friendlier to the caches, and it is in general faster than the LinkedList from the JDK. In fact, you should try not to use a LinkedList.

If you foresee that you’ll need to establish concurrent access to a list, you’ll need to worry about the synchronization yourself. Typically, that means that either you will use a CopyOnWriteArrayListwhich is thread-safe and immutable. If your data can be mutated by another thread, but the performance of the reading accesses is much more important. CopyOnWriteArrayList is your list of choice.

Set

A collection that contains no duplicate elements is a set. Just like the mathematical set, the interface denotes a collection that holds elements and basically answers a single question: is a given element contained in the set.

Set doesn’t necessarily specify the order of elements when you iterate them, but all set implementations are created with the performance of the contains method in mind.

There are two main Set implementations that you should know about: HashSet and TreeSet. HashSet hashes the elements and distributes them into buckets by the hash value. Tree set is backed by a balanced tree, which makes it ordered and navigable (so you can ask what for the previous and next elements by value). TreeSet operations will have worse complexity compared to the HashSet as a result, but bear in mind that the operations still take sublinear time of the set size, which means that for realistic values of the set sizes, it’s still quite a short time.

However, typically use-cases for sets do not require navigating from element to element, so the HashSet is the goto implementation you’ll tend to use. And it’s a good one. Just remember to correctly implement the hashCode() and equals() methods for your elements.

Map

Perhaps the most used collection type of all time — an object that maps keys to values, an associative array, a table: the map. Maps are the most versatile collection type because the association of keys to values is really what computers are all about: a dictionary, mapping object properties to their values just like javascript does, mapping filenames to their contents and metadata, mapping usernames to password hashes, session attributes, product cart items, game high scores. Wherever you look you’ll find a use case for a map.

Naturally there are different implementations that are tweaked to provide different performance trade-offs. But the default goto implementation of the map interface is undoubtedly the infamousHashMap.

The Hashmap implementation depends on the Key objects implementing the hashCode() and equals() methods correctly, so always take care of these. In return the HashMap promises you the almost constant time performance which is as amazing as you can get out of any data structure and scales amazingly well.

If you need the navigation between elements or you’d need to deal with unhashable element types, you can use a TreeMap. Using a balanced tree, just like the sets above, treemap scales appropriately and gives you a chance to iterate the contents in a sorted order.

Now we don’t want to dive into all the API methods for maps. You can put and get values, as you’d expect. But we would love to point out one super amazing method that has been available to us since Java 8: computeIfAbsent.

default V computeIfAbsent(K key,                           Function<? super K,? extends V> mappingFunction) 

What computeIfAbsent does is give you an opportunity to specify how to obtain the value for the key, if it’s not in the collection yet. Essentially it checks if the given key is contained in the map. If it happens to be so, you get the corresponding value back. If not, the mapping function is executed and the resulting values is put into the map and returned to you.

That’s more or less how caches work. Amazing, right?

Queue

queue is a collection designed to hold elements prior to processing, the elements wait in line to be consumed and can be added to the tail of the queue. Queues are those fundamental pieces of software that tie components together. When components are communicating in a system, there’s typically a queue of messages sitting between them.

Queues are a special sort of collection, because are mostly operated using the Queue interface, rather than methods inherited from the Collection interface. To add an element to a queue, use:

E e;  Queue<E> q = …  q.offer(e); // try to put the element into the queue, if the queue is full, do nothing q.poll(); // remove the head of the queue  q.peek(); // return the head of the queue without modifying it. 

There are also corresponding methods that throw exceptions if operations don’t succeed. But all in all, there are three main operations one performs on a queue: enqueue, deque and peek.
Note that you can get an iterator from the queue and process the elements similar to any other collection. It would even work for some implementations of the queue interface, but not for all.

These are the typical classes that you might use that implement the queue interface:

  • ArrayDeque – a good general purpose battle-tested implementation of a queue. ArrayDeque is backed by a resizeable array that can grow to accommodate additional elements. Most ArrayDeque operations run in amortized constant time.
  • PriorityQueue – a queue of sorted elements. The sorting is achieved either naturally or determined by a provided comparator, but the head of the queue is always the minimal element. Note that a priority queue won’t change its order if you mutate the elements inside it. If you’re curious about the performance, the mutating operations run in logarithmic time of the queue size, peeking and such — in constant, and the search is linear.

Collection utilities

Now we’ve talked about all the most common collection types you’ll encounter, it’s time to dig into the other parts of the Java collections framework. There’s an amazing class, calledCollections, that provides handy utility methods that you should be aware of. First of all let’s talk about the collection wrappers. Any collection type can have additional requirements to its functionality, these orthogonal qualities are implemented with the wrappers. The original collection is wrapped into another one that delegates the element handling logic to it.

The prime example of some functionality that is suitable for a wrapper is making a collection immutable. Indeed, you just need to ignore all the mutating operations like: put, insert, and so on. And all the non-mutating operations can be easily delegated to the actual collection implementations.

The Collections class provides a set of methods that give you just that: unmodifiable collections:

Java-collections-wrappers

Another useful type of wrapper available is the synchronized collections wrapper. Indeed, most of the collection implementations do not implement the synchronization themselves. What would you do if you need to use HashSet concurrently from multiple threads? That’s right, you call the corresponding wrapper method and use the returned set.

Collections.synchronizedSet(new HashSet<E>()); 

It’s important to remember that the wrapper does not change the implementation of the underlying collection. That is if you obtain a reference to the wrapped hash set and use that concurrently there are no guarantees.

Here’s a short list of the useful methods in the Collections class that typically are used more than others:

  • binarySearch – a fast way to find an element in a sorted List.
  • frequency – tells you how many times an element is encountered in a collection
  • min / max – returns the smallest / largest element of the collection
  • reverseOrder – provides you with a Comparator to sort elements in the descending order
  • singleton – wraps an object into the Set containing that object, the similar methods are available for the List and Map classes.

Other libraries

There are more questions that you can ask of your collection implementation and obviously there are more answers than just the stock implementations you can find in the JDK. Here are some libraries that we think are amazing and give you more functionality for the collection creation and manipulation and more collection types.

  • Guava – Google Core Libraries for Java 6+. Perhaps the default third party collection library for Java projects. Contains a magnitude of convenient methods for creating collection, like fluent builders, as well as advanced collection types.
  • Eclipse Collections – Features you want with the collections you need. Previously known as gs-collections, this library includes almost any collection you might need: primitive type collections, multimaps, bidirectional maps and so on.
  • Fastutil – Fast & compact type-specific collections for Java. Great default choice for collections of primitive types, like int or long. Also handles big collections with more than 2^31 elements.
  • JCTools – Java Concurrency Tools for the JVM. If you work on high throughput concurrent applications and need a way to increase your performance, check out JCTools. It contains lots of queues for all kinds of single / multiple producer / consumer environments and other useful classes.

Sure, this is not a definitive list, but these are the essential libraries that you should know about. You’re might be using Guava in your project already; at least once you have thought about how awesome would it be to have the collections for primitives, and so on. So check these out!

Improving JDK collections

It’s not easy to change something as fundamental as the collections library in the JDK. However, the Java 8 release had implemented a major enhancements to the collections library and more than that, with the inclusion of the default methods it made it possible to evolve the collection interfaces without breaking all of the implementations.

The progress doesn’t stop there. The upcoming Java 9 release contains the JEP 269: Convenience Factory Methods for Collections, the proposal to include the methods for easier collection creation. Finally, we would be able to specify the collections with a simpler syntax like:

  List.of(a, b, c); Set.of(d, e, f, g); Map.ofEntries(     entry(k1, v1),     entry(k2, v2),     entry(k3, v3)); 

That would be really sweet.

Conclusion

We’ve talked a lot about Java collections and different implementations of the collection interfaces you can find in the java.util package. Sets, Lists and Maps are your friends and you’ll need to apply quite a bit of imagination to come up with a program that doesn’t need the collections API. We touched on the subject of collection wrappers and how to make collections immutable and synchronize them for concurrent access.

Be sure to check out those libraries above with the alternative collections implementations. Hopefully you liked this post and the cheat sheet that tries to give you the information about Java collections on a single printable A4 sized piece of paper.

SHOW ME JAVA COLLECTIONS CHEAT SHEET!



    ]]>借HSDB来探索HotSpot VM的运行时数据 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/archive/2016/04/22/430188.html小马?/dc:creator>小马?/author>Fri, 22 Apr 2016 01:59:00 GMT//www.ot7t.com.cn/xiaomage234/archive/2016/04/22/430188.html//www.ot7t.com.cn/xiaomage234/comments/430188.html//www.ot7t.com.cn/xiaomage234/archive/2016/04/22/430188.html#Feedback0//www.ot7t.com.cn/xiaomage234/comments/commentRss/430188.html//www.ot7t.com.cn/xiaomage234/services/trackbacks/430188.html阅读全文

    ]]>
    java注解是怎么实现?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2016/04/22/430187.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Fri, 22 Apr 2016 01:58:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2016/04/22/430187.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/430187.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2016/04/22/430187.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/430187.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/430187.html</trackback:ping><description><![CDATA[<div class="yibqv">作者:曹旭?br />链接:https://www.zhihu.com/question/24401191/answer/37601385<br />来源:知?br />著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处?br /><br /><div clearfix"="">下文所使用的java版本信息<br /><br /><div class="yibqv"><pre><code>$ java -version java version "1.8.0_20" Java(TM) SE Runtime Environment (build 1.8.0_20-b26) Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode) </code></pre></div><br /><br />java中的注解是一种继承自接口`java.lang.annotation.Annotation`的特殊接口。参见下面的[JLS][2]和JDK文?br /><br /><blockquote><div class="yibqv"><pre><code>An annotation type declaration specifies a new annotation type, a special kind of interface type. To distinguish an annotation type declaration from a normal interface declaration, the keyword interface is preceded by an at-sign (@). ... The direct superinterface of every annotation type is java.lang.annotation.Annotation. </code></pre></div></blockquote><br /><div class="yibqv"><pre><code>/** * The common interface extended by all annotation types. Note that an * interface that manually extends this one does <i>not</i> define * an annotation type. Also note that this interface does not itself * define an annotation type. * * More information about annotation types can be found in section 9.6 of * <cite>The Java&trade; Language Specification</cite>. * * The {@link java.lang.reflect.AnnotatedElement} interface discusses * compatibility concerns when evolving an annotation type from being * non-repeatable to being repeatable. * * @author Josh Bloch * @since 1.5 */ public interface Annotation { ... } </code></pre></div><br />下面看一下具体示例?br /><br />定义一个注解:<br /><div class="yibqv"><pre><code>import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by Administrator on 2015/1/18. */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface TestAnnotation { int count() default 1; } </code></pre></div><br />经过编译之后,注解`TestAnnotation`的字节码是这样的?br /><div class="yibqv"><pre><code>Classfile /e:/workspace/intellij/SpringTest/target/classes/TestAnnotation.class Last modified 2015-1-18; size 379 bytes MD5 checksum 200dc3a75216b7a88ae17873d5dffd4f Compiled from "TestAnnotation.java" public interface TestAnnotation extends java.lang.annotation.Annotation minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION Constant pool: #1 = Class #14 // TestAnnotation #2 = Class #15 // java/lang/Object #3 = Class #16 // java/lang/annotation/Annotation #4 = Utf8 SourceFile #5 = Utf8 TestAnnotation.java #6 = Utf8 RuntimeVisibleAnnotations #7 = Utf8 Ljava/lang/annotation/Target; #8 = Utf8 value #9 = Utf8 Ljava/lang/annotation/ElementType; #10 = Utf8 TYPE #11 = Utf8 Ljava/lang/annotation/Retention; #12 = Utf8 Ljava/lang/annotation/RetentionPolicy; #13 = Utf8 RUNTIME #14 = Utf8 TestAnnotation #15 = Utf8 java/lang/Object #16 = Utf8 java/lang/annotation/Annotation { } SourceFile: "TestAnnotation.java" RuntimeVisibleAnnotations: 0: #7(#8=[e#9.#10]) 1: #11(#8=e#12.#13) </code></pre></div><br />从反编译后的信息中可以看出,注解就是一个继承自`java.lang.annotation.Annotation`的接口?br /><br />那么接口怎么能够设置属性呢?简单来说就是java通过动态代理的方式为你生成了一个实现了"接口"`TestAnnotation`的实例(对于当前的实体来说,例如类、方法、属性域等,这个代理对象是单例的),然后对该代理实例的属性赋值,这样就可以在程序运行时(如果将注解设置为运行时可见的话)通过反射获取到注解的配置信息?br /><br />具体来说是怎么实现的呢?br /><br />写一个使用该注解的类?br /><div class="yibqv"><pre><code>import java.io.IOException; /** * Created by Administrator on 2015/1/18. */ @TestAnnotation(count = 0x7fffffff) public class TestMain { public static void main(String[] args) throws InterruptedException, NoSuchFieldException, IllegalAccessException, IOException { TestAnnotation annotation = TestMain.class.getAnnotation(TestAnnotation.class); System.out.println(annotation.count()); System.in.read(); } } </code></pre></div><br />反编译一下这段代码:<br /><div class="yibqv"><pre><code>Classfile /e:/workspace/intellij/SpringTest/target/classes/TestMain.class Last modified 2015-1-20; size 1006 bytes MD5 checksum a2d5367ea568240f078d5fb1de917550 Compiled from "TestMain.java" public class TestMain minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #10.#34 // java/lang/Object."<init>":()V #2 = Class #35 // TestMain #3 = Class #36 // TestAnnotation #4 = Methodref #37.#38 // java/lang/Class.getAnnotation:(Ljava/lang/Class;)Ljava/lang/annotation/Annotation; #5 = Fieldref #39.#40 // java/lang/System.out:Ljava/io/PrintStream; #6 = InterfaceMethodref #3.#41 // TestAnnotation.count:()I #7 = Methodref #42.#43 // java/io/PrintStream.println:(I)V #8 = Fieldref #39.#44 // java/lang/System.in:Ljava/io/InputStream; #9 = Methodref #45.#46 // java/io/InputStream.read:()I #10 = Class #47 // java/lang/Object #11 = Utf8 <init> #12 = Utf8 ()V #13 = Utf8 Code #14 = Utf8 LineNumberTable #15 = Utf8 LocalVariableTable #16 = Utf8 this #17 = Utf8 LTestMain; #18 = Utf8 main #19 = Utf8 ([Ljava/lang/String;)V #20 = Utf8 args #21 = Utf8 [Ljava/lang/String; #22 = Utf8 annotation #23 = Utf8 LTestAnnotation; #24 = Utf8 Exceptions #25 = Class #48 // java/lang/InterruptedException #26 = Class #49 // java/lang/NoSuchFieldException #27 = Class #50 // java/lang/IllegalAccessException #28 = Class #51 // java/io/IOException #29 = Utf8 SourceFile #30 = Utf8 TestMain.java #31 = Utf8 RuntimeVisibleAnnotations #32 = Utf8 count #33 = Integer 2147483647 #34 = NameAndType #11:#12 // "<init>":()V #35 = Utf8 TestMain #36 = Utf8 TestAnnotation #37 = Class #52 // java/lang/Class #38 = NameAndType #53:#54 // getAnnotation:(Ljava/lang/Class;)Ljava/lang/annotation/Annotation; #39 = Class #55 // java/lang/System #40 = NameAndType #56:#57 // out:Ljava/io/PrintStream; #41 = NameAndType #32:#58 // count:()I #42 = Class #59 // java/io/PrintStream #43 = NameAndType #60:#61 // println:(I)V #44 = NameAndType #62:#63 // in:Ljava/io/InputStream; #45 = Class #64 // java/io/InputStream #46 = NameAndType #65:#58 // read:()I #47 = Utf8 java/lang/Object #48 = Utf8 java/lang/InterruptedException #49 = Utf8 java/lang/NoSuchFieldException #50 = Utf8 java/lang/IllegalAccessException #51 = Utf8 java/io/IOException #52 = Utf8 java/lang/Class #53 = Utf8 getAnnotation #54 = Utf8 (Ljava/lang/Class;)Ljava/lang/annotation/Annotation; #55 = Utf8 java/lang/System #56 = Utf8 out #57 = Utf8 Ljava/io/PrintStream; #58 = Utf8 ()I #59 = Utf8 java/io/PrintStream #60 = Utf8 println #61 = Utf8 (I)V #62 = Utf8 in #63 = Utf8 Ljava/io/InputStream; #64 = Utf8 java/io/InputStream #65 = Utf8 read { public TestMain(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 7: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LTestMain; public static void main(java.lang.String[]) throws java.lang.InterruptedException, java.lang.NoSuchFieldException, java.lang.IllegalAccessException, java.io.IOException; descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=2, args_size=1 0: ldc #2 // class TestMain 2: ldc #3 // class TestAnnotation 4: invokevirtual #4 // Method java/lang/Class.getAnnotation:(Ljava/lang/Class;)Ljava/lang/annotation/Annotation; 7: checkcast #3 // class TestAnnotation 10: astore_1 11: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 14: aload_1 15: invokeinterface #6, 1 // InterfaceMethod TestAnnotation.count:()I 20: invokevirtual #7 // Method java/io/PrintStream.println:(I)V 23: getstatic #8 // Field java/lang/System.in:Ljava/io/InputStream; 26: invokevirtual #9 // Method java/io/InputStream.read:()I 29: pop 30: return LineNumberTable: line 10: 0 line 11: 11 line 12: 23 line 13: 30 LocalVariableTable: Start Length Slot Name Signature 0 31 0 args [Ljava/lang/String; 11 20 1 annotation LTestAnnotation; Exceptions: throws java.lang.InterruptedException, java.lang.NoSuchFieldException, java.lang.IllegalAccessException, java.io.IOException } SourceFile: "TestMain.java" RuntimeVisibleAnnotations: 0: #23(#32=I#33) </code></pre></div><br />最后一行的代码说明,注解`TestAnnotation`的属性设置是在编译时就确定了的。(对属性的说明在[这里][1])?br /><br />然后,运行上面的程序,通过CLHSDB在eden区找到注解实例,<br /><br /><div class="yibqv"><pre><code>hsdb> scanoops 0x00000000e1b80000 0x00000000e3300000 TestAnnotation 0x00000000e1d6c360 com/sun/proxy/$Proxy1 </code></pre></div><br />类型`com/sun/proxy/$Proxy1`是jdk动态代理生成对象时的默认类型,其中`com.sun.proxy`是默认的包名,定义于`ReflectUtil`类的`PROXY_PACKAGE`字段中。代理类名`$PROXY1`包含两部分,其中前缀`$PROXY`是jdk种默认的代理类类名前缀(参见`java.lang.reflect.Proxy`类的javadoc),后的1是自增的结果?br /><br />下面看一下这个代理类的内容。运行java程序时添加参数`-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true`可以将转储出jdk动态代理类的class文件。若是项目较大或是使用了各种框架的话,慎用此参数?br /><br /><div class="yibqv"><pre><code>Classfile /e:/workspace/intellij/SpringTest/target/classes/com/sun/proxy/$Proxy1.class Last modified 2015-1-19; size 2062 bytes MD5 checksum 7321e44402258ba9e061275e313c5c9f public final class com.sun.proxy.$Proxy1 extends java.lang.reflect.Proxy implements TestAnnotation minor version: 0 major version: 49 flags: ACC_PUBLIC, ACC_FINAL ... </code></pre></div><br />太长了,只截取一部分。从中可以看到,这个代理类实现了继承自`java.lang.reflect.Proxy`类,又实现了“接口”TestAnnotation?br /><br />接下来查看一下代理对象的内容?br /><br /><div class="yibqv"><pre><code>hsdb> inspect 0x00000000e1d6c360 instance of Oop for com/sun/proxy/$Proxy1 @ 0x00000000e1d6c360 @ 0x00000000e1d6c360 (size = 16) _mark: 1 _metadata._compressed_klass: InstanceKlass for com/sun/proxy/$Proxy1 h: Oop for sun/reflect/annotation/AnnotationInvocationHandler @ 0x00000000e1ce7670 Oop for sun/reflect/annotation/Annota tionInvocationHandler @ 0x00000000e1ce7670 </code></pre></div>其中?xe1ce74e0是成员变量h的地址(h是定义在`java.lang.reflect.Proxy`类中的),通过查看类`AnnotationInvocationHandler`的源码可以知道注解的代理实例的值就存储在它的成员变量`memberValues`中,然后继续向下挖就好了?br /><br /><div class="yibqv"><pre><code>hsdb> inspect 0x00000000e1ce7670 instance of Oop for sun/reflect/annotation/AnnotationInvocationHandler @ 0x00000000e1ce7670 @ 0x00000000e1ce7670 (size = 24) _mark: 1 _metadata._compressed_klass: InstanceKlass for sun/reflect/annotation/AnnotationInvocationHandler type: Oop for java/lang/Class @ 0x00000000e1ccc5f8 Oop for java/lang/Class @ 0x00000000e1ccc5f8 memberValues: Oop for java/util/LinkedHashMap @ 0x00000000e1ce7548 Oop for java/util/LinkedHashMap @ 0x00000000e1ce7548 memberMethods: null null hsdb> inspect 0x00000000e1ce7548 instance of Oop for java/util/LinkedHashMap @ 0x00000000e1ce7548 @ 0x00000000e1ce7548 (size = 56) _mark: 1 _metadata._compressed_klass: InstanceKlass for java/util/LinkedHashMap keySet: null null values: null null table: ObjArray @ 0x00000000e1ce75b8 Oop for [Ljava/util/HashMap$Node; @ 0x00000000e1ce75b8 entrySet: null null size: 1 modCount: 1 threshold: 1 loadFactor: 0.75 head: Oop for java/util/LinkedHashMap$Entry @ 0x00000000e1ce75d0 Oop for java/util/LinkedHashMap$Entry @ 0x00000000e1ce7 5d0 tail: Oop for java/util/LinkedHashMap$Entry @ 0x00000000e1ce75d0 Oop for java/util/LinkedHashMap$Entry @ 0x00000000e1ce75d0 accessOrder: false hsdb> inspect 0x00000000e1ce75d0 instance of Oop for java/util/LinkedHashMap$Entry @ 0x00000000e1ce75d0 @ 0x00000000e1ce75d0 (size = 40) _mark: 1 _metadata._compressed_klass: InstanceKlass for java/util/LinkedHashMap$Entry hash: 94852264 key: "count" @ 0x00000000e1bd7c90 Oop for java/lang/String @ 0x00000000e1bd7c90 value: Oop for java/lang/Integer @ 0x00000000e1ce7630 Oop for java/lang/Integer @ 0x00000000e1ce7630 next: null null before: null null after: null null hsdb> inspect 0x00000000e1ce7630 instance of Oop for java/lang/Integer @ 0x00000000e1ce7630 @ 0x00000000e1ce7630 (size = 16) _mark: 1 _metadata._compressed_klass: InstanceKlass for java/lang/Integer value: 2147483647 </code></pre></div><br />最后可以看到,key=“count”, value=Integer(2147483647 = 0x7fffffff),正是在TestMain中设置的?<br /><br />嗯,就这样吧?br /><br /><br />[1]: <a wrap="" external"="" target="_blank" rel="nofollow noreferrer">Chapter 4. The class File Format<em></em></a><br />[2]: <a wrap="" external"="" target="_blank" rel="nofollow noreferrer">Chapter 9. Interfaces<em></em></a></div></div><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/430187.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2016-04-22 09:58 <a href="//www.ot7t.com.cn/xiaomage234/archive/2016/04/22/430187.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring Boot 静态资源处? - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/archive/2016/04/12/430054.html小马?/dc:creator>小马?/author>Tue, 12 Apr 2016 06:21:00 GMT//www.ot7t.com.cn/xiaomage234/archive/2016/04/12/430054.html//www.ot7t.com.cn/xiaomage234/comments/430054.html//www.ot7t.com.cn/xiaomage234/archive/2016/04/12/430054.html#Feedback0//www.ot7t.com.cn/xiaomage234/comments/commentRss/430054.html//www.ot7t.com.cn/xiaomage234/services/trackbacks/430054.html阅读全文

    ]]>
    基于play-scala的sbt目录和ivy仓库设置【转?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2016/04/06/429983.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Wed, 06 Apr 2016 02:11:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2016/04/06/429983.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/429983.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2016/04/06/429983.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/429983.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/429983.html</trackback:ping><description><![CDATA[     摘要: 花了一下午时间,总算全部搞定。时间主要都花费在下载jar包上,虽然开了VPN还是下载慢,没有VPN的话,真心要奔溃的。这期间有太多坑了,所以写这篇文章?一是记录下,二是方便大家查阅。本人的系统环境为什么要说系统环境呢?不同的环境有不同的设置方法,但看了这篇文章后,可以举一反三,在其他环境设置也没什么问题。OS: OS X EI Capitan 10.11IDE: IntelliJ IDEA 14...  <a href='//www.ot7t.com.cn/xiaomage234/archive/2016/04/06/429983.html'>阅读全文</a><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/429983.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2016-04-06 10:11 <a href="//www.ot7t.com.cn/xiaomage234/archive/2016/04/06/429983.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>阿里巴巴分布式服务框?Dubbo 团队成员梁飞专访 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/archive/2016/03/24/429793.html小马?/dc:creator>小马?/author>Thu, 24 Mar 2016 05:21:00 GMT//www.ot7t.com.cn/xiaomage234/archive/2016/03/24/429793.html//www.ot7t.com.cn/xiaomage234/comments/429793.html//www.ot7t.com.cn/xiaomage234/archive/2016/03/24/429793.html#Feedback0//www.ot7t.com.cn/xiaomage234/comments/commentRss/429793.html//www.ot7t.com.cn/xiaomage234/services/trackbacks/429793.htmlDubbo是阿里巴巴内部的SOA服务化治理方案的核心框架,每天为2000+ 个服务提?,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。Dubbo?011年开源后,已被许多非阿里系公司使用?nbsp;

    项目主页?a target="_blank" style="color: #006699;">//alibaba.github.io/dubbo-doc-static/Home-zh.htm 

    为了使大家对该框架有一个深入的了解,本期我们采访了Dubbo团队主要开发人员之一梁飞?nbsp;

    ITeye期待并致力于为国内优秀的开源项目提供一个免费的推广平台,如果你和你的团队希望将自己的开源项目介绍给更多的开发者,或者你希望我们对哪些开源项目进行专访,请告诉我们,发站内短信给ITeye管理?/a>或者发邮件到webmaster@iteye.com即可?/strong>

    先来个自我介绍吧?span style="float: right; padding: 0px 0px 5px 5px;">Top

    我叫梁飞,花名虚极,之前负责Dubbo服务框架,现已调到天猫?nbsp;

    我的博客?a target="_blank" style="color: #006699; text-decoration: none;">//javatar.iteye.com

    Dubbo是什么?能做什么?Top

    Dubbo是一个分布式服务框架,以及SOA治理方案。其功能主要包括:高性能NIO通讯及多协议集成,服务动态寻址与路由,软负载均衡与容错,依赖分析与降级等?nbsp;

    可参见://alibaba.github.io/dubbo-doc-static/Home-zh.htm

    Dubbo适用于哪些场景?Top

    当网站变大后,不可避免的需要拆分应用进行服务化,以提高开发效率,调优性能,节省关键竞争资源等?nbsp;

    当服务越来越多时,服务的URL地址信息就会爆炸式增长,配置管理变得非常困难,F5硬件负载均衡器的单点压力也越来越大?nbsp;

    当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系?nbsp;

    接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?等等…… 

    在遇到这些问题时,都可以用Dubbo来解决?nbsp;

    可参见:Dubbo的背景及需?/a>

    Dubbo的设计思路是什么?Top

    该框架具有极高的扩展性,采用微核+插件体系,并且文?齐全,很方便二次开发,适应性极强?nbsp;

    可参见:开发者指?- 框架设计

    Dubbo的需求和依赖情况?span style="float: right; padding: 0px 0px 5px 5px;">Top

    Dubbo运行JDK1.5之上,缺省依赖javassist、netty、spring等包,但不是必须依赖,通过配置Dubbo可不依赖任何三方库运行?nbsp;

    可参见:用户指南 - 依赖

    Dubbo的性能如何?span style="float: right; padding: 0px 0px 5px 5px;">Top

    Dubbo通过长连接减少握手,通过NIO及线程池在单连接上并发拼包处理消息,通过二进制流压缩数据,比常规HTTP等短连接协议更快。在阿里巴巴内部,每天支?000多个服务?0多亿访问量,最大单机支撑每天近1亿访问量?nbsp;

    可参见:Dubbo性能测试报告

    和淘宝HSF相比,Dubbo的特点是什么?Top

    1.  Dubbo比HSF的部署方式更轻量,HSF要求使用指定的JBoss等容器,还需要在JBoss等容器中加入sar包扩展,对用户运行环境的侵入性大,如果你要运行在Weblogic或Websphere等其它容器上,需要自行扩展容器以兼容HSF的ClassLoader加载,而Dubbo没有任何要求,可运行在任何Java环境中?nbsp;

    2.  Dubbo比HSF的扩展性更好,很方便二次开?/strong>,一个框架不可能覆盖所有需求,Dubbo始终保持平等对待第三方理念,即所有功能,都可以在不修改Dubbo原生代码的情况下,在外围扩展,包括Dubbo自己内置的功能,也和第三方一样,是通过扩展的方式实现的,而HSF如果你要加功能或替换某部分实现是很困难的,比如支付宝和淘宝用的就是不同的HSF分支,因为加功能时改了核心代码,不得不拷一个分支单独发展,HSF现阶段就算开源出来,也很难复用,除非对架构重写?nbsp;

    3.  HSF依赖比较多内部系?/strong>,比如配置中心,通知中心,监控中心,单点登录等等,如果要开源还需要做很多剥离工作,而Dubbo为每个系统的集成都留出了扩展点,并已梳理干清所有依赖,同时为开源社区提供了替代方案,用户可以直接使用?nbsp;

    4.  Dubbo比HSF的功能更?/strong>,除了ClassLoader隔离,Dubbo基本上是HSF的超集,Dubbo也支持更多协议,更多注册中心的集成,以适应更多的网站架构?/div>

    Dubbo在安全机制方面是如何解决的?Top

    Dubbo主要针对内部服务,对外的服务,阿里有开放平台来处理安全和流控,所以Dubbo在安全方面实现的功能较少,基本上只防君子不防小人,只防止误调用?nbsp;

    Dubbo通过Token令牌防止用户绕过注册中心直连,然后在注册中心上管理授权。Dubbo还提供服务黑白名单,来控制服务所允许的调用方?nbsp;

    可参见:Dubbo的令牌验?/a>

    Dubbo在阿里巴巴内部以及外部的应用情况?span style="float: right; padding: 0px 0px 5px 5px;">Top

    在阿里内部,除淘系以外的其它阿里子公司,都在使用Dubbo,包括:中文主站,国际主站,AliExpress,阿里云,阿里金融,阿里学院,良无限,来往等等?nbsp;

    开源后,已被:去哪儿,京东,吉利汽车,方正证劵,海尔,焦点科技,中润四方,华新水泥,海康威视,等公司广泛使用,并不停的有新公司加入,社区讨论及贡献活跃,得到用户很高的评价?nbsp;

    可参见:Dubbo的已知用?/a>

    在分布式事务、多语言支持方面,Dubbo的计划是什么?Top

    分布式事务可能暂不会支持,因为如果只是支持简单的XA/JTA两阶段提交事务,实用性并不强。用户可以自行实现业务补偿的事件,或更复杂的分布式事务,Dubbo有很多扩展点可以集成?nbsp;

    在多语言方面,Dubbo实现了C++版本,但在内部使用面极窄,没有得到很强的验证,并且C++开发资源紧张,没有精力准备C++开源事项?/div>

    Dubbo采用的开源协议?商业应用应该注意哪些事项?span style="float: right; padding: 0px 0px 5px 5px;">Top

    Dubbo采用Apache License 2.0开源协议,它是一个商业友好的协议,你可以免费用于非开源的商业软件中?nbsp;

    你可以对它进行改造和二次发布,只要求保留阿里的著作权,并在再发布时保留原始许可声明?nbsp;

    可参见:Dubbo的开源许可证

    Dubbo开发团队情况?Top

    Dubbo共有六个开发人员参与开发和测试,每一个开发人员都是很有经验,团队合作很默契,开发过程也很有节奏,有完善质量保障流程。团队组成: 

    • 梁飞 (开发人?产品管理?/li>
    • 刘昊?(开发人?过程管理?/li>
    • 刘超 (开发人?用户支持?/li>
    • 李鼎 (开发人?用户支持?/li>
    • 陈雷 (开发人?质量保障?/li>
    • 闾刚 (开发人?开源运维)
     
    从左至右:刘超,梁飞,闾刚,陈雷,刘昊旻,李?/div>
    可参见:Dubbo的团队成?/a>

    其他开发者如何参与?可以做哪些工作?Top

    开发者可以在Github上fork分支,然后将修改push过来,我们审核并测试后,会合并到主干中?nbsp;

    Github地址?a target="_blank" style="color: #006699; text-decoration: none;">https://github.com/alibaba/dubbo 

    开发者可以在JIRA上认领小的BUG修复,也可以在开发者指南页面领取大的功能模块?nbsp;

    JIRA?a target="_blank" style="color: #006699; text-decoration: none;">//code.alibabatech.com/jira/browse/DUBBO(暂不可用) 

    开发者指南://alibaba.github.io/dubbo-doc-static/Developer+Guide-zh.htm

    Dubbo未来的发展计划?Top

    Dubbo的RPC框架已基本稳定,未来的重心会放在服务治理上,包括架构分析、监控统计、降级控制、流程协作等等?nbsp;

    可参见://alibaba.github.io/dubbo-doc-static/Roadmap-zh.htm


    ]]>搜索引擎选择?Elasticsearch与Solr - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/archive/2016/03/17/429700.html小马?/dc:creator>小马?/author>Thu, 17 Mar 2016 07:16:00 GMT//www.ot7t.com.cn/xiaomage234/archive/2016/03/17/429700.html//www.ot7t.com.cn/xiaomage234/comments/429700.html//www.ot7t.com.cn/xiaomage234/archive/2016/03/17/429700.html#Feedback0//www.ot7t.com.cn/xiaomage234/comments/commentRss/429700.html//www.ot7t.com.cn/xiaomage234/services/trackbacks/429700.html搜索引擎选型调研文

    Elasticsearch简?a target="_blank" style="margin: 0px; padding: 0px; color: #258fb8; text-decoration: none; outline-width: 0px;">*

    Elasticsearch是一?span style="margin: 0px; padding: 0px;">实时?span style="margin: 0px; padding: 0px;">分布式搜索和分析引擎。它可以帮助你用前所未有的速度去处理大规模数据?/span>

    它可以用?span style="margin: 0px; padding: 0px;">全文搜索?span style="margin: 0px; padding: 0px;">结构化搜索以?span style="margin: 0px; padding: 0px;">分析,当然你也可以将这三者进行组合?/span>

    Elasticsearch是一?span style="margin: 0px; padding: 0px;">建立在全文搜索引?Apache Lucene™ 基础上的搜索引擎,可以说Lucene是当今最先进,最高效的全功能开源搜索引擎框架?/span>

    但是Lucene只是一个框架,要充分利用它的功能,需要使用JAVA,并且在程序中集成Lucene。需要很多的学习了解,才能明白它是如何运行的,Lucene确实非常复杂?/p>

    Elasticsearch使用Lucene作为内部引擎,但是在使用它做全文搜索时,只需要使用统一开发好的API即可,而不需要了解其背后复杂的Lucene的运行原理?/p>

    当然Elasticsearch并不仅仅是Lucene这么简单,它不但包括了全文搜索功能,还可以进行以下工作:

    • 分布式实时文件存储,并将每一个字段都编入索引,使其可以被搜索?/p>

    • 实时分析的分布式搜索引擎?/p>

    • 可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据?/p>

    这么多的功能被集成到一台服务器上,你可以轻松地通过客户端或者任何你喜欢的程序语言与ES的RESTful API进行交流?/p>

    Elasticsearch?span style="margin: 0px; padding: 0px;">上手是非常简单的。它附带了很?span style="margin: 0px; padding: 0px;">非常合理的默认值,这让初学者很好地避免一上手就要面对复杂的理论,

    它安装好了就可以使用了,?span style="margin: 0px; padding: 0px;">很小的学习成本就可以变得很有生产力?/span>

    随着越学越深入,还可以利用Elasticsearch更多高级的功能,整个引擎可以很灵活地进行配置。可以根据自身需求来定制属于自己的Elasticsearch?/p>

    使用案例?/p>

    • 维基百科使用Elasticsearch来进行全文搜做并高亮显示关键词,以及提供search-as-you-type、did-you-mean等搜索建议功能?/p>

    • 英国卫报使用Elasticsearch来处理访客日志,以便能将公众对不同文章的反应实时地反馈给各位编辑?/p>

    • StackOverflow将全文搜索与地理位置和相关信息进行结合,以提供more-like-this相关问题的展现?/p>

    • GitHub使用Elasticsearch来检索超?300亿行代码?/p>

    • 每天,Goldman Sachs使用它来处理5TB数据的索引,还有很多投行使用它来分析股票市场的变动?/p>

    但是Elasticsearch并不只是面向大型企业的,它还帮助了很多类似DataDog以及Klout的创业公司进行了功能的扩展?/p>

    Elasticsearch的优缺点**:

    优点

    1. Elasticsearch是分布式的。不需要其他组件,分发是实时的,被叫做”Push replication”?/li>
    2. Elasticsearch 完全支持 Apache Lucene 的接近实时的搜索?/li>
    3. 处理多租户(multitenancy)不需要特殊配置,而Solr则需要更多的高级设置?/span>
    4. Elasticsearch 采用 Gateway 的概念,使得完备份更加简单?/li>
    5. 各节点组成对等的网络结构,某些节点出现故障时会自动分配其他节点代替其进行工作?/li>

    缺点

    1. 只有一名开发者(当前Elasticsearch GitHub组织已经不只如此,已经有了相当活跃的维护者)
    2. 还不够自动(不适合当前新的Index Warmup API?/li>

    Solr简?a target="_blank" style="margin: 0px; padding: 0px; color: #258fb8; text-decoration: none; outline-width: 0px;">*

    Solr(读?#8220;solar”)是Apache Lucene项目的开源企业搜索平台。其主要功能包括全文检索?span style="margin: 0px; padding: 0px;">命中标示?span style="margin: 0px; padding: 0px;">分面搜索?span style="margin: 0px; padding: 0px;">动态聚类?span style="margin: 0px; padding: 0px;">数据库集成,以及富文本(如Word、PDF)的处理。Solr?span style="margin: 0px; padding: 0px;">高度可扩展的,并提供?span style="margin: 0px; padding: 0px;">分布式搜索和索引复制。Solr?span style="margin: 0px; padding: 0px;">最流行的企业级搜索引擎,Solr4 还增加了NoSQL支持?/span>

    Solr是用Java编写、运行在Servlet容器(如 Apache Tomcat 或Jetty)的一个独立的全文搜索服务器?Solr采用?Lucene Java 搜索库为核心的全文索引和搜索,并具有类似REST的HTTP/XML和JSON的API。Solr强大的外部配置功能使得无需进行Java编码,便可对 其进行调整以适应多种类型的应用程序。Solr有一个插件架构,以支持更多的高级定制?/p>

    因为2010?Apache Lucene ?Apache Solr 项目合并,两个项目是由同一个Apache软件基金会开发团队制作实现的。提到技术或产品时,Lucene/Solr或Solr/Lucene是一样的?/p>

    Solr的优缺点

    优点

    1. Solr有一个更大、更成熟的用户、开发和贡献者社区?/li>
    2. 支持添加多种格式的索引,如:HTML、PDF、微?Office 系列软件格式以及 JSON、XML、CSV 等纯文本格式?/li>
    3. Solr比较成熟、稳定?/li>
    4. 不考虑建索引的同时进行搜索,速度更快?/li>

    缺点

    1. 建立索引时,搜索效率下降,实时索引搜索效率不高?/li>

    Elasticsearch与Solr的比?a target="_blank" style="margin: 0px; padding: 0px; color: #258fb8; text-decoration: none; outline-width: 0px;">*

    当单纯的对已有数据进行搜索时,Solr更快?/p>

    Search Fesh Index While Idle

    当实时建立索引时, Solr会产生io阻塞,查询性能较差, Elasticsearch具有明显的优势?/p>

    search_fresh_index_while_indexing

    随着数据量的增加,Solr的搜索效率会变得更低,而Elasticsearch却没有明显的变化?/p>

    search_fresh_index_while_indexing

    综上所述,Solr的架构不适合实时搜索的应用?/p>

    实际生产环境测试*

    下图为将搜索引擎从Solr转到Elasticsearch以后的平均查询速度有了50倍的提升?/p>

    average_execution_time

    Elasticsearch ?Solr 的比较总结

    • 二者安装都很简单;
    • Solr 利用 Zookeeper 进行分布式管理,?Elasticsearch 自身带有分布式协调管理功?
    • Solr 支持更多格式的数据,?Elasticsearch 仅支持json文件格式?/li>
    • Solr 官方提供的功能更多,?Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供?/li>
    • Solr 在传统的搜索应用中表现好?Elasticsearch,但在处理实时搜索应用时效率明显低于 Elasticsearch?/li>

    Solr 是传统搜索应用的有力解决方案,但 Elasticsearch 更适用于新兴的实时搜索应用?/p>

    其他基于Lucene的开源搜索引擎解决方?a target="_blank" style="margin: 0px; padding: 0px; color: #258fb8; text-decoration: none; outline-width: 0px;">*

    1. 直接使用 Lucene

    说明:Lucene 是一?JAVA 搜索类库,它本身并不是一个完整的解决方案,需要额外的开发工作?/p>

    优点:成熟的解决方案,有很多的成功案例。apache 顶级项目,正在持续快速的进步。庞大而活跃的开发社区,大量的开发人员。它只是一个类库,有足够的定制和优化空间:经过简单定制,就可以满足绝大部分常见的需求;经过优化,可以支?10? 量级的搜索?/p>

    缺点:需要额外的开发工作。所有的扩展,分布式,可靠性等都需要自己实现;非实时,从建索引到可以搜索中间有一个时间延迟,而当前的“近实?#8221;(Lucene Near Real Time search)搜索方案的可扩展性有待进一步完?/p>

    说明:基?Lucene 的,支持分布式,可扩展,具有容错功能,准实时的搜索方案?/p>

    优点:开箱即用,可以?Hadoop 配合实现分布式。具备扩展和容错机制?/p>

    缺点:只是搜索方案,建索引部分还是需要自己实现。在搜索功能上,只实现了最基本的需求。成功案例较少,项目的成熟度稍微差一些。因为需要支持分布式,对于一些复杂的查询需求,定制的难度会比较大?/p>

    说明:Map/Reduce 模式的,分布式建索引方案,可以跟 Katta 配合使用?/p>

    优点:分布式建索引,具备可扩展性?/p>

    缺点:只是建索引方案,不包括搜索实现。工作在批处理模式,对实时搜索的支持不佳?/p>

    说明:基?Lucene 的一系列解决方案,包?准实时搜?zoie ,facet 搜索实现 bobo ,机器学习算?decomposer ,摘要存储库 krati ,数据库模式包装 sensei 等等

    优点:经过验证的解决方案,支持分布式,可扩展,丰富的功能实现

    缺点:与 linkedin 公司的联系太紧密,可定制性比较差

    说明:基?Lucene,索引存?cassandra 数据库中

    优点:参?cassandra 的优?/p>

    缺点:参?cassandra 的缺点。另外,这只是一?demo,没有经过大量验?/p>

    说明:基?Lucene,索引存?HBase 数据库中

    优点:参?HBase 的优?/p>

    缺点:参?HBase 的缺点。另外,在实现中,lucene terms 是存成行,但每个 term 对应?posting lists 是以列的方式存储的。随着单个 term ?posting lists 的增大,查询时的速度受到的影响会非常?/p>

     

    转载://blog.csdn.net/jameshadoop/article/details/44905643



    ]]>
    快的打车架构实践 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/archive/2016/03/11/429621.html小马?/dc:creator>小马?/author>Fri, 11 Mar 2016 06:57:00 GMT//www.ot7t.com.cn/xiaomage234/archive/2016/03/11/429621.html//www.ot7t.com.cn/xiaomage234/comments/429621.html//www.ot7t.com.cn/xiaomage234/archive/2016/03/11/429621.html#Feedback0//www.ot7t.com.cn/xiaomage234/comments/commentRss/429621.html//www.ot7t.com.cn/xiaomage234/services/trackbacks/429621.html阅读全文

    ]]>
    JVM致命错误日志(hs_err_pid.log)解?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2016/03/02/429509.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Wed, 02 Mar 2016 07:00:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2016/03/02/429509.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/429509.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2016/03/02/429509.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/429509.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/429509.html</trackback:ping><description><![CDATA[<div id="postbody" style="font-family: Simsun; font-size: medium; line-height: normal;"><div class="yibqv"><div class="yibqv"><p>致命错误出现的时候,JVM生成了hs_err_pid<pid>.log这样的文件,其中往往包含了虚拟机崩溃原因的重要信息。因为经常遇 到,在这篇文章里,我挑选了一个,并且逐段分析它包含的内容(文件可以在文章最后下载)。默认情况下文件是创建在工作目录下的(如果没权限创建的话JVM 会尝试把文件写到/tmp这样的临时目录下面去),当然,文件格式和路径也可以通过参数指定,比如:</p><ol><li class="yibqv">java -XX:ErrorFile=/var/log/java/java_error%p.log </li></ol><p>这个文件将包括:</p><ul class="yibqv"><li class="yibqv">触发致命错误的操作异常或者信号;</li><li class="yibqv">版本和配置信息;</li><li class="yibqv">触发致命异常的线程详细信息和线程栈;</li><li class="yibqv">当前运行的线程列表和它们的状态;</li><li class="yibqv">堆的总括信息?/li><li class="yibqv">加载的本地库?/li><li class="yibqv">命令行参数;</li><li class="yibqv">环境变量?/li><li class="yibqv">操作系统CPU的详细信息?/li></ul><p>首先,看到的是对问题的概要介绍:</p><ol><li class="yibqv">#  SIGSEGV (0xb) at pc=0x03568cf4, pid=16819, tid=3073346448 </li></ol><p>一个非预期的错误被JRE检测到,其中:</p><ul class="yibqv"><li class="yibqv">SIGSEGV是信号名?/li><li class="yibqv">0xb是信号码</li><li class="yibqv">pc=0x03568cf4指的是程序计数器的?/li><li class="yibqv">pid=16819是进程号</li><li class="yibqv">tid=3073346448是线程号</li></ul><p>如果你对JVM有了解,应该不会对这些东西陌生?/p><p>接下来是JRE和JVM的版本信息:</p><ol><li class="yibqv"># JRE version: 6.0_32-b05 </li><li class="yibqv">  </li><li class="yibqv"># Java VM: Java HotSpot(TM) Server VM (20.7-b02 mixed mode linux-x86 ) </li></ol><p>运行在mixed模式下?/p><p>然后是问题帧的信息:</p><ol><li class="yibqv"># Problematic frame: </li><li class="yibqv">  </li><li class="yibqv"># C  [libgtk-x11-2.0.so.0+0x19fcf4]  __float128+0x19fcf4 </li></ol><ul class="yibqv"><li class="yibqv">C:帧类型为本地帧,帧的类型包括: <br /><ul class="yibqv"><li class="yibqv">C:本地C?/li><li class="yibqv">j:解释的Java?/li><li class="yibqv">V:虚拟机?/li><li class="yibqv">v:虚拟机生成的存根栈?/li><li class="yibqv">J:其他帧类型,包括编译后的Java?/li></ul></li><li class="yibqv">libgtk-x11-2.0.so.0+0x19fcf4:和程序计数器(pc)表达的含义一样,但是用的是本地so?偏移量的方式?/li></ul><p>接下去第一部分是线程信息:</p><ol><li class="yibqv">Current thread (0x09f30c00):  JavaThread "main" [_thread_in_native, id=16822, stack(0xb72a8000,0xb72f9000)] </li></ol><p>当前线程的:</p><ul class="yibqv"><li class="yibqv">0x09f30c00:指?/li><li class="yibqv">JavaThread:线程类型,可能的类型包括: <br /><ul class="yibqv"><li class="yibqv">JavaThread</li><li class="yibqv">VMThread</li><li class="yibqv">CompilerThread</li><li class="yibqv">GCTaskThread</li><li class="yibqv">WatcherThread</li><li class="yibqv">ConcurrentMarkSweepThread</li></ul></li><li class="yibqv">main:名?nbsp;<br /><ul class="yibqv"><li class="yibqv">_thread_in_native:线程当前状态,状态枚举包括:</li><li class="yibqv">_thread_uninitialized:线程还没有创建,它只在内存原因崩溃的时候才出现</li><li class="yibqv">_thread_new:线程已经被创建,但是还没有启动</li><li class="yibqv">_thread_in_native:线程正在执行本地代码,一般这种情况很可能是本地代码有问题</li><li class="yibqv">_thread_in_vm:线程正在执行虚拟机代码</li><li class="yibqv">_thread_in_Java:线程正在执行解释或者编译后的Java代码</li><li class="yibqv">_thread_blocked:线程处于阻塞状?/li><li class="yibqv">…_trans:以_trans结尾,线程正处于要切换到其它状态的中间状?/li></ul></li><li class="yibqv">id=16822:线程ID</li><li class="yibqv">0xb72a8000,0xb72f9000:栈区间</li></ul><ol><li class="yibqv">siginfo:si_signo=SIGSEGV: si_errno=0, si_code=1 (SEGV_MAPERR), si_addr=0x00000010 </li></ol><p>这部分是导致虚拟机终止的非预期的信号信息,含义前面已经大致提到过了。其中si_errno和si_code是Linux下用来鉴别异常的,Windows下是一个ExceptionCode?/p><ol><li class="yibqv">EAX=0x00000000, EBX=0x0375dd84, ECX=0x00000000, EDX=0x00000000 </li><li class="yibqv">ESP=0xb72f0fa0, EBP=0xb72f0fb8, ESI=0x00000000, EDI=0x0a6c1800 </li><li class="yibqv">EIP=0x03568cf4, EFLAGS=0x00010246, CR2=0x00000010 </li></ol><p>这是寄存器上下文?/p><p> </p><ol><li class="yibqv">Top of Stack: (sp=0xb72f0fa0) </li><li class="yibqv">0xb72f0fa0:   00000000 00402250 0040217f 0375dd84 </li><li class="yibqv">0xb72f0fb0:   00000000 0a6c1800 b72f0fe8 0356c2c0 </li><li class="yibqv">0xb72f0fc0:   00000000 0a6c1800 b72f0fe8 003b3e77 </li><li class="yibqv">0xb72f0fd0:   003e6c8b 0a1a70d0 0a193358 0375dd84 </li><li class="yibqv">0xb72f0fe0:   0a276418 0a276418 b72f1048 03536c56 </li><li class="yibqv">0xb72f0ff0:   0acad000 0b3ca978 0000000c 00dd0674 </li><li class="yibqv">0xb72f1000:   00000003 0a2c7d50 b72f1038 0000330c </li><li class="yibqv">0xb72f1010:   ffffffff ffffffff 00000001 00000001 </li><li class="yibqv">  </li><li class="yibqv">Instructions: (pc=0x03568cf4) </li><li class="yibqv">0x03568cd4:   89 14 24 89 75 f8 89 d6 89 7d fc 89 c7 e8 7e 1b </li><li class="yibqv">0x03568ce4:   ea ff 89 34 24 89 87 d4 02 00 00 e8 30 00 ea ff </li><li class="yibqv">0x03568cf4:   8b 40 10 89 3c 24 c7 44 24 08 00 00 00 00 89 87 </li><li class="yibqv">0x03568d04:   d0 02 00 00 8b 83 88 24 00 00 89 44 24 04 e8 dd </li></ol><p>栈顶程序计数器旁的操作码,它们可以被反汇编成系统崩溃前执行的指令?/p><ol><li class="yibqv">Register to memory mapping: </li><li class="yibqv">  </li><li class="yibqv">EAX=0x00000000 is an unknown value </li><li class="yibqv">EBX=0x0375dd84: <offset 0x394d84> in /usr/lib/libgtk-x11-2.0.so.0 at 0x033c9000 </li><li class="yibqv">ECX=0x00000000 is an unknown value </li><li class="yibqv">EDX=0x00000000 is an unknown value </li><li class="yibqv">ESP=0xb72f0fa0 is pointing into the stack for thread: 0x09f30c00 </li><li class="yibqv">EBP=0xb72f0fb8 is pointing into the stack for thread: 0x09f30c00 </li><li class="yibqv">ESI=0x00000000 is an unknown value </li><li class="yibqv">EDI=0x0a6c1800 is an unknown value </li></ol><p>寄存器和内存映射信息?/p><ol><li class="yibqv">Stack: [0xb72a8000,0xb72f9000],  sp=0xb72f0fa0,  free space=291k </li><li class="yibqv">Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) </li><li class="yibqv">C  [libgtk-x11-2.0.so.0+0x19fcf4]  __float128+0x19fcf4 </li><li class="yibqv">C  [libgtk-x11-2.0.so.0+0x1a32c0]  __float128+0xc0 </li><li class="yibqv">... ... </li><li class="yibqv">C  [libswt-pi-gtk-3738.so+0x33f6a]  Java_org_eclipse_swt_internal_gtk_OS__1Call+0xf </li><li class="yibqv">J  org.eclipse.swt.internal.gtk.OS._Call(III)I </li><li class="yibqv">J  org.eclipse.swt.internal.gtk.OS.Call(III)I </li><li class="yibqv">  </li><li class="yibqv">Java frames: (J=compiled Java code, j=interpreted, Vv=VM code) </li><li class="yibqv">J  org.eclipse.swt.internal.gtk.OS._Call(III)I </li><li class="yibqv">J  org.eclipse.swt.internal.gtk.OS.Call(III)I </li><li class="yibqv">j  org.eclipse.swt.widgets.Widget.fixedSizeAllocateProc(II)I+5 </li><li class="yibqv">j  org.eclipse.swt.widgets.Display.fixedSizeAllocateProc(II)I+17 </li><li class="yibqv">v  ~StubRoutines::call_stub </li></ol><p>线程栈。包含了地址、栈顶、栈计数器和线程尚未使用的栈信息,由于栈可能非常长,打印的长度有限制,但是至少本地栈和Java栈都打印出来了(很多时候本地栈打印不出来,但是Java栈一般都能打印出来)。从中可以看到,Eclipse的虚拟机崩溃了?/p><ol><li class="yibqv">ava Threads: ( => current thread ) </li><li class="yibqv">  0x0b4c1000 JavaThread "Worker-247" [_thread_blocked, id=25417, stack(0x741bc000,0x7420d000)] </li><li class="yibqv">  0x0a300c00 JavaThread "Worker-246" [_thread_blocked, id=25235, stack(0x7d30c000,0x7d35d000)] </li><li class="yibqv">... ... </li></ol><p>线程信息。一目了然,不解释了?/p><ol><li class="yibqv">VM state:not at safepoint (normal execution) </li></ol><p>虚拟机状态。包括:</p><ul class="yibqv"><li class="yibqv">not at a safepoint:正常运行状态;</li><li class="yibqv">at safepoint:所有线程都因为虚拟机等待状态而阻塞,等待一个虚拟机操作完成?/li><li class="yibqv">synchronizing:一个特殊的虚拟机操作,要求虚拟机内的其它线程保持等待状态?/li></ul><ol><li class="yibqv">VM Mutex/Monitor currently owned by a thread: None </li></ol><p>虚拟机的Mutex和Monitor目前没有被线程持有。Mutex是虚拟机内部的锁,而Monitor则关联到了Java对象?/p><ol><li class="yibqv">Heap </li><li class="yibqv"> PSYoungGen      total 149056K, used 125317K [0xa9700000, 0xb41a0000, 0xb41a0000) </li><li class="yibqv">  eden space 123520K, 95% used [0xa9700000,0xb0ac0de0,0xb0fa0000) </li><li class="yibqv">  from space 25536K, 26% used [0xb28b0000,0xb2f50748,0xb41a0000) </li><li class="yibqv">  to   space 25600K, 0% used [0xb0fa0000,0xb0fa0000,0xb28a0000) </li><li class="yibqv"> PSOldGen        total 261248K, used 239964K [0x941a0000, 0xa40c0000, 0xa9700000) </li><li class="yibqv">  object space 261248K, 91% used [0x941a0000,0xa2bf7018,0xa40c0000) </li><li class="yibqv"> PSPermGen       total 163328K, used 130819K [0x841a0000, 0x8e120000, 0x941a0000) </li><li class="yibqv">  object space 163328K, 80% used [0x841a0000,0x8c160c40,0x8e120000) </li></ol><p>堆信息。新生代、老生代、永久代。对JVM有了解的人应该都清楚,不解释了?/p><ol><li class="yibqv">Code Cache  [0xb4262000, 0xb5ac2000, 0xb7262000) </li><li class="yibqv"> total_blobs=5795 nmethods=5534 adapters=209 free_code_cache=25103616 largest_free_block=38336 </li></ol><p>代码缓存(Code Cache)。这是一块用于编译和保存本地代码的内存,注意是本地代码,它和PermGen(永久代)是不一样的,永久带是用来存放Java类定义的?/p><ol><li class="yibqv">Dynamic libraries: </li><li class="yibqv">00101000-00122000 r-xp 00000000 08:01 3483560    /usr/lib/libjpeg.so.62.0.0 </li><li class="yibqv">00122000-00123000 rwxp 00020000 08:01 3483560    /usr/lib/libjpeg.so.62.0.0 </li><li class="yibqv">00125000-00130000 r-xp 00000000 08:01 9093202    /lib/libgcc_s-4.1.2-20080825.so.1 </li><li class="yibqv">00130000-00131000 rwxp 0000a000 08:01 9093202    /lib/libgcc_s-4.1.2-20080825.so.1 </li><li class="yibqv">... ... </li></ol><p>内存映射。这些信息是虚拟机崩溃时的虚拟内存列表区域。在定位崩溃原因的时候,它可以告诉你哪些类库正在被使用,位置在哪里,还有堆栈和守护页信息。就以列表中第一条为例说明:</p><ul class="yibqv"><li class="yibqv">00101000-00122000:内存区?/li><li class="yibqv">r-xp:权限,r/w/x/p/s分别表示??执行/私有/共享</li><li class="yibqv">00000000:文件内的偏移量</li><li class="yibqv">08:01:文件位置的majorID和minorID</li><li class="yibqv">3483560:索引节点号</li><li class="yibqv">/usr/lib/libjpeg.so.62.0.0:文件位?/li></ul><p>每一个lib都有两块虚拟内存区域——代码和数据,它们的权限不同,代码区域是r-xp;数据区域是rwxp。守护页(guard page)由权限?-xp和rwxp的一对组成?/p><ol><li class="yibqv">VM Arguments: </li><li class="yibqv">jvm_args: -Dosgi.requiredJavaVersion=1.5 -XX:MaxPermSize=256m -Xms40m -Xmx512m -Dorg.eclipse.swt.browser.XULRunnerPath='' </li><li class="yibqv">java_command: /.../eclipse/plugins/org.eclipse.equinox.launcher_1.2.0.v20110502.jar -os linux -ws gtk -arch x86 -showsplash -launcher /.../eclipse/eclipse -name Eclipse ... </li><li class="yibqv">Launcher Type: SUN_STANDARD </li><li class="yibqv">  </li><li class="yibqv">Environment Variables: </li><li class="yibqv">PATH=... </li><li class="yibqv">DISPLAY=:0.0 </li></ol><p>虚拟机参数和环境变量?/p><ol><li class="yibqv">Signal Handlers: </li><li class="yibqv">SIGSEGV: [libjvm.so+0x726440], sa_mask[0]=0x7ffbfeff, sa_flags=0x10000004 </li><li class="yibqv">SIGBUS: [libjvm.so+0x726440], sa_mask[0]=0x7ffbfeff, sa_flags=0x10000004 </li><li class="yibqv">... ... </li></ol><p>信号句柄。对于Linux下的信号机制,参阅wiki百科?nbsp;<a target="_blank">链接</a>?/p><p> </p><ol><li class="yibqv">OS:Red Hat Enterprise Linux Client release 5.4 (Tikanga) </li><li class="yibqv">  </li><li class="yibqv">uname:Linux 2.6.18-164.el5 #1 SMP Tue Aug 18 15:51:54 EDT 2009 i686 </li><li class="yibqv">libc:glibc 2.5 NPTL 2.5 </li><li class="yibqv">rlimit: STACK 10240k, CORE 0k, NPROC 65536, NOFILE 1024, AS infinity </li><li class="yibqv">load average:1.78 1.58 1.54 </li><li class="yibqv">  </li><li class="yibqv">/proc/meminfo: </li><li class="yibqv">... </li><li class="yibqv">  </li><li class="yibqv">CPU:total 4 (4 cores per cpu, 1 threads per core) family 6 model 42 stepping 7, cmov, cx8, fxsr, mmx, sse, sse2, sse3, ssse3 </li><li class="yibqv">  </li><li class="yibqv">/proc/cpuinfo: </li><li class="yibqv">... </li><li class="yibqv">  </li><li class="yibqv">Memory: 4k page, physical 3631860k(155144k free), swap 5124724k(5056452k free) </li></ol></div><br /><br /><a >已有 <strong class="yibqv">0</strong> 人发表留言,猛?>> <strong class="yibqv">这里</strong><<-参与讨论</a> <br /><br /><br />ITeye推荐 <br /><ul class="yibqv"><li class="yibqv"><a target="_blank">—软件人才免语言低担?赴美带薪读研?#8212;</a></li></ul><br /><br /></div></div><div style="font-family: Simsun; font-size: medium; line-height: normal;"><h3>相关 [jvm 错误 日志] 推荐?/h3><div class="yibqv"><h2 class="yibqv"><a title="JVM致命错误日志(hs_err_pid.log)解? >JVM致命错误日志(hs_err_pid.log)解?/a></h2>- - 四火的唠?div>文章系本人原创,转载请保持完整性并注明出自 《四火的唠叨? 致命错误出现的时候,JVM生成了hs_err_pid<pid>.log这样的文件,其中往往包含了虚拟机崩溃原因的重要信? 因为经常遇到,在这篇文章里,我挑选了一个,并且逐段分析它包含的内容(文件可以在文章最后下载). 默认情况下文件是创建在工作目录下的(如果没权限创建的话JVM会尝试把文件写到/tmp这样的临时目录下面去),当然,文件格式和路径也可以通过参数指定,比如:.</div></div><div class="yibqv"><h2 class="yibqv"><a title="Fatal Error log format,JVM 致命错误日志格式" >Fatal Error log format,JVM 致命错误日志格式</a></h2>- - 码蜂笔记<div class="yibqv">本文翻译自: //www.oracle.com/technetwork/java/javase/felog-138657.html. 本文内容基于 Java SE 6,HotSpot JVM. 当一个致命错误发生时,一个错误日志将被创建,存储了在致命错误发生时获取到的信息和状? 注意:这个文件的格式可能随着版本的更新而改?</div></div><div class="yibqv"><h2 class="yibqv"><a title="JVM日志和参数的理解" >JVM日志和参数的理解</a></h2>- - 开源软?- ITeye博客<div class="yibqv">转自://hot66hot.iteye.com/blog/2075819. 写这篇wiki的目?最近在调整Hbase的JVM,翻了些文?和wiki,想写点东?给自己和想了解jvm日志和参数的?学提供些帮助..  一:理解GC日志格式,读GC日志的方? -XX:+UseGCLogFileRotation  启用GC日志文件的自动转?(Since Java).</div></div><div class="yibqv"><h2 class="yibqv"><a title="通过JVM日志来进行安全点分析" >通过JVM日志来进行安全点分析</a></h2>- - 并发编程?- ifeve.com<div class="yibqv">原文链接 作? Plumbr 译者:之诸? 许多事件都可能会导致JVM暂停所有的应用线程. 这类暂停又被称为”stop-the-world”(STW)暂? 触发STW暂停最常见的原因就是垃圾回收了?github中的一个例子),但不同的JIT活动( 例子),偏向锁擦除?例子), 特定的JVMTI操作,以及许多场景也可能会导致应用程序暂?</div></div><div class="yibqv"><h2 class="yibqv"><a title="【体系结构】MySQL 日志文件--错误日志" >【体系结构】MySQL 日志文件--错误日志</a></h2>- - CSDN博客数据库推荐文?div>        记录MySQL Server 启动和关闭的详细信息、以及运行过程中较为严重的警告和错误信息.        为了维护方便需要、有时候会希望将错误日志中的内容做备份并重新开始记录、那么可以:.         MySQL DBA 在遇到问题时应该首先查看该文?         当出?MySQL Server 不能正常启动时、第一个拷问的重点对象应该就是此人.</div></div><div class="yibqv"><h2 class="yibqv"><a title="Oracle GoldenGate 监控工具:ggserr.log 错误日志不可忽视" >Oracle GoldenGate 监控工具:ggserr.log 错误日志不可忽视</a></h2>- - CSDN博客推荐文章<div class="yibqv">Oracle 原厂最近在生产环境的主数据库安装了 OEM 12C 的监控插件后,主数据库对外十几个库同步同步的. Oracle GoldenGate 实例出现异常,疯狂地往 GoldenGate 根目录的 ggserr.log 输入出如下错误日志:. 2013-02-22 22:33:26  WARNING OGG-01930  Oracle GoldenGate Capture for Oracle, pcqstqz1.prm:  Datastore error in 'dirbdb': BDB0060 PANIC: fatal region error detected; run recovery.</div></div><div class="yibqv"><h2 class="yibqv"><a title="JVM研究" >JVM研究</a></h2>- - 开源软?- ITeye博客<div class="yibqv">每天接客户的电话都是战战兢兢的,生怕再出什么幺蛾子? 我想Java做的久一点的都有这样的经历,那这些问题的最终根结是在哪? JVM全称是Java Virtual Machine,Java虚拟机,也就是在计算机上再虚拟一个计算机,这和我们使?VMWare不一样,那个虚拟的东西你是可以看到的,这个JVM你是看不到的,它存在内存?</div></div><div class="yibqv"><h2 class="yibqv"><a title="学习JVM的References" >学习JVM的References</a></h2>- LightingMan - 淘宝JAVA中间件团队博?div>本blog中列举了我学习JVM的references,会不断的更新,为了避免版权问题,就不在blog上提供references的下载了,感兴趣的同学可自行下载或购买,:). |— [ Hotspot GC论文 ]. |— [ 其他JVM GC ]. |— Linux内核源代码情景分? |— Linux 内核中断内幕.</div></div><div class="yibqv"><h2 class="yibqv"><a title="深入理解JVM" >深入理解JVM</a></h2>- 小伟 - ITeye论坛最新讨?div>1   Java技术与Java虚拟? 说起Java,人们首先想到的是Java编程语言,然而事实上,Java是一种技术,它由四方面组? Java编程语言、Java类文件格式、Java虚拟机和Java应用程序接口(Java API). ?   Java四个方面的关? 运行期环境代表着Java平台,开发人员编写Java代码(.java文件),然后将之编译成字节?.class文件).</div></div></div><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/429509.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2016-03-02 15:00 <a href="//www.ot7t.com.cn/xiaomage234/archive/2016/03/02/429509.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring中循环引用的处理-1【转?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2016/01/27/429226.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Wed, 27 Jan 2016 06:09:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2016/01/27/429226.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/429226.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2016/01/27/429226.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/429226.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/429226.html</trackback:ping><description><![CDATA[     摘要: 2012/08/28 09:49:49 No CommentsTags: bean, earlySingletonObjects, getBean, recycle reference, singletonFactories, spring, 源码分析   Posted :java开? ...  <a href='//www.ot7t.com.cn/xiaomage234/archive/2016/01/27/429226.html'>阅读全文</a><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/429226.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2016-01-27 14:09 <a href="//www.ot7t.com.cn/xiaomage234/archive/2016/01/27/429226.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Dubbo学习过程、使用经验分享及实现原理简单介?/title><link>//www.ot7t.com.cn/xiaomage234/archive/2016/01/26/429219.html</link><dc:creator>小马?/dc:creator><author>小马?/author><pubDate>Tue, 26 Jan 2016 09:58:00 GMT</pubDate><guid>//www.ot7t.com.cn/xiaomage234/archive/2016/01/26/429219.html</guid><wfw:comment>//www.ot7t.com.cn/xiaomage234/comments/429219.html</wfw:comment><comments>//www.ot7t.com.cn/xiaomage234/archive/2016/01/26/429219.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>//www.ot7t.com.cn/xiaomage234/comments/commentRss/429219.html</wfw:commentRss><trackback:ping>//www.ot7t.com.cn/xiaomage234/services/trackbacks/429219.html</trackback:ping><description><![CDATA[     摘要: 原文见://blog.csdn.net/hzzhoushaoyu/article/details/43273099一、前言部门去年年中开始各种改造,第一步是模块服务化,这边初选dubbo试用在一些非重要模块上,慢慢引入到一些稍微重要的功能上,半年时间,学习过程及线上使用遇到的些问题在此总结下。整理这篇文章差不多花了两天半时间,请尊重劳动成果,如转载请注明出处//blog.csd...  <a href='//www.ot7t.com.cn/xiaomage234/archive/2016/01/26/429219.html'>阅读全文</a><img src ="//www.ot7t.com.cn/xiaomage234/aggbug/429219.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="//www.ot7t.com.cn/xiaomage234/" target="_blank">小马?/a> 2016-01-26 17:58 <a href="//www.ot7t.com.cn/xiaomage234/archive/2016/01/26/429219.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Gradle命令行黑魔法 - 四川福利彩票快乐12快乐12开奖直播快乐12开奖辽宁福彩快乐12快乐彩12选5走势图//www.ot7t.com.cn/xiaomage234/archive/2016/01/20/429130.html小马?/dc:creator>小马?/author>Wed, 20 Jan 2016 06:46:00 GMT//www.ot7t.com.cn/xiaomage234/archive/2016/01/20/429130.html//www.ot7t.com.cn/xiaomage234/comments/429130.html//www.ot7t.com.cn/xiaomage234/archive/2016/01/20/429130.html#Feedback0//www.ot7t.com.cn/xiaomage234/comments/commentRss/429130.html//www.ot7t.com.cn/xiaomage234/services/trackbacks/429130.html毫无疑问,现在Gradle已经成为java世界最火的构建工具,风头已经盖过了冗余的ant,落后的maven。Gradle是以Groovy语言编写的一套构建脚本的DSL,由于Groovy语法的优雅,所以导致Gradle天生就有简洁、可读性强、灵活等特性?/p>

    Gradle的命令行功能也非常强大。本人从maven转到Gradle,深深被gradle强大的命令行功能折服。通过命令行来实现Gradle的各种特性,就像魔法师在表演魔法一样?/p>more

    • 日志输出?/strong> Gradle中的日志?个层级。从高到低分别是 ERROR(错误信息)、QUIET(重要信息)、WARNGING(警告信息)、LIFECYCLE(进程信息)、INFO(一般信息)、DEBUG(调试信息)。在执行gradle task时可以适时的调整信息输出等级,以便更方便的观看执行结果?/li>

    -i(?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">--info)则会输出除debug以外的所有信息?/p>

    -d(或--debug)会输出所有日志信息?/p>

    比如一个build.gradle有这样一个task?/p>

    task hello << {      println 'hello world!' }

    加入-q与不?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">-q的输出结果不同?/p>

    $ gradle hello :hello hello world!  BUILD SUCCESSFUL  Total time: 3.546 secs $ gradle -q hello hello world!
    • 堆栈跟踪?/strong>如果执行gradle task失败时,如果想得到更详细的错误信息,那么就可以使?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">-s(?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">--stacktrace)来输出详细的错误堆栈。你还可以使?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">-S(?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">--full-stacktrace)来输出全部堆栈信息,不过一般不推荐这样做,因为gradle是基于groovy语言,而groovy作为一门动态语言可能会输出与你的错误代码毫不相关的信息?/p>

    • 跳过指定的测试?/strong>如果你在执行build的时候想跳过test task,那么可以使?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">-x命令?/p>

    $ gradle build -x test :compileJava UP-TO-DATE :processResources UP-TO-DATE :classes UP-TO-DATE :jar UP-TO-DATE :assemble UP-TO-DATE :check :build  BUILD SUCCESSFUL  Total time: 3.529 secs
    • 继续执行task而忽略前面失败的task?/strong>默认情况下,如果有某个task失败,后续的task就不会继续执行。但是有时候我们想运行所有的task来一次性得到所有的构建错误,那么我们可以使?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">--continue命令。使?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">--continue命令后即使遇到某些task失败也不会停止后续task的执行。但是需要注意的是如果某个task失败了,那么依赖于这个task的其他task依旧不会执行,因为这会带来不安全的因素?/p>

    • 调用task时使用短名或缩写?/strong>如果一个task的名称过长,那么调用时可以只输入部分名称即可调用,无需输入全名?/p>

    task helloWorld << {      println 'hello world!' }

    比如调用helloWorld可以通过全名调用、前缀调用或首字母调用?/p>

    $ gradle -q helloWorld hello world! $ gradle -q hell hello world! $ gradle -q hW hello world!
    • 使用指定的gradle文件调用task?/strong>默认情况下,如果你调用gradle task,那么首先会寻找当前目录下的build.gradle文件,以及根据settings.gradle中的配置寻找子项目的build.gradle。但是有时候我们想指定使用某个gradle文件,那么可以使?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">-b命令?比如当前目录有个子目录subproject1,里面有个叫hello.gradle?/li>
    task helloWorld << {      println 'hello world!' }

    那么在当前目录可以使用以下命令调用这个task?/p>

    $ gradle -b subproject1/hello.gradle  helloWorld :helloWorld hello world!  BUILD SUCCESSFUL  Total time: 3.752 secs
    • 使用指定的项目目录调用task?/strong>前面已经说过,执行gradle的task默认会在当前目录寻找build.gradle及settings.gradle文件。如果我们想在任何地方执行某个项目的task,那么可以使?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">-p来指定使用的项目?/li>
    gradle -q -p learnGradle helloWorld

    这条命令是调用learnGradle这个项目下的helloWorld task?/p>

    • 显示task之间的依赖关系?/strong>众所周知,使?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">gradle tasks可以列出当前所有可被使用的task,但是并没有显示task之间的依赖关系。我们可以加?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">--all来显?task的依赖关系?/li>
    $ gradle tasks --all ………………  Other tasks ----------- task0     task1     task2     task3  …………
    从上面可以看出task0依赖task1、task2及task3?/code>
    • 查看指定阶段的依赖关系?/strong>使用gradle dependencies 可以查看项目中包的依赖关系。不过是列出了所有阶段的依赖,如果项目中依赖复杂的话看起来有点头痛。那么可以使?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">--configuration来查看指定阶段的依赖情况?/li>
    $ gradle -q dependencies  ------------------------------------------------------------ Root project ------------------------------------------------------------  archives - Configuration for archive artifacts. No dependencies  compile - Compile classpath for source set 'main'. No dependencies  default - Configuration for default artifacts. No dependencies  runtime - Runtime classpath for source set 'main'. No dependencies  testCompile - Compile classpath for source set 'test'. \--- junit:junit:4.11      \--- org.hamcrest:hamcrest-core:1.3  testRuntime - Runtime classpath for source set 'test'. \--- junit:junit:4.11      \--- org.hamcrest:hamcrest-core:1.3

    使用gradle -q dependencies --configuration testCompile可以只查看testComiple的依赖?/p>

    $ gradle -q dependencies --configuration testCompile  ------------------------------------------------------------ Root project ------------------------------------------------------------  testCompile - Compile classpath for source set 'test'. \--- junit:junit:4.11      \--- org.hamcrest:hamcrest-core:1.3
    • 查看指定dependency的依赖情况?/strong> 假如我想查看项目中有没有引入junit,那些阶段引入了junit,那么可以使?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">dependecyInsight来查看?/li>
    $ gradle dependencyInsight --dependency junit --configuration testCompile :dependencyInsight junit:junit:4.11 \--- testCompile

    注意dependencyInsight默认只会查看compile阶段的依赖,如果要查看其他阶段可以使?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">--configuration来指定?/p>

    • 使用--profile命令行可以产生build运行时间的报告?/strong>该报告存储在build/report/profile目录,名称为build运行的时间?/li>
    $ gradle build --profile :compileJava UP-TO-DATE :processResources UP-TO-DATE :classes UP-TO-DATE :jar UP-TO-DATE :assemble UP-TO-DATE :compileTestJava UP-TO-DATE :processTestResources UP-TO-DATE :testClasses UP-TO-DATE :test UP-TO-DATE :check UP-TO-DATE :build UP-TO-DATE  BUILD SUCCESSFUL  Total time: 3.726 secs

    然后在build/report/profile目录下可以看到build的report?/p>

    这个报表非常有用,尤其是在在缩短build时间时可以快速定位那些耗时长的task?/p>

    • 试运行build?/strong>如果你想知道某个task执行时那些task会被一起执行,但是你又不想真正的执行这些task,可以使?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">-m来试运行?/li>
    $ gradle -m build :compileJava SKIPPED :processResources SKIPPED :classes SKIPPED :jar SKIPPED :assemble SKIPPED :compileTestJava SKIPPED :processTestResources SKIPPED :testClasses SKIPPED :test SKIPPED :check SKIPPED :build SKIPPED  BUILD SUCCESSFUL  Total time: 3.53 secs

    这样我们可以一目了然的看到那些task被执行了,又不需要花太多的时间?/p>

    • Gradle的图形界面?/strong>

    其实Gradle自带一个图形界面来让习惯gui操作的人来操作Gradle。打开方式很简单?/p>

    $ gradle --gui

    这样就会弹出一个gui界面?/p>

    通过这个gui界面可以很方面的执行gradle的各种命令,还可以将常用的命令保存为favorites。该gui的配置信息默认被存储在当前项目的gradle-app.setting文件中?/p>

    注意使用gradle --gui会阻塞当前终端,可以使用gradle --gui&来实现后台运行?/p>

    • 重新编译Gradle脚本?/strong>第一次运行Gradle命令,会在项目更目录下生成一?gradle目录来存放编译后的脚本。只有当构建脚本发生修改时采用重新编译。我们可以使?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">--recompile-scripts来强行重新编译?/li>


    ]]>

    -q(?code prettyprinted"="" style="font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; background-color: #f7f7f7;">--quiet)是启用重要信息级别,该级别下只会输出自己在命令行下打印的信息及错误信息?/p>