??xml version="1.0" encoding="utf-8" standalone="yes"?>BlogJava-我的Java路上那些事儿http://www.fpcwrs.live/hello-yun/快乐成长zh-cnSun, 25 Aug 2019 23:29:22 GMTSun, 25 Aug 2019 23:29:22 GMT60收录Q一个性能较好的jvm参数配置以及jvm的简?/title><link>http://www.fpcwrs.live/hello-yun/archive/2015/07/19/426314.html</link><dc:creator>云云</dc:creator><author>云云</author><pubDate>Sun, 19 Jul 2015 14:57:00 GMT</pubDate><guid>http://www.fpcwrs.live/hello-yun/archive/2015/07/19/426314.html</guid><wfw:comment>http://www.fpcwrs.live/hello-yun/comments/426314.html</wfw:comment><comments>http://www.fpcwrs.live/hello-yun/archive/2015/07/19/426314.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.fpcwrs.live/hello-yun/comments/commentRss/426314.html</wfw:commentRss><trackback:ping>http://www.fpcwrs.live/hello-yun/services/trackbacks/426314.html</trackback:ping><description><![CDATA[转自Qhttp://blog.csdn.net/jeffreynicole/article/details/46953059 <br /><br /><br /><p style="margin: 0px; padding: 0px; color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">一个性能较好的web服务器jvm参数配置Q?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;"><br /></p><p style="margin: 0px; padding: 0px; color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;"></p><div bg_plain"="" style="width: 938.515625px; overflow: hidden; border-color: #cccccc; color: #555555; line-height: 35px;"><div><div><strong>[plain]</strong> <a href="http://blog.csdn.net/jeffreynicole/article/details/46953059#" title="view plain" style="padding: 1px; color: #0c89cf; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-position: 0% 0%; background-repeat: no-repeat;">view plain</a><a href="http://blog.csdn.net/jeffreynicole/article/details/46953059#" title="copy" style="padding: 1px; color: #0c89cf; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); background-position: 0% 0%; background-repeat: no-repeat;">copy</a><div style="position: absolute; left: 472px; top: 696px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol start="1"><li style="line-height: 18px;">-server //服务器模?nbsp; </li><li style="line-height: 18px;">-Xmx2g //JVM最大允许分配的堆内存,按需分配  </li><li style="line-height: 18px;">-Xms2g //JVM初始分配的堆内存Q一般和Xmx配置成一样以避免每次gc后JVM重新分配内存?nbsp; </li><li style="line-height: 18px;">-Xmn256m //q轻代内存大,整个JVM内存=q轻?nbsp;+ q老代 + 持久?nbsp; </li><li style="line-height: 18px;">-XX:PermSize=128m //持久代内存大?nbsp; </li><li style="line-height: 18px;">-Xss256k //讄每个U程的堆栈大?nbsp; </li><li style="line-height: 18px;">-XX:+DisableExplicitGC //忽略手动调用GC, System.gc()的调用就会变成一个空调用Q完全不触发GC  </li><li style="line-height: 18px;">-XX:+UseConcMarkSweepGC //q发标记清除QCMSQ收集器  </li><li style="line-height: 18px;">-XX:+CMSParallelRemarkEnabled //降低标记停顿  </li><li style="line-height: 18px;">-XX:+UseCMSCompactAtFullCollection //在FULL GC的时候对q老代的压~?nbsp; </li><li style="line-height: 18px;">-XX:LargePageSizeInBytes=128m //内存늚大小  </li><li style="line-height: 18px;">-XX:+UseFastAccessorMethods //原始cd的快速优?nbsp; </li><li style="line-height: 18px;">-XX:+UseCMSInitiatingOccupancyOnly //使用手动定义初始化定义开始CMS攉  </li><li style="line-height: 18px;">-XX:CMSInitiatingOccupancyFraction=70 //使用cms作ؓ垃圾回收使用70Q后开始CMS攉  </li></ol></div><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><p style="margin: 0px; padding: 0px; color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;"></p><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">说明Q?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><p style="margin: 0px; padding: 0px; color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">-Xmn?Xmx之比大概?:9Q如果把新生代内存设|得太大会导致young gc旉较长</p><p style="margin: 0px; padding: 0px; color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">一个好的Webpȝ应该是每ơhttph甌内存都能在young gc回收掉,full gc怸发生Q当然这是最理想的情?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">xmn的值应该是保证够用Q够httpq发h之用Q的前提下设|得量?/p><p style="margin: 0px; padding: 0px; color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">web服务器和游戏服务器的配置思\不太一P最重要的区别是Ҏ戏服务器的xmn卛_M讄比较大,和Xmx大概1:3的关p,因ؓ游戏服务器一般是长连接,在保持一定的q发量后需要较大的q轻代堆内存Q如果设|得大小了会l常引发young gc</p><p style="margin: 0px; padding: 0px; color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;"><br /></p><p style="margin: 0px; padding: 0px; color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;"></p><ul style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;"><li>对JVM的简?/li></ul><p style="margin: 0px; padding: 0px; color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;"></p><p style="margin: 0px; padding: 0px; color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;"><img src="http://img.blog.csdn.net/20150719105526584?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 602px; height: auto;" /><br /></p><p style="margin: 0px; padding: 0px; color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">׃囑֏以看出jvm堆内存的分类情况QJVM内存被分成多个独立的部分?br />q泛地说QJVM堆内存被分ؓ两部?#8212;—q轻代(Young GenerationQ和老年代(Old GenerationQ?br /><br /><br /></p><ul style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;"><li><strong>q轻?/strong></li></ul><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">q轻代是所有新对象产生的地斏V当q轻代内存空间被用完Ӟ׃触发垃圾回收。这个垃圑֛收叫做Minor GC。年M被分?个部?#8212;—Enden区和两个Survivor区?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><strong style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">q轻代空间的要点Q?/strong><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">大多数新建的对象都位于Eden区?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">当Eden对象填满Ӟ׃执行Minor GC。ƈ把所有存zM来的对象转移到其中一个survivor区?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">Minor GC同样会检查存zM来的对象Qƈ把它们{Ud另一个survivor区。这样在一D|间内QM有一个空的survivor区?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">l过多次GC周期后,仍然存活下来的对象会被{Udq老代内存I间。通常q是在年M有资格提升到q老代前通过讑֮q龄阈值来完成的?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><strong style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;"><br /></strong><p style="margin: 0px; padding: 0px; color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;"></p><p style="margin: 0px; padding: 0px; color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;"></p><ul style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;"><li><strong>q老代</strong></li></ul><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">q老代内存里包含了长期存活的对象和l过多次Minor GC后依然存zM来的对象。通常会在老年代内存被占满时进行垃圑֛收。老年代的垃圾攉叫做Major GC。Major GC会花Ҏ多的旉?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><strong style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">Stop the World事g</strong><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">所有的垃圾攉都是“Stop the World”事gQ因为所有的应用U程都会停下来直到操作完成(所以叫“Stop the World”Q?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">因ؓq轻代里的对象都是一些Ӟshort-lived Q对象,执行Minor GC非常快,所以应用不会受刎ͼ“Stop the World”Q媄响?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">׃Major GC会检查所有存zȝ对象Q因此会p更长的时间。应该尽量减Major GC。因为Major GC会在垃圾回收期间让你的应用反应迟钝,所以如果你有一个需要快速响应的应用发生多次Major GCQ你会看到超旉误?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">垃圾回收旉取决于垃圑֛收策略。这是Z么有必要ȝ控垃圾收集和对垃圾收集进行调优。从而避免要求快速响应的应用出现时错误?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><ul style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;"><li><strong>怹?/strong></li></ul><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">怹代或?#8220;Perm Gen”包含了JVM需要的应用元数据,q些元数据描qC在应用里使用的类和方法。注意,怹代不是Java堆内存的一部分?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">怹代存放JVMq行时用的cR永久代同样包含了Java SE库的cdҎ。永久代的对象在full GC时进行垃圾收集?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><strong style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">Ҏ?/strong><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">Ҏ区是怹代空间的一部分Qƈ用来存储cd信息Q运行时帔R和静态变量)和方法代码和构造函C码?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><strong style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">内存?/strong><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">如果JVM实现支持QJVM内存理会ؓ创徏内存池,用来Z变对象创建对象池。字W串池就是内存池cd的一个很好的例子。内存池可以属于堆或者永久代Q这取决于JVM内存理的实现?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><strong style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">q行时常量池</strong><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">q行时常量池是每个类帔R池的q行时代表。它包含了类的运行时帔R和静态方法。运行时帔R池是Ҏ区的一部分?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><strong style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">Java栈内?/strong><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">Java栈内存用于运行线E。它们包含了Ҏ里的临时数据、堆里其它对象引用的特定数据?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><strong style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">Java垃圾回收</strong><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">Java垃圾回收会找出没用的对象Q把它从内存中移除ƈ释放出内存给以后创徏的对象用。JavaE序语言中的一个最大优Ҏ自动垃圾回收Q不像其他的E序语言那样需要手动分配和释放内存Q比如C语言?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">垃圾攉器是一个后台运行程序。它理着内存中的所有对象ƈ扑և没被引用的对象。所有的q些未引用的对象都会被删除,回收它们的空间ƈ分配l其他对象?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">一个基本的垃圾回收q程涉及三个步骤Q?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">标记Q这是第一步。在q一步,垃圾攉器会扑և哪些对象正在使用和哪些对象不在用?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">正常清除Q垃圾收集器清会除不在用的对象Q回收它们的I间分配l其他对象?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">压羃清除Qؓ了提升性能Q压~清除会在删除没用的对象后,把所有存zȝ对象Ud一赗这样可以提高分配新对象的效率?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">单标记和清除Ҏ存在两个问题Q?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">效率很低。因为大多数新徏对象都会成ؓ“没用对象”?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">l过多次垃圾回收周期的对象很有可能在以后的周期也会存zM来?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">上面单清除方法的问题在于Java垃圾攉的分代回收的Q而且在堆内存里有q轻代和q老代两个区域?/span><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><br style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;" /><ul style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;"><li><strong>Java垃圾回收cd</strong></li></ul><span style="color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">q里有五U可以在应用里用的垃圾回收cd?/span><p style="margin: 0px; padding: 0px; color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;"></p><p style="margin: 0px; padding: 0px; color: #555555; font-family: 'microsoft yahei'; font-size: 15px; line-height: 35px; background-color: #ffffff;">仅需要用JVM开兛_可以在我们的应用里启用垃圑֛收策略?br /><br /><strong>Serial GCQ?XX:+UseSerialGCQ?/strong>QSerial GC使用单的标记、清除、压~方法对q轻代和q老代q行垃圾回收Q即Minor GC和Major GC。Serial GC在client模式Q客L模式Q很有用Q比如在单的独立应用和CPU配置较低的机器。这个模式对占有内存较少的应用很用?br /><strong>Parallel GCQ?XX:+UseParallelGCQ?/strong>Q除了会产生N个线E来q行q轻代的垃圾攉外,Parallel GC和Serial GC几乎一栗这里的N是系lCPU的核数。我们可以?-XX:ParallelGCThreads=n q个JVM选项来控制线E数量。ƈ行垃圾收集器也叫throughput攉器。因为它使用了多CPU加快垃圾回收性能。Parallel GC在进行年老代垃圾攉时用单U程?br /><strong>Parallel Old GCQ?XX:+UseParallelOldGCQ?/strong>Q和Parallel GC一栗不同之处,Parallel Old GC在年M垃圾攉和年老代垃圾回收旉使用多线E收集?br /><strong>q发标记清除QCMSQ收集器Q?XX:+UseConcMarkSweepGC)</strong>QCMS攉器也被称为短暂停ƈ发收集器。它是对q老代q行垃圾攉的。CMS攉器通过多线Eƈ发进行垃圑֛Ӟ量减少垃圾攉造成的停ѝCMS攉器对q轻代进行垃圑֛收用的法和Parallel攉器一栗这个垃圾收集器适用于不能忍受长旉停顿要求快速响应的应用。可使用 -XX:ParallelCMSThreads=n JVM选项来限制CMS攉器的U程数量?br /><strong>G1垃圾攉器(-XX:+UseG1GC) G1QGarbage FirstQ?/strong>Q垃圾收集器是在Java 7后才可以使用的特性,它的长远目标时代替CMS攉器。G1攉器是一个ƈ行的、ƈ发的和增量式压羃短暂停顿的垃圾收集器。G1攉器和其他的收集器q行方式不一P不区分年M和年老代I间。它把堆I间划分为多个大相{的区域。当q行垃圾攉Ӟ它会优先攉存活对象较少的区域,因此?#8220;Garbage First”?/p><img src ="http://www.fpcwrs.live/hello-yun/aggbug/426314.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.fpcwrs.live/hello-yun/" target="_blank">云云</a> 2015-07-19 22:57 <a href="http://www.fpcwrs.live/hello-yun/archive/2015/07/19/426314.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux pdhttp://www.fpcwrs.live/hello-yun/archive/2014/09/28/418366.html云云云云Sun, 28 Sep 2014 15:45:00 GMThttp://www.fpcwrs.live/hello-yun/archive/2014/09/28/418366.htmlhttp://www.fpcwrs.live/fancydeepin/archive/2014/09/28/linux.html

17Qubuntu 防火?/a>
16Qubuntu 开?ssh 服务
15Qubuntu jdk 安装与配|?/a>
14Qubuntu tomcat 安装与配|?/a>
13Qubuntu mysql 安装
12Qubuntu root ?user 用户切换
11Qlinux more 命o
10Qlinux tar 命o
09Qlinux chmod 命o
08Qlinux touch 命o
07Qlinux cat 命o
06Qlinux mv 命o
05Qlinux rm 命o
04Qlinux cp 命o
03Qlinux mkdir 命o
02Qlinux cd 命o
01Qlinux ls 命o

云云 2014-09-28 23:45 发表评论
]]>
Java动态代理机制详解(JDK 和CGLIBQJavassistQASMQ[转]http://www.fpcwrs.live/hello-yun/archive/2014/09/28/418365.html云云云云Sun, 28 Sep 2014 15:44:00 GMThttp://www.fpcwrs.live/hello-yun/archive/2014/09/28/418365.html阅读全文

云云 2014-09-28 23:44 发表评论
]]>
后台 xss 控制http://www.fpcwrs.live/hello-yun/archive/2014/09/28/418353.html云云云云Sun, 28 Sep 2014 05:49:00 GMThttp://www.fpcwrs.live/hello-yun/archive/2014/09/28/418353.htmlhttp://www.fpcwrs.live/hello-yun/comments/418353.htmlhttp://www.fpcwrs.live/hello-yun/archive/2014/09/28/418353.html#Feedback0http://www.fpcwrs.live/hello-yun/comments/commentRss/418353.htmlhttp://www.fpcwrs.live/hello-yun/services/trackbacks/418353.html 
package com.qiyi.appstore.util;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.qiyi.appstore.exception.AppStoreException;
import com.qiyi.cloud.user.ApiCode;
public class XssUtils {
private static final Logger logger=LoggerFactory.getLogger(XssUtils.class);
public static String getSafeStringXSS(String s){
      if (StringUtils.isBlank(s)) {  
          return s;  
      }  
      StringBuilder sb = new StringBuilder(s.length() + 16);  
      for (int i = 0; i < s.length(); i++) {  
          char c = s.charAt(i);  
          switch (c) {  
          case '<':  
              sb.append("&lt;");  
              break; 
          case '>':  
              sb.append("&gt;");  
              break;  
          case '\'':  
              sb.append("&prime;");// &acute;");  
              break;  
          case '′':  
              sb.append("&prime;");// &acute;");  
              break;  
          case '\"':  
              sb.append("&quot;");  
              break;  
          case 'Q?:  
              sb.append("&quot;");  
              break;  
          case '&':  
              sb.append("Q?);  
              break;  
          case '#':  
              sb.append("Q?);  
              break;  
          case '\\':  
              sb.append('K?);  
              break; 
          case '=':  
              sb.append("=");  
              break;
          default:  
              sb.append(c);  
              break;  
          }  
      }  
      return sb.toString(); 
  }
public static <T> void getXssSaftBean(Class<?> clz,T bean) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException{
String classname = clz.getSimpleName();
logger.info("map target class name is {} .",classname);
Field[] fields = clz.getDeclaredFields();
for(Field field : fields){
Class<?> type = field.getType();
if(type.equals(String.class)){
String fieldname = field.getName();
String value = BeanUtils.getProperty(bean, fieldname);
if(StringUtils.isNotBlank(value)){
BeanUtils.setProperty(bean, fieldname, getSafeStringXSS(value));
}
}
}
}
}


云云 2014-09-28 13:49 发表评论
]]>
提升tomcat 性能 apr扩展libhttp://www.fpcwrs.live/hello-yun/archive/2014/01/16/409026.html云云云云Thu, 16 Jan 2014 06:50:00 GMThttp://www.fpcwrs.live/hello-yun/archive/2014/01/16/409026.htmlhttp://www.fpcwrs.live/hello-yun/comments/409026.htmlhttp://www.fpcwrs.live/hello-yun/archive/2014/01/16/409026.html#Feedback0http://www.fpcwrs.live/hello-yun/comments/commentRss/409026.htmlhttp://www.fpcwrs.live/hello-yun/services/trackbacks/409026.html提升tomcat 性能 apr扩展lib
使用aprcd 可以让tomcat的性能提升??? 
目前目中都使用q样的配|?br />
<Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol" URIEncoding="UTF-8"
               enableLookups="false"
               acceptCount="300"
               connectionTimeout="20000"
               disableUploadTimeout="true" maxThreads="1000" maxSpareThreads="50" minSpareThreads="25"
               redirectPort="8443" />


catalia.sh 
CATALINA_OPTS="$CATALINA_OPTS -Djava.library.path=/usr/local/apr/lib"


云云 2014-01-16 14:50 发表评论
]]>
redis 讄分布式锁 http://www.fpcwrs.live/hello-yun/archive/2014/01/15/408988.html云云云云Wed, 15 Jan 2014 11:00:00 GMThttp://www.fpcwrs.live/hello-yun/archive/2014/01/15/408988.htmlhttp://www.fpcwrs.live/hello-yun/comments/408988.htmlhttp://www.fpcwrs.live/hello-yun/archive/2014/01/15/408988.html#Feedback1http://www.fpcwrs.live/hello-yun/comments/commentRss/408988.htmlhttp://www.fpcwrs.live/hello-yun/services/trackbacks/408988.html阅读全文

云云 2014-01-15 19:00 发表评论
]]>
Eclipse背景颜色和字体配|?/title><link>http://www.fpcwrs.live/hello-yun/archive/2014/01/09/408739.html</link><dc:creator>云云</dc:creator><author>云云</author><pubDate>Thu, 09 Jan 2014 08:41:00 GMT</pubDate><guid>http://www.fpcwrs.live/hello-yun/archive/2014/01/09/408739.html</guid><wfw:comment>http://www.fpcwrs.live/hello-yun/comments/408739.html</wfw:comment><comments>http://www.fpcwrs.live/hello-yun/archive/2014/01/09/408739.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.fpcwrs.live/hello-yun/comments/commentRss/408739.html</wfw:commentRss><trackback:ping>http://www.fpcwrs.live/hello-yun/services/trackbacks/408739.html</trackback:ping><description><![CDATA[<div style="margin: 0px; color: #333333; font-family: 微Y雅黑, Verdana, sans-serif, 宋体; font-size: 13px; line-height: 23px; background-color: #ffffff;">对eclipse的默认配|很不爽Q黑色字体白色底好刺|而且字体习惯用Courier New</div><div style="margin: 0px; color: #333333; font-family: 微Y雅黑, Verdana, sans-serif, 宋体; font-size: 13px; line-height: 23px; background-color: #ffffff;"></div><div style="margin: 0px; color: #333333; font-family: 微Y雅黑, Verdana, sans-serif, 宋体; font-size: 13px; line-height: 23px; background-color: #ffffff;"><div style="margin: 0px;">改变背景颜色Q?/div><div style="margin: 0px;">windows->Preferences->General->Editor->Text Editors</div><div style="margin: 0px;">双选择Appearance color options </div><div style="margin: 0px;">选Background color 选择背景颜色</div><div style="margin: 0px;">个h比较舒服的豆沙绿色和黑色背景Q但黑色背景q要把其他的字体颜色也改了才好看Q而且豆沙l色跟默认的字体颜色搭配的很好?/div><div style="margin: 0px;">豆沙l色Q色调:85   饱和度:123   亮度Q?05 Q?/div><div style="margin: 0px;">据说q个色调是眼U专安的, 因其颜色比较柔和Q据说阅ȝ时候用q种颜色做背景有利于保护眼睛Q?word底色p多h讄成豆沙绿艌Ӏ?/div><div style="margin: 0px;"></div><div style="margin: 0px;">xml的字体调_ </div><div style="margin: 0px;">window--preferences--General--appearance--colors and fonts--Basic-- "Text font "  </div><div style="margin: 0px;">然后点change,可以讄字体Q我喜欢Courier New</div><div style="margin: 0px;"></div><div style="margin: 0px;">Java的字体调_ </div><div style="margin: 0px;">window--preferences--General--appearance--colors and fonts--java </div></div><img src ="http://www.fpcwrs.live/hello-yun/aggbug/408739.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.fpcwrs.live/hello-yun/" target="_blank">云云</a> 2014-01-09 16:41 <a href="http://www.fpcwrs.live/hello-yun/archive/2014/01/09/408739.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>删除文g的svn信息 解决从其它\径拷q来的文件带有\径信?无法提交的问?/title><link>http://www.fpcwrs.live/hello-yun/archive/2013/12/05/407259.html</link><dc:creator>云云</dc:creator><author>云云</author><pubDate>Thu, 05 Dec 2013 09:17:00 GMT</pubDate><guid>http://www.fpcwrs.live/hello-yun/archive/2013/12/05/407259.html</guid><wfw:comment>http://www.fpcwrs.live/hello-yun/comments/407259.html</wfw:comment><comments>http://www.fpcwrs.live/hello-yun/archive/2013/12/05/407259.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.fpcwrs.live/hello-yun/comments/commentRss/407259.html</wfw:commentRss><trackback:ping>http://www.fpcwrs.live/hello-yun/services/trackbacks/407259.html</trackback:ping><description><![CDATA[<p align="left">有时候在目?会变化\?把原有\径的文g拷到新的路径下面<br />再删除原来不想的路径再提交一?q样以来 原来的\径确实不存在?br />但是拯来的文g带有原来路径的svn信息 q样以来 在提交的时?无法提?br />惌文g按照的\径提?但始lsvnq是再往以前的\径提?q提CZ路径不存?br />在网上搜了下 如何删除文g自带的svn路径信息 <br />按照下面的方式来操作卛_</p> <p style="text-align: left; padding-bottom: 0px; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 10px; padding-left: 0px; padding-right: 0px; font: 16px/28px 'Hiragino Sans GB W3', 'Hiragino Sans GB', Arial, Helvetica, simsun, u5b8bu4f53; white-space: normal; letter-spacing: normal; color: rgb(13,13,13); word-spacing: 0px; padding-top: 0px; -webkit-text-stroke-width: 0px">Windows Registry Editor Version 5.00<br style="line-height: 28px" />[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN]<span class="Apple-converted-space"> </span><br style="line-height: 28px" />@="删除该目录下?svn文g"<br style="line-height: 28px" />[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN\command]<span class="Apple-converted-space"> </span><br style="line-height: 28px" />@="cmd.exe /c \"TITLE Removing SVN Folders in %1 && COLOR 9A && FOR /r \"%1\" %%f IN (.svn) DO RD /s /q \"%%f\" \""</p> <p style="text-align: left; padding-bottom: 0px; text-transform: none; background-color: rgb(255,255,255); text-indent: 0px; margin: 0px 0px 10px; padding-left: 0px; padding-right: 0px; font: 16px/28px 'Hiragino Sans GB W3', 'Hiragino Sans GB', Arial, Helvetica, simsun, u5b8bu4f53; white-space: normal; letter-spacing: normal; color: rgb(13,13,13); word-spacing: 0px; padding-top: 0px; -webkit-text-stroke-width: 0px"><br style="line-height: 28px" />把上面这D|字保存问一个Done.reg文g<br style="line-height: 28px" />然后执行,导入到注册表<br style="line-height: 28px" />׃在你右键一个文件夹的时候多出来一个菜?删除该目录下?svn文g"<br style="line-height: 28px" />执行该命令即?/p> <p align="left"> </p><img src ="http://www.fpcwrs.live/hello-yun/aggbug/407259.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.fpcwrs.live/hello-yun/" target="_blank">云云</a> 2013-12-05 17:17 <a href="http://www.fpcwrs.live/hello-yun/archive/2013/12/05/407259.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mybatis No enum const class org.apache.ibatis.type.JdbcType.Date 坑爹的配|?/title><link>http://www.fpcwrs.live/hello-yun/archive/2013/11/26/406862.html</link><dc:creator>云云</dc:creator><author>云云</author><pubDate>Tue, 26 Nov 2013 13:02:00 GMT</pubDate><guid>http://www.fpcwrs.live/hello-yun/archive/2013/11/26/406862.html</guid><wfw:comment>http://www.fpcwrs.live/hello-yun/comments/406862.html</wfw:comment><comments>http://www.fpcwrs.live/hello-yun/archive/2013/11/26/406862.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.fpcwrs.live/hello-yun/comments/commentRss/406862.html</wfw:commentRss><trackback:ping>http://www.fpcwrs.live/hello-yun/services/trackbacks/406862.html</trackback:ping><description><![CDATA[在ibatis中不需要关注这些参?而{到mybatis?如果字段gؓI?必须讄jdbcType<br />?br />insert into testTable<br />   (ID,<br />   NAME,<br />   DESCRIPTION,<br />   IMAGEURL,<br />   LINKURL,<br />   ISALWAYS,<br />   ISDISPLAYINDEX,<br />   DISPLAYWEIGHT,<br />   STARTTIME,<br />   ENDTIME,<br />   CREATOR,<br />   CREATTIME,<br />   MODIFYTIME)<br />  values<br />   (SEQ_ACTIVITY_TABLE.NEXTVAL,<br />   #{name},<br />   #{desc,jdbcType=VARCHAR},<br />   #{imageUrl,jdbcType=VARCHAR},<br />   #{linkUrl,jdbcType=VARCHAR},<br />   #{isAlways,jdbcType=CHAR},<br />   #{isDisplayIndex,jdbcType=CHAR},<br />   #{displayWeight,jdbcType=VARCHAR},<br />   #{startTime,jdbcType=DATE},<br />   #{endTime,jdbcType=DATE},<br />   #{creator,jdbcType=VARCHAR},<br />   sysdate,<br />   sysdate<br />   )<br /> </insert><br /><br />q些讄之多Q太烦了Q最让h烦的?nbsp; jdbcType = DATEQ类型还必须大写Q不能小写?br />如下面的例子Q将DATE Ҏ Date 。结果让人很抓狂啊!Q!<br />insert into testTable<br />   (ID,<br />   NAME,<br />   DESCRIPTION,<br />   IMAGEURL,<br />   LINKURL,<br />   ISALWAYS,<br />   ISDISPLAYINDEX,<br />   DISPLAYWEIGHT,<br />   STARTTIME,<br />   ENDTIME,<br />   CREATOR,<br />   CREATTIME,<br />   MODIFYTIME)<br />  values<br />   (SEQ_ACTIVITY_TABLE.NEXTVAL,<br />   #{name},<br />   #{desc,jdbcType=VARCHAR},<br />   #{imageUrl,jdbcType=VARCHAR},<br />   #{linkUrl,jdbcType=VARCHAR},<br />   #{isAlways,jdbcType=CHAR},<br />   #{isDisplayIndex,jdbcType=CHAR},<br />   #{displayWeight,jdbcType=VARCHAR},<br />   #{startTime,jdbcType=Date},<br />   #{endTime,jdbcType=DATE},<br />   #{creator,jdbcType=VARCHAR},<br />   sysdate,<br />   sysdate<br />   )<br /> </insert><br /><pre style="line-height: normal; text-transform: none; font-variant: normal; font-style: normal; text-indent: 0px; letter-spacing: normal; color: rgb(0,0,0); font-weight: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px">org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error resolving JdbcType. Cause: java.lang.IllegalArgumentException: No enum const class org.apache.ibatis.type.JdbcType.Date org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:75) org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:368)</pre>更坑爹的在后面,上面insert时的时候用#{endTime,jdbcType=DATE},可以时间插入成功,且可以精到时分U?br />但如果在update语句中也q样使用Q那你得到的只会有日期,q够坑爹的了?Q尼?nbsp; 比vibatis方便之处差远?br />要想在update语句?时间格式化成时分秒 不得不再加一个类?如下面:<br />startTime = #{startTime,javaType=DATE, jdbcType=VARCHAR} <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><img src ="http://www.fpcwrs.live/hello-yun/aggbug/406862.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.fpcwrs.live/hello-yun/" target="_blank">云云</a> 2013-11-26 21:02 <a href="http://www.fpcwrs.live/hello-yun/archive/2013/11/26/406862.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>走过路过 不要错过的好文章 CSRF 防MҎ选择之道http://www.fpcwrs.live/hello-yun/archive/2013/11/05/406028.html云云云云Tue, 05 Nov 2013 12:53:00 GMThttp://www.fpcwrs.live/hello-yun/archive/2013/11/05/406028.htmlhttp://www.fpcwrs.live/hello-yun/comments/406028.htmlhttp://www.fpcwrs.live/hello-yun/archive/2013/11/05/406028.html#Feedback0http://www.fpcwrs.live/hello-yun/comments/commentRss/406028.htmlhttp://www.fpcwrs.live/hello-yun/services/trackbacks/406028.htmlCSRF 背景与介l?/strong>

CSRFQCross Site Request Forgery, 跨站域请求伪造)是一U网l的d方式Q它?2007 q曾被列Z联网 20 大安全隐患之一。其他安全隐患,比如 SQL 脚本注入Q跨站域脚本d{在q年来已l逐渐Z人熟知,很多|站也都针对他们q行了防御。然而,对于大多Ch来说QCSRF 却依然是一个陌生的概念。即便是大名鼎鼎?Gmail, ?2007 q底也存在着 CSRF 漏洞Q从而被黑客d而 Gmail 的用户造成巨大的损失?/p>

CSRF d实例

CSRF d可以在受完毫不知情的情况下以受害者名义伪造请求发送给受攻ȝ点,从而在q未授权的情况下执行在权限保护之下的操作。比如说Q受完?Bob 在银行有一W存ƾ,通过寚w行的|站发送请?http://bank.example/withdraw?account=bob&amount=1000000&for=bob2 可以?Bob ?1000000 的存ƾ{?bob2 的̎号下。通常情况下,该请求发送到|站后,服务器会先验证该h是否来自一个合法的 sessionQƈ且该 session 的用?Bob 已经成功登陆。黑?Mallory 自己在该银行也有账户Q他知道上文中的 URL 可以把钱q行转帐操作。Mallory 可以自己发送一个请求给银行Qhttp://bank.example/withdraw?account=bob&amount=1000000&for=Mallory。但是这个请求来?Mallory 而非 BobQ他不能通过安全认证Q因此该h不会起作用。这ӞMallory 惛_使用 CSRF 的攻L式,他先自己做一个网站,在网站中攑օ如下代码Q?src=”http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory ”Qƈ且通过q告{诱?Bob 来访问他的网站。当 Bob 讉K该网站时Q上q?url ׃?Bob 的浏览器发向银行Q而这个请求会附带 Bob 览器中?cookie 一起发向银行服务器。大多数情况下,该请求会p|Q因Z要求 Bob 的认证信息。但是,如果 Bob 当时恰y刚访问他的银行后不久Q他的浏览器与银行网站之间的 session 未q期Q浏览器?cookie 之中含有 Bob 的认证信息。这Ӟ悲剧发生了,q个 url h׃得到响应Q钱从 Bob 的̎可{Ud Mallory 的̎P?Bob 当时毫不知情。等以后 Bob 发现账户钱少了,即他去银行查询日志Q他也只能发现确实有一个来自于他本人的合法h转移了资金,没有M被攻ȝ痕迹。?Mallory 则可以拿到钱后逍遥法外?/p>

CSRF d的对?/strong>

在讨论如何抵?CSRF 之前Q先要明?CSRF d的对象,也就是要保护的对象。从以上的例子可知,CSRF d是黑客借助受害者的 cookie 骗取服务器的信QQ但是黑客ƈ不能拿到 cookieQ也看不?cookie 的内宏V另外,对于服务器返回的l果Q由于浏览器同源{略的限Ӟ黑客也无法进行解析。因此,黑客无法从返回的l果中得CQ何东西,他所能做的就是给服务器发送请求,以执行请求中所描述的命令,在服务器端直接改变数据的|而非H取服务器中的数据。所以,我们要保护的对象是那些可以直接生数据改变的服务Q而对于读取数据的服务Q则不需要进?CSRF 的保护。比如银行系l中转̎的请求会直接改变账户的金额,会遭?CSRF dQ需要保护。而查询余额是寚w额的d操作Q不会改变数据,CSRF d无法解析服务器返回的l果Q无需保护?/p>

当前防M CSRF 的几U策?/strong>

在业界目前防?CSRF d主要有三U策略:验证 HTTP Referer 字段Q在h地址中添?token q证;?HTTP 头中自定义属性ƈ验证。下面就分别对这三种{略q行详细介绍?/p>

验证 HTTP Referer 字段

Ҏ HTTP 协议Q在 HTTP 头中有一个字D叫 RefererQ它记录了该 HTTP h的来源地址。在通常情况下,讉K一个安全受限页面的h来自于同一个网站,比如需要访?http://bank.example/withdraw?account=bob&amount=1000000&for=MalloryQ用户必d登陆 bank.exampleQ然后通过点击面上的按钮来触发{账事件。这Ӟ该{帐请求的 Referer 值就会是转̎按钮所在的面?URLQ通常是以 bank.example 域名开头的地址。而如果黑客要寚w行网站实?CSRF dQ他只能在他自己的网站构造请求,当用户通过黑客的网站发送请求到银行Ӟ该请求的 Referer 是指向黑客自q|站。因此,要防?CSRF dQ银行网站只需要对于每一个{账请求验证其 Referer |如果是以 bank.example 开头的域名Q则说明该请求是来自银行|站自己的请求,是合法的。如?Referer 是其他网站的话,则有可能是黑客的 CSRF dQ拒l该h?/p>

q种Ҏ的显而易见的好处是单易行,|站的普通开发h员不需要操?CSRF 的漏z,只需要在最后给所有安全敏感的hl一增加一个拦截器来检?Referer 的值就可以。特别是对于当前现有的系l,不需要改变当前系l的M已有代码和逻辑Q没有风险,非常便捷?/p>

然而,q种Ҏq万无一失。Referer 的值是由浏览器提供的,虽然 HTTP 协议上有明确的要求,但是每个览器对?Referer 的具体实现可能有差别Qƈ不能保证览器自w没有安全漏z。用验?Referer 值的ҎQ就是把安全性都依赖于第三方Q即览器)来保障,从理Z来讲Q这样ƈ不安全。事实上Q对于某些浏览器Q比?IE6 ?FF2Q目前已l有一些方法可以篡?Referer 倹{如?bank.example |站支持 IE6 览器,黑客完全可以把用h览器?Referer DZ bank.example 域名开头的地址Q这样就可以通过验证Q从而进?CSRF d?/p>

即便是用最新的览器,黑客无法改 Referer |q种Ҏ仍然有问题。因?Referer g记录下用L讉K来源Q有些用戯样会늊C们自q隐私权,特别是有些组l担?Referer g把组l内|中的某些信息泄露到外网中。因此,用户自己可以讄览器其在发送请求时不再提供 Referer。当他们正常讉K银行|站Ӟ|站会因求没?Referer D认为是 CSRF dQ拒l合法用L讉K?/p>

在请求地址中添?token q?/strong>

CSRF d之所以能够成功,是因为黑客可以完全伪造用LhQ该h中所有的用户验证信息都是存在?cookie 中,因此黑客可以在不知道q些验证信息的情况下直接利用用户自己?cookie 来通过安全验证。要抵M CSRFQ关键在于在h中放入黑客所不能伪造的信息Qƈ且该信息不存在于 cookie 之中。可以在 HTTP h中以参数的Ş式加入一个随Z生的 tokenQƈ在服务器端徏立一个拦截器来验证这?tokenQ如果请求中没有 token 或?token 内容不正,则认为可能是 CSRF d而拒l该h?/p>

q种Ҏ要比?Referer 要安全一些,token 可以在用L陆后产生q放?session 之中Q然后在每次h时把 token ?session 中拿出,与请求中?token q行比对Q但q种Ҏ的难点在于如何把 token 以参数的形式加入h。对?GET hQtoken 附在请求地址之后Q这?URL 变?http://url?csrftoken=tokenvalue?而对?POST h来说Q要?form 的最后加?<input type=”hidden” name=”csrftoken” value=”tokenvalue”/>Q这样就?token 以参数的形式加入h了。但是,在一个网站中Q可以接受请求的地方非常多,要对于每一个请求都加上 token 是很ȝ的,q且很容易漏掉,通常使用的方法就是在每次面加蝲Ӟ使用 javascript 遍历整个 dom 树,对于 dom 中所有的 a ?form 标签后加?token。这样可以解军_部分的请求,但是对于在页面加载之后动态生成的 html 代码Q这U方法就没有作用Q还需要程序员在编码时手动d token?/p>

该方法还有一个缺Ҏ难以保证 token 本n的安全。特别是在一些论坛之cL持用戯己发表内容的|站Q黑客可以在上面发布自己个h|站的地址。由于系l也会在q个地址后面加上 tokenQ黑客可以在自己的网站上得到q个 tokenQƈ马上可以发?CSRF d。ؓ了避免这一点,pȝ可以在添?token 的时候增加一个判断,如果q个链接是链到自己本站的Q就在后面添?tokenQ如果是通向外网则不加。不q,即ɘq个 csrftoken 不以参数的Ş式附加在h之中Q黑客的|站也同样可以通过 Referer 来得到这?token g发动 CSRF d。这也是一些用户喜Ƣ手动关闭浏览器 Referer 功能的原因?/p>

?HTTP 头中自定义属性ƈ验证

q种Ҏ也是使用 token q进行验证,和上一U方法不同的是,q里q不是把 token 以参数的形式|于 HTTP h之中Q而是把它攑ֈ HTTP 头中自定义的属性里。通过 XMLHttpRequest q个c,可以一ơ性给所有该c请求加?csrftoken q个 HTTP 头属性,q把 token 值放入其中。这栯决了上种Ҏ在请求中加入 token 的不便,同时Q通过 XMLHttpRequest h的地址不会被记录到览器的地址栏,也不用担?token 会透过 Referer 泄露到其他网站中厅R?/p>

然而这U方法的局限性非常大。XMLHttpRequest h通常用于 Ajax Ҏ中对于页面局部的异步hQƈ非所有的h都适合用这个类来发P而且通过该类h得到的页面不能被览器所记录下,从而进行前q,后退Q刷斎ͼ收藏{操作,l用户带来不ѝ另外,对于没有q行 CSRF 防护的遗留系l来_要采用这U方法来q行防护Q要把所有请求都改ؓ XMLHttpRequest hQ这样几乎是要重写整个网站,q代h疑是不能接受的?/p>

Java 代码CZ

下文以 Java ZQ对上述三种Ҏ分别用代码进行示例。无Z用何U方法,在服务器端的拦截器必不可,它将负责查到来的h是否W合要求Q然后视l果而决定是否l请求或者丢弃。在 Java 中,拦截器是?Filter 来实现的。我们可以编写一?FilterQƈ?web.xml 中对其进行配|,使其对于讉K所有需?CSRF 保护的资源的hq行拦截?/p>

?filter 中对h?Referer 验证代码如下
清单 1. ?Filter 中验?Referer

1
2
3
4
5
6
7
8
// ?HTTP 头中取得 Referer ?
 String referer=request.getHeader("Referer"); 
 // 判断 Referer 是否?bank.example 开?
 if((referer!=null) &&(referer.trim().startsWith(“bank.example”))){ 
    chain.doFilter(request, response); 
 }else
    request.getRequestDispatcher(“error.jsp”).forward(request,response); 
 }

以上代码先取?Referer |然后q行判断Q当光Iƈ?bank.example 开头时Q则l箋hQ否则的话可能是 CSRF dQ{?error.jsp 面?/p>

如果要进一步验证请求中?token |代码如下

1
<em><strong>清单 2. ?filter 中验证请求中?lt;/strong></em> token
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
HttpServletRequest req = (HttpServletRequest)request; 
 HttpSession s = req.getSession(); 
  
 // ?session 中得?csrftoken 属?
 String sToken = (String)s.getAttribute(“csrftoken”); 
 if(sToken == null){ 
  
    // 产生新的 token 攑օ session ?
    sToken = generateToken(); 
    s.setAttribute(“csrftoken”,sToken); 
    chain.doFilter(request, response); 
 } else
  
    // ?HTTP 头中取得 csrftoken 
    String xhrToken = req.getHeader(“csrftoken”); 
  
    // 从请求参C取得 csrftoken 
    String pToken = req.getParameter(“csrftoken”); 
    if(sToken != null && xhrToken != null && sToken.equals(xhrToken)){ 
        chain.doFilter(request, response); 
    }else if(sToken != null && pToken != null && sToken.equals(pToken)){ 
        chain.doFilter(request, response); 
    }else
        request.getRequestDispatcher(“error.jsp”).forward(request,response); 
    
 }

首先判断 session 中有没有 csrftokenQ如果没有,则认为是W一ơ访问,session 是新建立的,q时生成一个新?tokenQ放?session 之中Qƈl箋执行h。如?session 中已l有 csrftokenQ则说明用户已经与服务器之间建立了一个活跃的 sessionQ这时要看这个请求中有没有同旉带这?tokenQ由于请求可能来自于常规的访问或?XMLHttpRequest 异步讉KQ我们分别尝试从h中获?csrftoken 参数以及?HTTP 头中获取 csrftoken 自定义属性ƈ?session 中的D行比较,只要有一个地方带有有?tokenQ就判定h合法Q可以l执行,否则p{到错误页面。生?token 有很多种ҎQQ何的随机法都可以用,Java ?UUID cM是一个不错的选择?/p>

除了在服务器端利?filter 来验?token 的g外,我们q需要在客户端给每个h附加上这?tokenQ这是利?js 来给 html 中的链接和表单请求地址附加 csrftoken 代码Q其中已定义 token 为全局变量Q其值可以从 session 中得到?/p>

1
<em><strong>清单 3. 在客L对于h附加</strong> </em>token
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
function appendToken(){ 
    updateForms(); 
    updateTags(); 
 
  
 function updateForms() { 
    // 得到面中所有的 form 元素
    var forms = document.getElementsByTagName('form'); 
    for(i=0; i<forms.length; i++) { 
        var url = forms[i].action; 
  
        // 如果q个 form ?action gؓI,则不附加 csrftoken 
        if(url == null || url == "" ) continue
  
        // 动态生?input 元素Q加入到 form 之后
        var e = document.createElement("input"); 
        e.name = "csrftoken"
        e.value = token; 
        e.type="hidden"
        forms[i].appendChild(e); 
    
 
  
 function updateTags() { 
    var all = document.getElementsByTagName('a'); 
    var len = all.length; 
  
    // 遍历所?a 元素
    for(var i=0; i<len; i++) { 
        var e = all[i]; 
        updateTag(e, 'href', token); 
    
 
  
 function updateTag(element, attr, token) { 
    var location = element.getAttribute(attr); 
    if(location != null && location != '' '' ) { 
        var fragmentIndex = location.indexOf('#'); 
        var fragment = null
        if(fragmentIndex != -1){ 
  
            //url 中含有只相当늚锚标?
            fragment = location.substring(fragmentIndex); 
            location = location.substring(0,fragmentIndex); 
        
  
        var index = location.indexOf('?'); 
  
        if(index != -1) { 
            //url 中已含有其他参数
            location = location + '&csrftoken=' + token; 
        } else
            //url 中没有其他参?
            location = location + '?csrftoken=' + token; 
        
        if(fragment != null){ 
            location += fragment; 
        
  
        element.setAttribute(attr, location); 
    
 }

在客L html 中,主要是有两个地方需要加?tokenQ一个是表单 formQ另一个就是链?a。这D代码首先遍历所有的 formQ在 form 最后添加一隐藏字段Q把 csrftoken 攑օ其中。然后,代码遍历所有的链接标记 aQ在?href 属性中加入 csrftoken 参数。注意对?a.href 来说Q可能该属性已l有参数Q或者有锚标记。因此需要分情况讨论Q以不同的格式把 csrftoken 加入其中?/p>

如果你的|站使用 XMLHttpRequestQ那么还需要在 HTTP 头中自定?csrftoken 属性,利用 dojo.xhr l?XMLHttpRequest 加上自定义属性代码如下:

1
<strong><em>清单 4. ?HTTP 头中自定义属?lt;/em></strong>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
                 
var plainXhr = dojo.xhr; 
 
// 重写 dojo.xhr Ҏ
dojo.xhr = function(method,args,hasBody) { 
   // 保 header 对象存在
   args.headers = args.header || {}; 
 
   tokenValue = '<%=request.getSession(false).getAttribute("csrftoken")%>'
   var token = dojo.getObject("tokenValue"); 
 
   // ?csrftoken 属性放到头?
   args.headers["csrftoken"] = (token) ? token : "  "
   return plainXhr(method,args,hasBody); 
};

q里改写?dojo.xhr 的方法,首先保 dojo.xhr 中存?HTTP _然后?args.headers 中添?csrftoken 字段Qƈ?token g session 里拿出放入字D中?/p>

CSRF 防MҎ选择之道

通过上文讨论可知Q目前业界应?CSRF d有一些克制方法,但是每种Ҏ都有利弊Q没有一U方法是完美的。如何选择合适的Ҏ非常重要。如果网站是一个现有系l,惌在最短时间内获得一定程度的 CSRF 的保护,那么验证 Referer 的方法是最方便的,要想增加安全性的话,可以选择不支持低版本览器,毕竟q前来_IE7+, FF3+ q类高版本浏览器?Referer D无法被篡攏V?/p>

如果pȝ必须支持 IE6Qƈ且仍焉要高安全性。那么就要?token 来进行验证,在大部分情况下,使用 XmlHttpRequest q不合适,token 只能以参数的形式放于h之中Q若你的pȝ不支持用戯己发布信息,那这U程度的防护已经_Q否则的话,你仍焉以防?token 被黑客窃取ƈ发动d。在q种情况下,你需要小心规划你|站提供的各U服务,从中间找出那些允许用戯己发布信息的部分Q把它们与其他服务分开Q用不同的 token q行保护Q这样可以有效抵御黑客对于你关键服务的攻击,把危害降到最低。毕竟,删除别h一个帖子比直接从别̎号中转走大笔存款严重E度要轻的多?/p>

如果是开发一个全新的pȝQ则抵M CSRF 的选择要大得多。笔者徏议对于重要的服务Q可以尽量?XMLHttpRequest 来访问,q样增加 token 要容易很多。另外尽量避免在 js 代码中用复杂逻辑来构造常规的同步h来访问需?CSRF 保护的资源,比如 window.location ?document.createElement(“a”) 之类Q这样也可以减少在附?token 时生的不必要的ȝ?/p>

最后,要记?CSRF 不是黑客唯一的攻LD,无论?CSRF 防范有多么严密,如果你系l有其他安全漏洞Q比如跨站域脚本d XSSQ那么黑客就可以l过你的安全防护Q展开包括 CSRF 在内的各U攻击,你的防线如同虚设?/p>

ȝ与展?/strong>

可见QCSRF 是一U危害非常大的攻击,又很难以防范。目前几U防御策略虽然可以很大程度上抵M CSRF 的攻击,但ƈ没有一U完的解决Ҏ。一些新的方案正在研I之中,比如对于每次h都用不同的动态口令,?Referer ?token Ҏl合hQ甚臛_试修?HTTP 规范Q但是这些新的方案尚不成熟,要正式投入用ƈ被业界广为接受还需时日。在q之前,我们只有充分重视 CSRFQ根据系l的实际情况选择最合适的{略Q这h能把 CSRF 的危害降到最低?/p>

云云 2013-11-05 20:53 发表评论
]]>
ħǹ