﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-岁月如歌-随笔分类-java</title><link>http://www.blogjava.net/midstr/category/24101.html</link><description>人生非梦</description><language>zh-cn</language><lastBuildDate>Fri, 06 Nov 2009 16:31:22 GMT</lastBuildDate><pubDate>Fri, 06 Nov 2009 16:31:22 GMT</pubDate><ttl>60</ttl><item><title>伪ajax方式提交带文件上传的表单</title><link>http://www.blogjava.net/midstr/archive/2009/11/06/301505.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Fri, 06 Nov 2009 15:10:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2009/11/06/301505.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/301505.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2009/11/06/301505.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/301505.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/301505.html</trackback:ping><description><![CDATA[<p align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在ajax还没有流行起来的时候，因为表单使用form的action进行页面跳转提交，所以不存在什么问题。<br />
</p>
<hr />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 自从ajax流行起来之后，一般的表单都是通过ajax方式提交，所以碰到带文件上传的表单就比较麻烦。后来在网上查了一下，基本都没有比较好的解决办法，所以还是对这种特殊的表单使用页面跳转方式提交。最近看到同事用一种伪ajax方式解决了此问题。其基本原理就是在页面增加一个隐藏iframe，然后通过ajax提交除文件之外的表单数据，在表单数据提交成功之后的回调函数中，通过form单独提交文件，而这个提交文件的form的target就指向前述隐藏的iframe。代码如下(注意form的target属性指向隐藏的iframe)：<br />
<p>&nbsp;</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #0000ff">&lt;</span><span style="color: #800000">form&nbsp;</span><span style="color: #ff0000">style</span><span style="color: #0000ff">="padding:0px;margin:0px;"</span><span style="color: #ff0000">&nbsp;target</span><span style="color: #0000ff">="upload"</span><span style="color: #ff0000">&nbsp;action</span><span style="color: #0000ff">="/xxx/xx.do"</span><span style="color: #ff0000">&nbsp;id</span><span style="color: #0000ff">="uploadForm"</span><span style="color: #ff0000">&nbsp;name</span><span style="color: #0000ff">="uploadForm"</span><span style="color: #ff0000">&nbsp;encType</span><span style="color: #0000ff">="multipart/form-data"</span><span style="color: #ff0000">&nbsp;method</span><span style="color: #0000ff">="post"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">input&nbsp;&nbsp;</span><span style="color: #ff0000">type</span><span style="color: #0000ff">="file"</span><span style="color: #ff0000">&nbsp;id</span><span style="color: #0000ff">=""</span><span style="color: #ff0000">attachFile</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">form</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">iframe&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="upload"</span><span style="color: #ff0000">&nbsp;style</span><span style="color: #0000ff">="display:none"</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">iframe</span><span style="color: #0000ff">&gt;</span></div>
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上述伪ajax方法的缺点是，表单数据和文件数据不能做到一个事物里面，如果后面文件上传失败（比如网络中断、服务器down掉等），则前面上传的表单数据算是垃圾数据了。当然这个在对数据一致性要求不是很高的环境，还是不错的解决办法。 
<img src ="http://www.blogjava.net/midstr/aggbug/301505.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2009-11-06 23:10 <a href="http://www.blogjava.net/midstr/archive/2009/11/06/301505.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java XML API 漫谈 zz</title><link>http://www.blogjava.net/midstr/archive/2009/10/01/297066.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Wed, 30 Sep 2009 17:34:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2009/10/01/297066.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/297066.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2009/10/01/297066.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/297066.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/297066.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">作者：robbin (MSN:robbin_fan AT hotmail DOT com)</font></p>
<p><font style="background-color: #cce8cf">在IBM的developerWorks上有两篇非常优秀的关于Java XML API的评测文章：</font></p>
<p><font style="background-color: #cce8cf">Java中XML文档模型的性能</font></p>
<p><font style="background-color: #cce8cf">Java中XML文档模型的用法</font></p>
<p><font style="background-color: #cce8cf">对这两篇文章我想说的就是 吐血推荐 </font></p>
<p><font style="background-color: #cce8cf">Java的XML API这几篇文章该讲的都讲到了，我只想补充几点：</font></p>
<p><font style="background-color: #cce8cf"><strong>一、Crimson和Xerces恩仇录</strong><br />
Crimson来自于Sun捐赠给Apache的ProjectX项目，Xerces来自IBM捐赠给Apache的XML4J项目，结果Xerces胜出，成了Apache XML小组全力开发的XML API，而Crimon已经早就不做了，如今Xerces名满天下，到处都是在用Xerces DOM和SAX解析器，只有Sun不服气，非要在JDK1.4里面使用过时的Crimson，让人感觉像是在赌气一样，真是让人可怜又可气！不过IBM发行JDK用的XML 解析器自然是Xerces。</font></p>
<p><font style="background-color: #cce8cf">由于JDK的Class Loader的优先级关系，当你采用JAXP编写XML程序的时候，即使把Xerces包引入CLASSPATH，JDK还是会顽固的使用Crimson，这一点通过打开JVM的verbose参数可以观察到。不过JDK也允许你采用其它的解析器，因此我们可以通过在JRE\lib\目录下建一个jaxp.properties的文件，来替换解析器，jaxp.properties内容如下：</font></p>
<p><font style="background-color: #cce8cf">javax.xml.parsers.DocumentBuilderFactory=org.apache.xerces.jaxp.DocumentBuilderFactoryImpl</font></p>
<p><font style="background-color: #cce8cf">javax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl</font></p>
<p><font style="background-color: #cce8cf">这样就可以使用Xerces，当然你必须还是要把Xerces包放到CLASSPATH下。</font></p>
<p><font style="background-color: #cce8cf"><strong>二、JAXP的姗姗来迟</strong><br />
Sun在XML领域总是后知后觉，等到Sun重视XML的时候，XML的API早就满天 飞了，尤其是IBM具有非常大的领先优势。不过Sun是规范的制订者，于是参考W3C的标准制订了JAXP规范。JAXP不像Xerces和Crimon那样，它只是一个spec，本身是不做任何事情的，它的作用就是提出一个统一的接口，让其它的XML API都来遵循JAXP编程，那么用JAXP写出来的程序，底层的API可以任意切换。</font></p>
<p><font style="background-color: #cce8cf">具体来说JAXP包括了几个工厂类，这就是JDK1.4里面的javax.xml.parsers 包，用来寻找符合DOM标准的XML API实现类的位置；此外JAXP还包括一整套interface，这就是JDK1.4里面的org.w3c.dom那几个包。工厂类负责加载DOM的实现类。那么加载的规则是什么呢？</font></p>
<p><font style="background-color: #cce8cf">我是通过阅读JAXP的源代码知道的，工厂类首先会根据java命令行传入的参数进行寻找，然后在根据JRE\lib\jaxp.properties中定义的实现类寻找，最后什么都找不到的话，就用Crimson。注意Crimons是由Bootstrap Class Loader来load的，如果你不通过上面两个方法来改变工厂的寻找顺序，那么铁定用Crimson了 :(</font></p>
<p><font style="background-color: #cce8cf"><strong>三、DOM解析器和DOM API</strong><br />
当你严格采用JAXP编程的时候，是遵循W3C的DOm标准的，那么在JAXP底层你实际上可以任意切换不同的DOM实现，例如Xerces，或者Crimon，再或者其它，切换方法就是配置jaxp.properties。因此JAXP就是一些标准接口而已。</font></p>
<p><font style="background-color: #cce8cf">而Xerces和Crimon也不单单是一个DOM实现那么简单，他们本身实际上也包含SAX解析器和DOM解析器。所以一个JAXP程序下面有如下层次：</font></p>
<p><font style="background-color: #cce8cf">JAXP应用程序 -&gt; JAXP接口 -&gt; Xerces DOM实现 -&gt; Xerces DOM/SAX 解析器</font></p>
<p><font style="background-color: #cce8cf">只要你用JAXP编程，那么你就可以切换到Crimson上来</font></p>
<p><font style="background-color: #cce8cf">JAXP应用程序 -&gt; JAXP接口 -&gt; Crimson DOM实现 -&gt; Crimson DOM/SAX 解析器</font></p>
<p><font style="background-color: #cce8cf">另外你也可以这样来做：</font></p>
<p><font style="background-color: #cce8cf">JAXP应用程序 -&gt; JAXP接口 -&gt; Crimson DOM实现 -&gt; Xerces DOM/SAX 解析器</font></p>
<p><font style="background-color: #cce8cf">不过如果你的程序不安装JAXP来写，那么就没有办法切换不同的DOM实现了。</font></p>
<p><font style="background-color: #cce8cf"><strong>四、不是标准的dom4j和jdom</strong><br />
W3C的DOM标准API难用的让人想撞墙，于是有一帮人开发Java专用的XML API目的是为了便于使用，这就是jdom的由来，开发到一半的时候，另一部分人又分了出来，他们有自己的想法，于是他们就去开发dom4j，形成了今天这样两个API，至于他们之间的性能，功能之比较看看上面我推荐的文章就知道了，jdom全面惨败。</font></p>
<p><font style="background-color: #cce8cf">jdom 相当于上面的 JAXP接口 ＋ Xerces DOM实现部分，它本身没有解析器，它可以使用Xerces或者Crimson的解析器，就是这样：</font></p>
<p><font style="background-color: #cce8cf">jdom应用程序 -&gt; jdom API -&gt; Xerces/Crimson解析器</font></p>
<p><font style="background-color: #cce8cf">dom4j 和jdom类似，不过他自己绑定了一个叫做Alfred2的解析器，功能不是很全，但是速度很快，当没有其它的解析器的时候，dom4j将使用Alfred2解析器，如下：</font></p>
<p><font style="background-color: #cce8cf">dom4j应用程序 -&gt; dom4j API -&gt;&nbsp; Xerces/Crimson解析器</font></p>
<p><font style="background-color: #cce8cf">或者</font></p>
<p><font style="background-color: #cce8cf">dom4j应用程序 -&gt; dom4j API -&gt;&nbsp; Alfred2解析器</font></p>
<p><font style="background-color: #cce8cf">你在SF上下载的dom4j.jar是不含 Alfred2解析器的，而dom4j-full.jar包含了 Alfred2解析器，在这种情况下，实际上你什么也不需要，光是一个dom4j-full.jar就全部都包括了。</font></p>
<p><font style="background-color: #cce8cf">因此可以看出采用dom4j/jdom编写的应用程序，已经不具备可移植性了。</font></p>
<p><font style="background-color: #cce8cf"><strong>五、小插曲</strong><br />
Sun是JAXP标准的制订者，甚至很执著的在JDK1.4里面绑定Crimson DOM实现和解析器，然后可笑的是，Sun自己的JAXM RI竟然不是用JAXP写出来的，而是dom4j，制订标准让大家遵守，自己却监守自盗，这未免太说不过去了吧！</font></p>
<p><font style="background-color: #cce8cf">BTW: Hibernate也用的是dom4j来读取XML配置文件，如今已经越来越多的程序纷纷采用dom4j，如果你不是那么在乎可移植性，我强烈建议你采用dom4j。</font></p>
<p><font style="background-color: #cce8cf"><br />
本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/rosen/articles/154194.aspx</font></p>
<img src ="http://www.blogjava.net/midstr/aggbug/297066.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2009-10-01 01:34 <a href="http://www.blogjava.net/midstr/archive/2009/10/01/297066.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于url中传中文的问题记录</title><link>http://www.blogjava.net/midstr/archive/2009/08/28/292990.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Fri, 28 Aug 2009 07:49:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2009/08/28/292990.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/292990.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2009/08/28/292990.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/292990.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/292990.html</trackback:ping><description><![CDATA[<ul>
    <li><strong>背景</strong>
    <ol>
        <li><font style="background-color: #cce8cf"><font style="background-color: #ffffff"><font style="background-color: #cce8cf"><font style="background-color: #ffffff">JSP</font></font>页面UTF-8编码</font></font>
        <li><font style="background-color: #cce8cf"><font style="background-color: #ffffff">CharsetFilter采用UTF-8编码</font></font>
        <li><font style="background-color: #cce8cf"><font style="background-color: #ffffff"></font>JS文件也是UTF-8编码（这个算么？&#8230;&#8230;）</font>
        <li><font style="background-color: #cce8cf">tomcat为5.0以上版本</font> </li>
    </ol>
    <li><font style="background-color: #cce8cf"><strong>方式</strong></font>
    <ol>
        <li><font style="background-color: #cce8cf">非AJAX方式（比如&lt;a href&gt;、form的get方式）-----通过在tomcat的server.xml中的&lt;connector&gt;节点配置URIEncoding="UTF-8"可以解决url传中文乱码的问题</font>
        <li><font style="background-color: #cce8cf">ajax方式------需要在url请求之前进行url=encodeURI(url)的操作，而我们系统中用到两种ajax,如下解释：</font>
        <ul>
            <li><font style="background-color: #cce8cf">summer提供的ajax框架，已经在提交之前进行了encodeURI和encodeURIComponent编码（具体可参考xmlhttp.js之_makeParams方法，summer/component/common/util.js之export2uri方法）</font>
            <li><font style="background-color: #cce8cf">ajaxAnywhere进行ajax请求，我准备修改aa.js，再提交之前统一做encodeURI。</font> </li>
        </ul>
        </li>
    </ol>
    </li>
</ul>
<p><font style="background-color: #cce8cf">在经过以上修改之后，大家可放心在url中传中文</font></p>
<img src ="http://www.blogjava.net/midstr/aggbug/292990.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2009-08-28 15:49 <a href="http://www.blogjava.net/midstr/archive/2009/08/28/292990.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>再次小结领域模型的种种观点 zz</title><link>http://www.blogjava.net/midstr/archive/2009/07/16/286958.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Thu, 16 Jul 2009 03:47:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2009/07/16/286958.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/286958.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2009/07/16/286958.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/286958.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/286958.html</trackback:ping><description><![CDATA[<div id="related_topics" style="position: relative" _madepositioned="true">原文：<font style="background-color: #cce8cf"><a href="http://www.javaeye.com/topic/17579">http://www.javaeye.com/topic/17579</a></font><br />
<br />
关于领域模型的设计问题，JavaEye已经组织过n多次大规模讨论，几乎每过一段时期就会出现一次。最近出现了一个新的趋势，Craig Walls在自己的blog上面写一篇文章，介绍如何使用Spring2.0和AspectJ的新特性给domain object注入DAO依赖，即如何实现post-instantiation，请见： <br />
http://jroller.com/page/habuma?entry=spring_2_0_vs_the <br />
<br />
与此同时，ajoo也给出了nuts的post-instantiation方案，请见： <br />
http://www.javaeye.com/display/ajoo/Dependency+Injection+For+Rich+Domain+Model <br />
<br />
因此，从技术手段来上说，对于Spring/Hibernate架构，Martin的Rich domin model变得可行了，那么让我们看看究竟有哪些领域模型，以及他们的优缺点： <br />
<br />
一、失血模型 <br />
<br />
失血模型请看 <br />
http://forum.javaeye.com/viewtopic.php?t=11712 <br />
中列举的第一种模型，简单来说，就是domain object只有属性的getter/setter方法，没有任何业务逻辑。 <br />
<br />
二、贫血模型 <br />
<br />
贫血模型请看 <br />
http://forum.javaeye.com/viewtopic.php?t=11712 <br />
中列举的第二种模型，简单来说，就是domain ojbect包含了不依赖于持久化的领域逻辑，而那些依赖持久化的领域逻辑被分离到Service层。 <br />
Service(业务逻辑，事务封装) --&amp;gt; DAO ---&amp;gt; domain object <br />
<br />
这种模型的优点： <br />
1、各层单向依赖，结构清楚，易于实现和维护 <br />
2、设计简单易行，底层模型非常稳定 <br />
这种模型的缺点： <br />
1、domain object的部分比较紧密依赖的持久化domain logic被分离到Service层，显得不够OO <br />
2、Service层过于厚重 <br />
<br />
三、充血模型 <br />
充血模型和第二种模型差不多，所不同的就是如何划分业务逻辑，即认为，绝大多业务逻辑都应该被放在domain object里面(包括持久化逻辑)，而Service层应该是很薄的一层，仅仅封装事务和少量逻辑，不和DAO层打交道。 <br />
Service(事务封装) ---&amp;gt; domain object &amp;lt;---&amp;gt; DAO <br />
<br />
这种模型的优点： <br />
1、更加符合OO的原则 <br />
2、Service层很薄，只充当Facade的角色，不和DAO打交道。 <br />
这种模型的缺点： <br />
1、DAO和domain object形成了双向依赖，复杂的双向依赖会导致很多潜在的问题。 <br />
2、如何划分Service层逻辑和domain层逻辑是非常含混的，在实际项目中，由于设计和开发人员的水平差异，可能导致整个结构的混乱无序。 <br />
3、考虑到Service层的事务封装特性，Service层必须对所有的domain object的逻辑提供相应的事务封装方法，其结果就是Service完全重定义一遍所有的domain logic，非常烦琐，而且Service的事务化封装其意义就等于把OO的domain logic转换为过程的Service TransactionScript。该充血模型辛辛苦苦在domain层实现的OO在Service层又变成了过程式，对于Web层程序员的角度来看，和贫血模型没有什么区别了。 <br />
<br />
四、胀血模型 <br />
基于充血模型的第三个缺点，有同学提出，干脆取消Service层，只剩下domain object和DAO两层，在domain object的domain logic上面封装事务。 <br />
domain object(事务封装，业务逻辑) &amp;lt;---&amp;gt; DAO <br />
似乎ruby on rails就是这种模型，他甚至把domain object和DAO都合并了。 <br />
该模型优点： <br />
1、简化了分层 <br />
2、也算符合OO <br />
该模型缺点： <br />
1、很多不是domain logic的service逻辑也被强行放入domain object ，引起了domain ojbect模型的不稳定 <br />
2、domain object暴露给web层过多的信息，可能引起意想不到的副作用。 <br />
<br />
在这四种模型当中，失血模型和胀血模型应该是不被提倡的。而贫血模型和充血模型从技术上来说，都已经是可行的了。但是我个人仍然主张使用贫血模型。其理由： <br />
<br />
1、参考充血模型第三个缺点，由于暴露给web层程序拿到的还是Service Transaction Script，对于web层程序员来说，底层OO意义丧失了。 <br />
<br />
2、参考充血模型第三个缺点，为了事务封装，Service层要给每个domain logic提供一个过程化封装，这对于编程来说，做了多余的工作，非常烦琐。 <br />
<br />
3、domain object和DAO的双向依赖在做大项目中，考虑到团队成员的水平差异，很容易引入不可预知的潜在bug。 <br />
<br />
4、如何划分domain logic和service logic的标准是不确定的，往往要根据个人经验，有些人就是觉得某个业务他更加贴近domain，也有人认为这个业务是贴近service的。由于划分标准的不确定性，带来的后果就是实际项目中会产生很多这样的争议和纠纷，不同的人会有不同的划分方法，最后就会造成整个项目的逻辑分层混乱。这不像贫血模型中我提出的按照是否依赖持久化进行划分，这种标准是非常确定的，不会引起争议，因此团队开发中，不会产生此类问题。 <br />
<br />
5、贫血模型的domain object确实不够rich，但是我们是做项目，不是做研究，好用就行了，管它是不是那么纯的OO呢？其实我不同意firebody认为的贫血模型在设计模型和实现代码中有很大跨越的说法。一个设计模型到实现的时候，你直接得到两个类：一个实体类，一个控制类就行了，没有什么跨越。 <br />
<br />
关于领域模型的问题，限于时间原因，暂时不能展开详谈，待有空，写篇更加详细的文章。 </div>
<img src ="http://www.blogjava.net/midstr/aggbug/286958.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2009-07-16 11:47 <a href="http://www.blogjava.net/midstr/archive/2009/07/16/286958.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>summer中jaas登录验证存在问题</title><link>http://www.blogjava.net/midstr/archive/2009/07/15/286906.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Wed, 15 Jul 2009 09:09:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2009/07/15/286906.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/286906.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2009/07/15/286906.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/286906.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/286906.html</trackback:ping><description><![CDATA[今天恰巧在一个tomcat同时发布了两个<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CF%B5%CD%B3">系统</span>：DAXT、XFXT。tomcat启动<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CB%B3%D0%F2">顺序</span>为先DAXT后XFXT，启动完成之后发现DAXT可以登录，但是XFXT不能登录（单个系统发布可以登录）。通过跟踪XFXT登录发现在UserAASAction的如下<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B4%FA%C2%EB">代码</span>处获取的SummerLoginModule为com.thunisoft.fy.security.login.FYLoginModule
<div class="blockcode"><span class="headactions" onclick="copycode($('code0'));"><span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B8%B4%D6%C6">复制</span>内容到剪贴板</span>
<h5>代码:</h5>
<code id="code0">LoginContext loginContext = new LoginContext(<br />
longinModule == null ? GlobalKey.KEY_LoginModule: longinModule, handler);<br />
loginContext.login();<br />
subject = loginContext.getSubject();<br />
request.getSession().setAttribute(GlobalKey.KEY_USER, subject);</code></div>
一般情况我们每个系统都在src目录下有一个SummerLogin.config文件，用来配置登录所用的LoginModule<br />
&nbsp;DAXT的为
<div class="quote">
<h5>引用:</h5>
<blockquote>SummerLoginModule{<br />
&nbsp; &nbsp;com.thunisoft.fy.security.login.FYLoginModule required debug=true;<br />
};</blockquote></div>
XFXT的为
<div class="quote">
<h5>引用:</h5>
<blockquote>SummerLoginModule{<br />
&nbsp; &nbsp;com.thunisoft.fy.security.login.SJFYLoginModule required debug=true;<br />
};</blockquote></div>
通过跟踪LoginContext的初始化，发现在com.sun.security.auth.login.ConfigFile.init()初始化的时候是从系统<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B1%E4%C1%BF">变量</span>获取SummerLogin.config文件并进行初始化的，如下
<div class="blockcode"><span class="headactions" onclick="copycode($('code1'));">复制内容到剪贴板</span>
<h5>代码:</h5>
<code id="code1">String extra_config = System.getProperty("java.security.auth.login.config");</code></div>
至此，就需要找到初始化<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=java">java</span>.security.auth.login.config的地方，最后在com.thunisoft.summer.sys.PropertyResource找到初始化的源码
<div class="blockcode"><span class="headactions" onclick="copycode($('code2'));">复制内容到剪贴板</span>
<h5>代码:</h5>
<code id="code2">private void setEnvironment() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Properties props = System.getProperties();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 如果运行<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%BB%B7%BE%B3">环境</span>中已经存在，则不配置<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (null == props.getProperty(GlobalKey.LOGIN_CONFIG)) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String config = null;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; config = SysConfiguration.getInstance().getProperty(<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; GlobalKey.LOGIN_CONFIG);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; catch(MissingResourceException mre){<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; logger.info(GlobalKey.LOGIN_CONFIG + ": Not Configured.");<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 如果配置<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CE%C4%BC%FE">文件</span>中没有配置则用缺省值<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (null == config || "".equalsIgnoreCase(config.trim())) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; URL url = PropertyResource.class<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .getResource(GlobalKey.LOGIN_CONFIG_MODULE);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (null != url)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; props.setProperty(GlobalKey.LOGIN_CONFIG, url.getFile());<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; props.setProperty(GlobalKey.LOGIN_CONFIG, config);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; }</code></div>
显然<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CE%CA%CC%E2">问题</span>原因在于系统变量java.security.auth.login.config只能存在一份，启动DAXT时候已经初始化，后续启动XFXT的时候已经不能初始化XFXT的SummerLoginModule。而在XFXT登录的时候，实际上就只能获取到DAXT的LoginModule了。<br />
&nbsp; &nbsp;&nbsp; &nbsp; 当然如果几个系统使用的是同一个LoginModule类，上述问题就不会存在了。目前有三个LoginModule：FYLoginModule、SJFYLoginModule StatLoginModule，如果把这三个类合成为一个公用的LoginModule倒是可以解决问题，但是感觉很怪异。。。。<br />
<img src ="http://www.blogjava.net/midstr/aggbug/286906.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2009-07-15 17:09 <a href="http://www.blogjava.net/midstr/archive/2009/07/15/286906.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>工作流jbpm3.1.2导致数据库连接池满的问题</title><link>http://www.blogjava.net/midstr/archive/2009/06/22/283619.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Mon, 22 Jun 2009 09:38:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2009/06/22/283619.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/283619.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2009/06/22/283619.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/283619.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/283619.html</trackback:ping><description><![CDATA[背景：&nbsp;<br />
&nbsp;&nbsp;&nbsp; XX系统实施一段时间之后，出现<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CA%FD%BE%DD%BF%E2"><span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CA%FD%BE%DD">数据</span>库</span>连接池满，第一次通过修改if(con!=null &amp;&amp; con.isClosed()){con.close();}这样的逻辑<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B4%ED%CE%F3">错误</span>解决部分<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CE%CA%CC%E2">问题</span>。第二次通过彻底复查<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B4%FA%C2%EB">代码</span>，修改了connection、session没有释放的问题，基本上保证我们自己写的代码没有数据库连接不释放的问题。但是临近近期还是出现连接池满的问题。。。<br />
<br />
过程：<br />
&nbsp; &nbsp; 从日志看，除了有大量工作流<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B1%A8%B4%ED">报错</span>之外程序很少有异常，类似如下：
<div class="quote">
<h5>引用:</h5>
<blockquote>2009-06-12 15:44:34,187 [http-80-Processor44] [org.hibernate.event.def.AbstractFlushingEventListener] [ERROR] - Could not synchronize database state with session<br />
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.graph.exe.Token#35000000000033432]<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;..............................................<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;at org.jbpm.persistence.db.DbPersistenceService.close(DbPersistenceService.java:180)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;..............................................<br />
2009-06-12 15:44:34,187 [http-80-Processor44] [org.jbpm.svc.Services] [ERROR] - problem closing service 'persistence'<br />
<font color="red">org.jbpm.persistence.JbpmPersistenceException: couldn't flush hibernate session</font><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;at org.jbpm.persistence.db.DbPersistenceService.close(DbPersistenceService.java:182)<br />
<br />
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.graph.exe.Token#35000000000033432]<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;at org.jbpm.persistence.db.DbPersistenceService.close(DbPersistenceService.java:180)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;... 54 more</blockquote></div>
最开始基本确定了是工作流报错导致数据库连接池不释放，理由：<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;a、上面的错和hibernate的session有关<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;b、在<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=sybase">sybase</span>执行sp_who发现大量不释放连接所占用的库为DB_LC，而这个库就是工作流相关的库。<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;c、从sybase的sysprocesses表查看，不释放连接是每天新增10-30不等，随机统计了日志某天的如前所述的异常为27个，而从数据库端统计该天新增连接也是27个。<br />
&nbsp; &nbsp;&nbsp;&nbsp;因为自己对工作流不熟悉，所以每次都是把情况反映给相关人员处理。前几天去客户现场正好抓取了一下不释放连接正在执行的<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=sql">sql</span>，基本都是<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%C2%D2%C2%EB">乱码</span>，如下：
<div class="quote">
<h5>引用:</h5>
<blockquote>DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role. <br />
SQL <span class="t_tag" onclick="tagshow(event)" href="tag.php?name=Text">Text</span>: ! <br />
DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role. <br />
(1 row affected)<br />
47<br />
DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role. <br />
SQL Text: * <br />
DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role. <br />
(1 row affected)<br />
49<br />
DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role. <br />
SQL Text:  <br />
DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role. <br />
(1 row affected)</blockquote></div>
这个结果用处不大，很好奇这个问题，所以找了一份工作流的源码，找到报错的类DbPersistenceService.close方法，如下：
<div class="blockcode"><span class="headactions" onclick="copycode($('code0'));"><span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B8%B4%D6%C6">复制</span>内容到剪贴板</span>
<h5>代码:</h5>
<code id="code0">public void close() {<br />
&nbsp; &nbsp; if ( (session!=null)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&amp;&amp; (transaction==null)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&amp;&amp; (isRollbackOnly)<br />
&nbsp; &nbsp;&nbsp; &nbsp; ) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;throw new JbpmException("setRollbackOnly was invoked while configuration specifies user managed transactions");<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; if (messagingSession!=null) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;messagingSession.closeOpenIterators();<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; if (schedulerSession!=null) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;schedulerSession.closeOpenIterators();<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; if ( (isTransactionEnabled)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&amp;&amp; (transaction!=null) <br />
&nbsp; &nbsp;&nbsp; &nbsp; ) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;if (isRollbackOnly) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;try {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; log.debug("rolling back hibernate transaction");<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; mustSessionBeFlushed = false; // flushing updates that will be rolled back is not very clever :-) <br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; transaction.rollback();<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;} catch (Exception e) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; throw new JbpmPersistenceException("couldn't rollback hibernate session", e);<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}<br />
&nbsp; &nbsp;&nbsp; &nbsp;} else {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;try {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; log.debug("committing hibernate transaction");<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; mustSessionBeFlushed = false; // commit does a flush anyway <br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; transaction.commit();<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;} catch (Exception e) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; try {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;// if the commit fails, we must do a rollback<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;transaction.rollback();<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; } catch (Exception e2) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;// if the rollback fails, we did what we could and you're in <br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;// deep shit :-(<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;log.error("problem rolling back after failed commit", e2);<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; }<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; throw new JbpmPersistenceException("couldn't commit hibernate session", e);<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}<br />
&nbsp; &nbsp;&nbsp; &nbsp;}<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; if (mustSessionBeFlushed) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;try {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;log.debug("flushing hibernate session");<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;session.flush();<br />
&nbsp; &nbsp;&nbsp; &nbsp;} catch (Exception e) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;throw new JbpmPersistenceException("couldn't flush hibernate session", e);<br />
&nbsp; &nbsp;&nbsp; &nbsp;}<br />
&nbsp; &nbsp; }&nbsp; &nbsp; <br />
&nbsp; &nbsp; if (mustSessionBeClosed) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;try {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;log.debug("closing hibernate session");<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;session.close();<br />
&nbsp; &nbsp;&nbsp; &nbsp;} catch (Exception e) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;throw new JbpmPersistenceException("couldn't close hibernate session", e);<br />
&nbsp; &nbsp;&nbsp; &nbsp;}<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; if (mustConnectionBeClosed) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;try {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;log.debug("closing <span class="t_tag" onclick="tagshow(event)" href="tag.php?name=jdbc">jdbc</span> connection");<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;connection.close();<br />
&nbsp; &nbsp;&nbsp; &nbsp;} catch (Exception e) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;throw new JbpmPersistenceException("couldn't close jdbc connection", e);<br />
&nbsp; &nbsp;&nbsp; &nbsp;}<br />
&nbsp; &nbsp; }<br />
&nbsp;&nbsp;}</code></div>
一看真是吓一跳，程序在执行到session.flush();时候报错的话，如果mustSessionBeClosed为true根本不能执行到后面的session.close()，会导致数据库连接不释放的问题&#8230;&#8230;基本确定问题所在了，就在本地试着复现一下问题（因为前面所描述的异常在<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%BF%AA%B7%A2">开发</span><span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%BB%B7%BE%B3">环境</span>无法复现，所以只能强制在flush后抛异常），果然不出意料。<br />
&nbsp; &nbsp;&nbsp;&nbsp;因为这个是jbpm3.1.2版本，觉得应该是jbpm的<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=bug">bug</span>吧，就又下载了一份jbpm3.3.0GA源码，找到DbPersistenceService.close()方法：
<div class="blockcode"><span class="headactions" onclick="copycode($('code1'));">复制内容到剪贴板</span>
<h5>代码:</h5>
<code id="code1">&nbsp;&nbsp;public void close() {<br />
<br />
&nbsp; &nbsp; if ( (session!=null)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&amp;&amp; !isTransactionActive()<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&amp;&amp; (isRollbackOnly())<br />
&nbsp; &nbsp;&nbsp; &nbsp; ) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;throw new JbpmException("setRollbackOnly was invoked while configuration specifies user managed transactions");<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; if ( (isTransactionEnabled)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&amp;&amp; (transaction!=null) <br />
&nbsp; &nbsp;&nbsp; &nbsp; ) {<br />
<br />
&nbsp; &nbsp;&nbsp; &nbsp;if (! isRollbackOnly()) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;Exception commitException = commit();<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;if (commitException!=null) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; rollback();<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; closeSession();<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; closeConnection();<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; throw new JbpmPersistenceException("hibernate commit failed", commitException);<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp; &nbsp;&nbsp; &nbsp;} else { // isRollbackOnly==true<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;Exception rollbackException = rollback();<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;if (rollbackException!=null) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; closeSession();<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; closeConnection();<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; throw new JbpmPersistenceException("hibernate rollback failed", rollbackException);<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}<br />
&nbsp; &nbsp;&nbsp; &nbsp;}<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; Exception flushException = flushSession();<br />
&nbsp; &nbsp; if (flushException!=null) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;// JBPM-1465 transaction has been either committed or rolled back at this point<br />
&nbsp; &nbsp;&nbsp; &nbsp;// on the other hand, it is possible that no transaction is underway<br />
&nbsp; &nbsp;&nbsp; &nbsp;// hence rolling back here is redundant and possibly dangerous<br />
&nbsp; &nbsp;&nbsp; &nbsp;closeSession();<br />
&nbsp; &nbsp;&nbsp; &nbsp;closeConnection();<br />
&nbsp; &nbsp;&nbsp; &nbsp;throw new JbpmPersistenceException("hibernate flush failed", flushException);<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; Exception closeSessionException = closeSession();<br />
&nbsp; &nbsp; if (closeSessionException!=null) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;closeConnection();<br />
&nbsp; &nbsp;&nbsp; &nbsp;throw new JbpmPersistenceException("hibernate close session failed", closeSessionException);<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; Exception closeConnectionException = closeConnection();<br />
&nbsp; &nbsp; if (closeConnectionException!=null) {<br />
&nbsp; &nbsp;&nbsp; &nbsp;throw new JbpmPersistenceException("hibernate close connection failed", closeConnectionException);<br />
&nbsp; &nbsp; }<br />
&nbsp;&nbsp;}</code></div>
果然在3.3.0版本中，当flush、close等操作出现异常时候，都会调用closeSession()和closeConnection()以保证连接正常释放。照猫画虎在该方法写了关闭session和connection的方法，准备月底发布新版本试试。<br />
<br />
结论：<br />
&nbsp;&nbsp;&nbsp;XX系统工作流jbpm3.1.2存在连接不释放的bug，当然前提是程序执行数据库操作报错的情况下（如session.flush）。虽然解决了连接不释放的问题，但是这个关于这个报错的深层原因还没搞清楚。另外和相关人员确认，工作流的这些异常可以cacth掉，到目前为止除了引起连接不释放之外，没有发现其他问题。<br />
<img src ="http://www.blogjava.net/midstr/aggbug/283619.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2009-06-22 17:38 <a href="http://www.blogjava.net/midstr/archive/2009/06/22/283619.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tomcat5报Post too large的错</title><link>http://www.blogjava.net/midstr/archive/2009/06/22/283618.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Mon, 22 Jun 2009 09:36:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2009/06/22/283618.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/283618.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2009/06/22/283618.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/283618.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/283618.html</trackback:ping><description><![CDATA[在用户实际<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%BB%B7%BE%B3">环境</span>的tomcat日志（localhost_log.2009-06-22.txt）看到下面这个错
<div class="quote">
<h5>引用:</h5>
<blockquote>2009-06-22 12:39:41 StandardWrapperValve[ajax]: Servlet.service() for servlet ajax threw exception<br />
java.lang.IllegalStateException: Post too large<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.coyote.tomcat5.CoyoteRequest.parseRequestParameters(CoyoteRequest.java:2405)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.coyote.tomcat5.CoyoteRequest.getParameter(CoyoteRequest.java:1073)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.coyote.tomcat5.CoyoteRequestFacade.getParameter(CoyoteRequestFacade.java:265)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.ajaxanywhere.AAUtils.isAjaxRequest(AAUtils.java:34)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.ajaxanywhere.AAFilter.doFilter(AAFilter.java:45)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:186)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at com.thunisoft.summer.web.filter.CharsetFilter.doFilter(CharsetFilter.java:48)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:186)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:214)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:198)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:152)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:118)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:799)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:705)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:577)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)<br />
&nbsp; &nbsp; &nbsp; &nbsp; at java.lang.Thread.run(Thread.java:534)</blockquote></div>
在另外一个catalina_log.2009-06-22.txt日志<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CE%C4%BC%FE">文件</span>中，有下面这句话
<div class="quote">
<h5>引用:</h5>
<blockquote>2009-06-22 12:39:41 CoyoteRequest Parameters were not parsed because the <span class="t_tag" onclick="tagshow(event)" href="tag.php?name=size">size</span> of the posted data was too big. Use the maxPostSize attribute of the connector to resolve this if the application should accept large POSTs.</blockquote></div>
上网查了一下，说是tomcat默认接收的POST提交<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CA%FD%BE%DD">数据</span>最大为2M，如果没有修改过配置post提交的数据超过这个就报上面的错了。这个配置在%tomcat-5.0.28%conf\server.xml中的我们用到的connector节点的属性。其中tomcat的文档是这么描述的
<div class="quote">
<h5>引用:</h5>
<blockquote>maxPostSize<br />
&nbsp; &nbsp;The maximum size in bytes of the POST which will be handled by the container FORM URL parameter parsing. The feature can be disbled by setting this attribute to a value inferior or equal to 0. If not specified, this attribute is set to 2097152 (2 megabytes).</blockquote></div>
准备复现<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CE%CA%CC%E2">问题</span>，第一个想到的就是XX系统文书保存到<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CA%FD%BE%DD%BF%E2">数据库</span>，并且为ajax的post方式提交（文件上传不会报这个错）
<div class="blockcode">
<h5><span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B4%FA%C2%EB">代码</span>:</h5>
<code id="code0">var map = new Map();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; map.put("key", "fy.doceditor.updateDoc");<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; map.put("jzjd", jzjd);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; map.put("caseType", caseType);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; map.put("caseId", caseId);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; map.put("docId", docId);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; map.put("wsxh", wsxh);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; map.put("doc", docDetail);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var query = new QueryObj(map,updated);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; query.send();</code></div>
所以创建了一个文书，粘贴了一个8M的word文书，点保存之后报js错。把上面这个docDetail保存成文件，发现大小为7.94 MB (8,332,134 字节)，检查日志有post too large错。<br />
按照文档描述，修改xml文件配置如下：
<div class="quote">
<h5>引用:</h5>
<blockquote>&lt;Connector port="8080"<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;maxThreads="150" minSpareThreads="25" maxSpareThreads="75"<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;enableLookups="false" redirectPort="8443" acceptCount="100"<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;debug="0" connectionTimeout="20000"<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;disableUploadTimeout="true" <font color="red">maxPostSize="0"</font>/&gt;</blockquote></div>
问题得到解决。<br />
<br />
&nbsp; &nbsp;一般来说大部分post提交都是没有问题的，但是还是要仔细考虑一下项目是否会出现这种情况，最好是修改一下tomcat的配置。有时候需要注意这个异常只会记录在tomcat的日志文件中。<br />
<img src ="http://www.blogjava.net/midstr/aggbug/283618.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2009-06-22 17:36 <a href="http://www.blogjava.net/midstr/archive/2009/06/22/283618.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>理解 SET CHAINED command not allowed within multi-statement transaction. (zz)</title><link>http://www.blogjava.net/midstr/archive/2009/03/02/257372.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Mon, 02 Mar 2009 09:48:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2009/03/02/257372.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/257372.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2009/03/02/257372.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/257372.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/257372.html</trackback:ping><description><![CDATA[在 Sybase ASE 实际应用中，特别是在 ASE + <span class="twikiNewLink">J2EE<a title="创建这个主题" href="http://www.sybaseclub.org/twiki/bin/edit.cgi/ASE/J2EE?topicparent=ASE.ASEProgrammingFAQ" rel="nofollow">?</a></span> 应用中，较容易出现 <u>SET CHAINED command not allowed within multi-statement transaction.</u>的异常（尽管到版本 15.0.1 为止，ASE 并不支持异常机制，但本文为了方便，统一采用&#8220;异常&#8221;一词）。有的开发人员认为这是 Sybase 数据库的问题；有的认为是多次调用 setAutoCommit() 方法的问题；有的开发人员则认为这是 jConnect 的问题，甚至从 jConnect 的代码上直接屏蔽此异常。<br />
　　然而，SET CHAINED 异常倒底是怎样产生的？<br />
　　<strong>一、数据库层</strong><br />
　　首先，让我们看看 <strong>set chained</strong>。下面的文字片段摘自《ASE 12.5.2 Reference Manual: Commands》，Page 430：
<pre style="font-size: 10pt; padding-bottom: 0px; background-color: menu">chained
begins a transaction just before the first data retrieval or data modification
statement at the beginning of a session and after a transaction ends. In
chained mode, Adaptive Server implicitly executes a begin transaction
command before the following statements: delete, fetch, insert, lock table,
open, select, and update. You cannot execute set chained within a transaction.
</pre>
　　从此段文字可以得知，当 set chained on 后，delete、fetch、insert、lock table、open、select 以及 update 语句将自动启动一个事务，并要求显式的完成事务，即明确地调用 commit/rollback。同时，在事务中，不允许设置 chained 模式。<br />
　　下面的 sql 代码片断将说明在数据库层上 SET CHAINED 错误信息是如何产生的。
<pre style="font-size: 10pt; padding-bottom: 0px; background-color: menu">1&gt; set chained on
2&gt; go
1&gt; set chained on
2&gt; go
1&gt; begin tran
2&gt; go
1&gt;
</pre>
　　<strong>似乎</strong>多次调用 set chained 并不会产生异常。接下来，<br />
<pre style="font-size: 10pt; padding-bottom: 0px; background-color: menu">1&gt; set chained on
2&gt; go
Msg 226, Level 16, State 1:
Server 'FLYBEAN', Line 1:
SET CHAINED command not allowed within multi-statement transaction.
1&gt; set chained off
2&gt; go
Msg 226, Level 16, State 1:
Server 'FLYBEAN', Line 1:
SET CHAINED command not allowed within multi-statement transaction.
1&gt;
</pre>
　　显然，处于事务环境下，调用 set chained 是会发生异常的，这一点手册上也非常明确的指出了。但为什么前面的片断中两次连续调用 set chained 却不会产生异常呢？请注意文档上这一句：<em>Adaptive Server implicitly executes a begin transaction command <strong>before</strong> the following statements: </em>。<br />
　　重建一个数据库连接，从头开始：<br />
<pre style="font-size: 10pt; padding-bottom: 0px; background-color: menu">1&gt; set chained on
2&gt; go
1&gt; select 1
2&gt; go
-----------
1
(1 row affected)
1&gt; set chained on
2&gt; go
Msg 226, Level 16, State 1:
Server 'FLYBEAN', Line 1:
SET CHAINED command not allowed within multi-statement transaction.
1&gt; set chained off
2&gt; go
Msg 226, Level 16, State 1:
Server 'FLYBEAN', Line 1:
SET CHAINED command not allowed within multi-statement transaction.
1&gt;
</pre>
　　在执行 select 1 之前，数据库自动启动了一笔事务，因此不能再执行 set chained。接下来，完成隐式启动的事务：<br />
<pre style="font-size: 10pt; padding-bottom: 0px; background-color: menu">1&gt; rollback
2&gt; go
1&gt; set chained off
2&gt; go
1&gt;
</pre>
　　<strong>二、J2EE 层</strong><br />
　　J2EE 应用中，一些轻量级的数据访问层实现采用 Connection 的setAutoCommit(false) + commit()/rollback() 的方式来管理事务。通过对 jConnect 的反编译以及对 spt_mda 数据的分析，可以得知 setAutoCommit(true) = SET CHAINED OFF；setAutoCommit(false) = SET CHAINED ON，下图以顺序图展示调用 setAutoCommit()&nbsp; 方法时，实际发生的交互。<br />
<img src="http://www.sybaseclub.org/blog/wp-content/uploads/2007/01/conn.jpg"  alt="" />
<h2><a name="理解 SET CHAINED command not all"></a><a name="SetChainedNotAllowed">理解 SET CHAINED command not allowed within multi-statement transaction.</a> </h2>
<br />
　　另一方面，J2EE 应用中大多采用了连接池。应用在调用 Connection.close() 方法时，实际上并没有真正地关闭连接，而是将连接回收到池中。假设连接的初态是 chained off。如果应用在取得连接后调用该连接的 setAutoCommit(false) 方法来启动事务，在未完成事务的情况下，通过 close() 方法回到池中，则当该连接下一次被取出并调用 setAutoCommit(false) 方法时就会抛出异常。见下图：<br />
<img src="http://www.sybaseclub.org/blog/wp-content/uploads/2007/01/setChainedException.JPG"  alt="" /><br />
　　通过上面的分析，理解了产生此异常的原因，就很容易避免此异常，即调用了 setAutoCommit(false) 后，必须显示地完成事务，即使只是执行了一个select语句。同时，关闭连接前，应显式地调用 setAutoCommit(true)。或许有的程序员会认为麻烦，但别忘记&#8220;完壁归赵&#8221;是资源借用者的义务。 
<img src ="http://www.blogjava.net/midstr/aggbug/257372.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2009-03-02 17:48 <a href="http://www.blogjava.net/midstr/archive/2009/03/02/257372.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>url中jsessionid引起的一个问题</title><link>http://www.blogjava.net/midstr/archive/2009/02/25/256596.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Wed, 25 Feb 2009 05:40:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2009/02/25/256596.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/256596.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2009/02/25/256596.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/256596.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/256596.html</trackback:ping><description><![CDATA[XX系统登录之后，偶尔在用户那会出现这个现象：<br />
<span id="attach_4308" onmouseover="showMenu(this.id, 0, 1)" style="display: none; left: 214px; position: absolute; top: 332px"><img alt="" src="http://172.16.1.3:8080/bbs/images/default/attachimg.gif" border="0" /></span>&nbsp;<a href="http://172.16.1.3:8080/bbs/viewthread.php?tid=39412&amp;highlight=%2B%C0%EE%D2%AB%B8%DA###zoom"></a> <br />
登录的逻辑是这样的：<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B5%C7%C2%BD">登陆</span>主<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%BD%E7%C3%E6">界面</span>之后，在主界面html执行到最后的时候，使用<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=windows">windows</span>.open打开一个弹出窗口，去<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B7%FE%CE%F1%C6%F7">服务器</span>取一些需要的<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CA%FD%BE%DD">数据</span>。<br />
但是偶尔用户那会出现弹出窗口又定位到登陆窗口了（<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=summer">summer</span>中使用filter对请求过滤，发现没有登陆的话会重新定位到登陆窗口）。<br />
这里明明是的刚登陆的程序，却出现没有登陆的现象。。这个现象在用户那一直就存在，一直也没找到原因。<br />
今天在和三期应服推广人员的沟通中无意了解到，用户习惯使用给登陆界面建立一个桌面快捷方式，一般操作如下：<br />
在ie地址栏输入&#8220;http://localhost:8080/spxt&#8221;，这个时候请求完成之后定位到了登陆<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%D2%B3%C3%E6">页面</span>，但是ie地址栏已经变成<br />
&#8220;http://localhost:8080/spxt/common/summer/jsp/login/register03.jsp;jsessionid=CA0CA7E455535994E523B01357B42214&#8221;<br />
此时直接在这个ie窗口登陆是没有<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CE%CA%CC%E2">问题</span>的。而用户一般都是在这个页面点右键，选择创建快捷方式，<br />
这个时候就有一个问题，用户的快捷方式超<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%C1%B4%BD%D3">链接</span>实际上指向的是后面那个带有jsessionid的很长很长的url。<br />
如果此时从桌面点击这个超链接的快捷方式打开ie进行登陆，就很容易复现文章开始的那个截图现象了，如果我修改快捷方式属性，把超链接的<br />
sessionid去掉就没有问题了。（这里描述不是很准确，比如重启一次tomcat的话就又不会复现了）。<br />
后来在后台打印每次使用的sessionid，发现如果从快捷方式登陆的话，真正的登录session就是jsessionid所代表的那个session，而后来ajax<br />
请求的是和服务器新建了连接，发现session没有登陆信息就定位到登陆页面了。<br />
<br />
这里在服务器端&#8220;可能&#8221;是产生两个session的概念：一个是本次真正登录的session；另外是一个空的session。而在ajax异步请求的时候，<br />
实际上用的就是后面这个空的session，这样发现没有登陆就重新定位到登陆页面了？<br />
<br />
后面原因的分析完全是自己的猜测，具体望大家指教一下：）<br />
<br />
解决问题可以这样：1、帮用户把那个快捷方式的jsessionid去掉。<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;2、写一个filter，对于是登陆请求的，把jsessionid去掉。<br />
<br />
ps：以上问题对于收藏夹存在同样问题。<br />
<br />
<br />
看了帖子终于明白jsessionid是怎么来的了~多谢<br />
在struts的org.apache.struts.action.RequestProcessor.processForwardConfig()中找到了如下代码：<br />
response.sendRedirect(response.encodeRedirectURL(uri));<br />
不过感觉一般情况还是不要去掉jsessionid比较好，对于特殊情况的需要特殊去掉，基本还是利大于弊。<br />
<img src ="http://www.blogjava.net/midstr/aggbug/256596.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2009-02-25 13:40 <a href="http://www.blogjava.net/midstr/archive/2009/02/25/256596.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>easerver6 jvm设置，解决OutOfMemory问题</title><link>http://www.blogjava.net/midstr/archive/2008/11/12/240122.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Wed, 12 Nov 2008 08:58:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/11/12/240122.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/240122.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/11/12/240122.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/240122.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/240122.html</trackback:ping><description><![CDATA[%Easerver%/bin目录下 djc-seten.bat(<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=linux">linux</span>下为.sh)，设置<br />
<br />
set DJC_JVM_MAXHEAP=512M<br />
set DJC_JVM_MINHEAP=256M<br />
<br />
在easerver上碰到了OutOfMemory的问题，参考上面的解决办法：<br />
set DJC_JVM_MAXHEAP=512M <br />
set DJC_JVM_MINHEAP=512M<br />
启动easerver6.0之后会发现进程之中有两个java.exe和一个javaw.exe，如下图所示：<br />
<span id="attach_3796" onmouseover="showMenu(this.id, 0, 1)" style="display: none; left: 214px; position: absolute; top: 659px"><img alt="" src="http://172.16.1.3:8080/bbs/images/default/attachimg.gif" border="0" /></span>&nbsp;<img height="191" alt="" src="http://www.blogjava.net/images/blogjava_net/midstr/11.PNG" width="565" border="0" /> <br />
则发现两个java.exe进程分配内存都是512M左右，显然有一些问题，这里怎么会有两个相同的进程，并且两个内存分配都是根据上面的配置来的，哪个是我们用的<br />
从easerver文档中发现，有另外一个地方可以配置jvm的启动参数，即web控制台如下图所示的java Startup Options：<br />
<span id="attach_3793" onmouseover="showMenu(this.id, 0, 1)" style="display: none; left: 214px; position: absolute; top: 912px"><img alt="" src="http://172.16.1.3:8080/bbs/images/default/attachimg.gif" border="0" /></span>&nbsp; <img height="677" alt="" src="http://www.blogjava.net/images/blogjava_net/midstr/22.PNG" width="1147" border="0" /><br />
设置成如下图所示的启动参数：<br />
<span id="attach_3794" onmouseover="showMenu(this.id, 0, 1)" style="display: none; left: 214px; position: absolute; top: 1627px"><img alt="" src="http://172.16.1.3:8080/bbs/images/default/attachimg.gif" border="0" /></span>&nbsp; <img height="645" alt="" src="http://www.blogjava.net/images/blogjava_net/midstr/33.PNG" width="1127" border="0" /><br />
然后重启easerver，发现内存分配的变化如下：<br />
<span id="attach_3795" onmouseover="showMenu(this.id, 0, 1)" style="display: none; left: 214px; position: absolute; top: 2310px"><img alt="" src="http://172.16.1.3:8080/bbs/images/default/attachimg.gif" border="0" /></span>&nbsp; <img height="191" alt="" src="http://www.blogjava.net/images/blogjava_net/midstr/44.PNG" width="565" border="0" /><br />
显然，两个java进程，有一个的内存是根据开始的set配置确定的，另外一个是根据我们在控制台配置。<br />
我个人理解是：这两个java进程，一个是easerver自己使用的，一个是我们发布程序使用的。<br />
如果我们没有在控制台设置具体的jvm参数，则发布程序使用的jvm参数默认会和easerver自己使用的相同（即通过set设置的）<br />
如果在easerver发布过程中碰到OutOfMemory，即发布本身需要很大的内存，比如包很大等等，修改set的那个jvm参数即可。<br />
如果是我们的应用程序使用过程中OutOfMemory，则需要在控制台直接设置jvm参数，控制比较精确（例如-server -Xms1024m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=128m）<br />
<br />
另外根据easerver的文档，好像set DJC_JVM_OPTIONS="-server -Xms1024m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=128m"<br />
应该也可以的，但是我试了几次（包括把引号去掉）都没有成功&#8230;&#8230;<br />
<br />
总结一下：就是一般来说不用修改set的这个jvm启动参数，使用默认配置即可，只需要根据实际情况到控制台精确修改一下我们的应用程序使用的jvm参数。<br />
<img src ="http://www.blogjava.net/midstr/aggbug/240122.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-11-12 16:58 <a href="http://www.blogjava.net/midstr/archive/2008/11/12/240122.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对jvm内存的一些理解</title><link>http://www.blogjava.net/midstr/archive/2008/09/21/230292.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Sun, 21 Sep 2008 12:13:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/09/21/230292.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/230292.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/09/21/230292.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/230292.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/230292.html</trackback:ping><description><![CDATA[首先引用jdk1.5api的doc：<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000"><strong>内存</strong>&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />Java&nbsp;虚拟机的内存系统管理以下类型的内存：<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><strong>1.&nbsp;堆&nbsp;<br />
</strong><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />Java&nbsp;虚拟机具有一个堆，堆是运行时数据区域，所有类实例和数组的内存均从此处分配。堆是在&nbsp;Java&nbsp;虚拟机启动时创建的。对象的堆内存由称为垃圾回收器&nbsp;的自动内存管理系统回收。<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />堆的大小可以固定，也可以扩大和缩小。堆的内存不需要是连续空间。<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><strong>2.&nbsp;非堆内存<br />
</strong><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />Java&nbsp;虚拟机管理堆之外的内存（称为非堆内存）。&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />Java&nbsp;虚拟机具有一个由所有线程共享的方法区。方法区属于非堆内存。它存储每个类结构，如运行时常数池、字段和方法数据，以及方法和构造方法的代码。它是在&nbsp;Java&nbsp;虚拟机启动时创建的。&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />方法区在逻辑上属于堆，但&nbsp;Java&nbsp;虚拟机实现可以选择不对其进行回收或压缩。与堆类似，方法区的大小可以固定，也可以扩大和缩小。方法区的内存不需要是连续空间。<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />除了方法区外，Java&nbsp;虚拟机实现可能需要用于内部处理或优化的内存，这种内存也是非堆内存。例如，JIT&nbsp;编译器需要内存来存储从&nbsp;Java&nbsp;虚拟机代码转换而来的本机代码，从而获得高性能。<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div>
&nbsp; 在网上找到如下的jsp来监视内存使用情况：<br />
&nbsp;
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5">@&nbsp;page&nbsp;import</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">java.lang.management.*</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;</span><span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #000000"><br />
</span><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5">@&nbsp;page&nbsp;import</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">java.util.*</span><span style="color: #000000; background-color: #f5f5f5">"</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;</span><span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">html</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">head</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">title</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">JVM&nbsp;Memory&nbsp;Monitor</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">title</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">head</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">body</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">table&nbsp;</span><span style="color: #ff0000">border</span><span style="color: #0000ff">="0"</span><span style="color: #ff0000">&nbsp;width</span><span style="color: #0000ff">="100%"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td&nbsp;</span><span style="color: #ff0000">colspan</span><span style="color: #0000ff">="2"</span><span style="color: #ff0000">&nbsp;align</span><span style="color: #0000ff">="center"</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">h3</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Memory&nbsp;MXBean</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">h3</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td<br />
</span><span style="color: #ff0000">width</span><span style="color: #0000ff">="200"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Heap&nbsp;Memory&nbsp;Usage</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;</span><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5"><br />
ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()<br />
</span><span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Non-Heap&nbsp;Memory<br />
Usage</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;</span><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5"><br />
ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()<br />
</span><span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td&nbsp;</span><span style="color: #ff0000">colspan</span><span style="color: #0000ff">="2"</span><span style="color: #0000ff">&gt;</span><span style="color: #ff0000">&amp;nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td&nbsp;</span><span style="color: #ff0000">colspan</span><span style="color: #0000ff">="2"</span><span style="color: #ff0000">&nbsp;align</span><span style="color: #0000ff">="center"</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">h3</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Memory&nbsp;Pool&nbsp;MXBeans</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">h3</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;iter&nbsp;</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;ManagementFactory.getMemoryPoolMXBeans().iterator();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; background-color: #f5f5f5">while</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;(iter.hasNext())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MemoryPoolMXBean&nbsp;item&nbsp;</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;(MemoryPoolMXBean)&nbsp;iter.next();<br />
</span><span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td&nbsp;</span><span style="color: #ff0000">colspan</span><span style="color: #0000ff">="2"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">table&nbsp;</span><span style="color: #ff0000">border</span><span style="color: #0000ff">="0"</span><span style="color: #ff0000">&nbsp;width</span><span style="color: #0000ff">="100%"</span><span style="color: #ff0000">&nbsp;style</span><span style="color: #0000ff">="border:&nbsp;1px&nbsp;#98AAB1&nbsp;solid;"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td&nbsp;</span><span style="color: #ff0000">colspan</span><span style="color: #0000ff">="2"</span><span style="color: #ff0000">&nbsp;align</span><span style="color: #0000ff">="center"</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">b</span><span style="color: #0000ff">&gt;</span><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;item.getName()&nbsp;</span><span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">b</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td&nbsp;</span><span style="color: #ff0000">width</span><span style="color: #0000ff">="200"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Type</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;</span><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;item.getType()&nbsp;</span><span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Usage</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;</span><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;item.getUsage()&nbsp;</span><span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Peak&nbsp;Usage</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;</span><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;item.getPeakUsage()&nbsp;</span><span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">Collection&nbsp;Usage</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;</span><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5">=</span><span style="color: #000000; background-color: #f5f5f5">&nbsp;item.getCollectionUsage()&nbsp;</span><span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">table</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;&lt;</span><span style="color: #800000">td&nbsp;</span><span style="color: #ff0000">colspan</span><span style="color: #0000ff">="2"</span><span style="color: #0000ff">&gt;</span><span style="color: #ff0000">&amp;nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">td</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">tr</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #000000; background-color: #ffff00">&lt;%</span><span style="color: #000000; background-color: #f5f5f5">}&nbsp;</span><span style="color: #000000; background-color: #ffff00">%&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">table</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">body</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">html</span><span style="color: #0000ff">&gt;</span></div>
<br />
使用的结果（JDK1.5）正如doc描述：<br />
&nbsp;&nbsp; <img height="163" alt="" src="http://www.blogjava.net/images/blogjava_net/midstr/memory.png" width="358" border="0" /><br />
从检测的结果来看，non-heap memory中，包含了perm gen<font style="background-color: #cce8cf">和一部分jvm自用的内存</font><br />
其中heap memory的最大值即我们指定的启动参数 -Xmx1024m所指定的1024m<br />
而Perm Gen的最大值即为我们指定的启动参数 -<font style="background-color: #cce8cf">XX:MaxPermSize=128m 所指定的128m（不指定默认为64m）<br />
一般的OutOfMemory大部分是因为上面两个配置参数不够引起的。<br />
当然native heap 也可以产生OutOfMemory，如果os的java可用内存全部分给heap了。<br />
<br />
如果发生oom，个人觉得首先是调整参数，比如：<font style="background-color: #cce8cf">-server -Xms1024m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=128m</font><br />
如果参数调整之后还是oom，则需要考虑优化程序了（当然首先要把死递归，死循环排除），最好是用工具监测一下。<br />
<br />
附我们tomcat配置参数修改方案：<br />
&nbsp;
<p class="a" style="margin-left: 45pt; text-indent: -21pt; mso-char-indent-count: 0; mso-list: l0 level1 lfo1"><span lang="EN-US" style="font-family: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"><span style="mso-list: Ignore">&#178;<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US">Tomcat</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">配置的修改</span><span lang="EN-US">(%tomcat%</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表示</span><span lang="EN-US">tomcat</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">实际安装目录</span><span lang="EN-US">)</span></p>
<p class="MsoNormal" style="text-indent: 30pt; line-height: normal; text-align: left; mso-char-indent-count: 2.5; mso-vertical-align-alt: auto" align="left"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果</span><span lang="EN-US">tomcat</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">安装在</span><span lang="EN-US">Solaris</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">环境下，打开</span><span lang="EN-US"> %tomcat%\bin\catalina.sh </span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件，在文件的前面加下面红色字体的内容（注意有双引号）：</span></p>
<p class="MsoNormal" style="text-indent: 30pt; line-height: normal; text-align: left; mso-char-indent-count: 2.5; mso-vertical-align-alt: auto" align="left"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </span><span style="color: red">LANG=zh_CN.GB18030<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span lang="EN-US" style="color: red">export LANG<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span lang="EN-US" style="color: red">JAVA_OPTS="-server -Xms<st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="1024" unitname="m">1024m</st1:chmetcnv> -Xmx<st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="1024" unitname="m">1024m</st1:chmetcnv> -XX:PermSize=<st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="128" unitname="m">128m</st1:chmetcnv> -XX:MaxPermSize=<st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="128" unitname="m">128m</st1:chmetcnv>"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span lang="EN-US" style="color: red">export JAVA_OPTS<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span lang="EN-US" style="color: red">JAVA_OPTS="$JAVA_OPTS<span style="mso-spacerun: yes">&nbsp;&nbsp; </span>-Djava.awt.headless=true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span lang="EN-US" style="color: red">echo $JAVA_OPTS&nbsp;</span><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp;&nbsp; </span></span></p>
<p class="MsoNormal" style="text-indent: 30pt; line-height: normal; text-align: left; mso-char-indent-count: 2.5; mso-vertical-align-alt: auto" align="left"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果</span><span lang="EN-US">tomcat</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">安装在</span><span lang="EN-US">Windows</span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">环境下，打开</span><span lang="EN-US"> %tomcat%\bin\catalina.bat </span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件，在文件的前面加下面红色字体的内容（注意没有双引号）：</span></p>
<p class="MsoNormal" style="text-indent: 30pt; line-height: normal; text-align: left; mso-char-indent-count: 2.5; mso-vertical-align-alt: auto" align="left"><span lang="EN-US" style="color: red">set JAVA_OPTS=-server -Xms<st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="1024" unitname="m">1024m</st1:chmetcnv> -Xmx<st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="1024" unitname="m">1024m</st1:chmetcnv> -XX:PermSize=<st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="128" unitname="m">128m</st1:chmetcnv> -XX:MaxPermSize=<st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="128" unitname="m">128m</st1:chmetcnv></span></p>
<p class="MsoNormal" style="text-indent: 30pt; line-height: normal; text-align: left; mso-char-indent-count: 2.5; mso-vertical-align-alt: auto" align="left"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">打开</span><span lang="EN-US"> %tomcat%\conf\server.xml </span><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">文件，下面这行：</span></p>
<p class="MsoNormal" style="text-indent: 0cm; line-height: normal; text-align: left; mso-char-indent-count: 0; mso-vertical-align-alt: auto" align="left"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>maxThreads="150" minSpareThreads="25" maxSpareThreads="75"</span></p>
<p class="MsoNormal" style="text-indent: 0cm; line-height: normal; text-align: left; mso-char-indent-count: 0; mso-vertical-align-alt: auto" align="left"><span style="font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">改成：</span></p>
<p class="MsoNormal" style="text-indent: 0cm; line-height: normal; text-align: left; mso-char-indent-count: 0; mso-vertical-align-alt: auto" align="left"><span lang="EN-US"><span style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>maxThreads="250" minSpareThreads="25" maxSpareThreads="100"</span></p>
<br />
</font>
<img src ="http://www.blogjava.net/midstr/aggbug/230292.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-09-21 20:13 <a href="http://www.blogjava.net/midstr/archive/2008/09/21/230292.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OOM和JVM优化配置 zz</title><link>http://www.blogjava.net/midstr/archive/2008/09/21/230281.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Sun, 21 Sep 2008 10:13:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/09/21/230281.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/230281.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/09/21/230281.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/230281.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/230281.html</trackback:ping><description><![CDATA[<div>转载：<font style="background-color: #cce8cf">http://hi.baidu.com/coofucoo/blog/item/25d361d9555c002811df9bf2.html</font><br />
<strong><font size="5"><span style="font-size: 12pt; line-height: 173%"><br />
JVM</span><span style="font-size: 12pt; line-height: 173%">优化配置</span></font></strong><strong><font size="5"><span style="font-size: 12pt; line-height: 173%">《一》</span></font></strong><br />
<strong><font size="5"><span style="font-size: 12pt; line-height: 173%"><br />
</span></font></strong><span>OOM</span>这个缩写就是Java程序开发过程中让人最头痛的问题：Out of Memory。在很多开发人员的开发过程中，或多或少的都会遇到这类问题，这类问题定位比较困难，往往需要根据经验来判断可能出现问题的代码。原因主要是 两个：对象没有被释放（多种情况引起，往往是比较隐蔽的引用导致被Hold而无法被回收）。另一种就是真的Memory不够用了，需要增加JVM的 Heap来满足应用程序的需求。最近有同事发的关于解决OOM的问题，让我了解了原来OOM除了在JVM Heap不够时会发生，在Native Heap不够的时候也会发生，同时JVM Heap和Native Heap存在着相互影响和平衡的关系，因此就仔细的去看了关于OOM和JVM配置优化的内容。
<div></div>
<div><strong><font size="5"><span style="font-size: 12pt; line-height: 173%">OOM</span></font></strong></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>在 其他语言类似于C,Delphi等等由于内存都是由自己分配和管理，因此内存泄露的问题比较常见，同时也是很头痛的一件事情。而Java的对象生命周期管 理都是JVM来做的，简化了开发人员的非业务逻辑的处理，但是这种自动管理回收机制也是基于一些规则的，而违背了这些规则的时候，就会造成所谓的 &#8220;Memory Leak&#8221;。</div>
<div></div>
<div>OOM(Java Heap)</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>错误提示：java.lang.OutOfMemoryError。</div>
<div style="text-indent: 21pt">这 类OOM是由于JVM分配的给应用的Heap Memory已经被耗尽，可能是因为应用在高负荷的情况下的却需要很大的内存，因此可以通过修改JVM参数来增加Java Heap Memory（不过也不能无限制增加，后面那种OOM有可能就是因为这个原因而产生）。另一种情况是因为应用程序使用对象或者资源没有释放，导致内存消耗 持续增加，最后出现OOM，这类问题引起的原因往往是应用已不需要的对象还被其他有效对象所引用，那么就无法释放，可能是业务代码逻辑造成的（异常处理不 够例如IO等资源），也可能是对于第三方开源项目中资源释放了解不够导致使用以后资源没有释放（例如JDBC的ResultSet等）。</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>几个容易出现问题的场景：</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1</span>．应用的缓存或者Collection：如果应用要缓存Java对象或者是在一个Collection中保存对象，那么就要确定是否会有大量的对象存入，要做保护，以防止在大数据量下大量内存被消耗，同时要保证Cache的大小不会无限制增加。</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2</span>．生命周期较长的对象：尽量简短对象的生命周期，现在采用对象的创建释放代价已经很低，同时作了很好的优化，要比创建一个对象长期反复使用要好。如果能够设置超时的情景下，尽量设置超时。</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3</span>．类似于JDBC的Connection Pool，在使用Pool中的对象以后需要释放并返回，不然就会造成Pool的不断增大，在其他Pool中使用也是一样。同样ResultSet，IO这类资源的释放都需要注意。</div>
<div></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>解决的方法就是查找错误或者是增加Java Heap Memory。对于此类问题检测工具相当多，这里就不做介绍了。<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></div>
<div></div>
<div></div>
<div>OOM(Native Heap)</div>
<div style="text-indent: 21pt">错误提示：requested XXXX bytes for ChunkPool::allocate. Out of swap space。</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Native Heap Memory</span>是JVM 内部使用的Memory，这部分的Memory可以通过JDK提供的JNI的方式去访问，这部分Memory效率很高，但是管理需要自己去做，如果没有把 握最好不要使用，以防出现内存泄露问题。JVM 使用Native Heap Memory用来优化代码载入（JTI代码生成），临时对象空间申请，以及JVM内部的一些操作。这次同事在压力测试中遇到的问题就是这类OOM，也就是 这类Memory耗尽。同样这类OOM产生的问题也是分成正常使用耗尽和无释放资源耗尽两类。无释放资源耗尽很多时候不是程序员自身的原因，可能是引用的 第三方包的缺陷，例如很多人遇到的Oracle 9 JDBC驱动在低版本中有内存泄露的问题。要确定这类问题，就需要去观察Native Heap Memory的增长和使用情况，在服务器应用起来以后，运行一段时间后JVM对于Native Heap Memory的使用会达到一个稳定的阶段，此时可以看看什么操作对于Native Heap Memory操作频繁，而且使得Native Heap Memory增长，对于Native Heap Memory的情况我还没有找到办法去检测，现在能够看到的就是为JVM启动时候增加-verbose:jni参数来观察对于Native Heap Memory的操作。另一种情况就是正常消耗Native Heap Memory，对于Native Heap Memory的使用主要取决于JVM代码生成，线程创建，用于优化的临时代码和对象产生。当正常耗尽Native Heap Memory时，那么就需要增加Native Heap Memory，此时就会和我们前面提到增加java Heap Memory的情况出现矛盾。</div>
<div></div>
<div>应用内存组合</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>对 于应用来说，可分配的内存受到OS的限制，不同的OS对进程所能访问虚拟内存地址区间直接影响对于应用内存的分配，32位的操作系统通常最大支持4G的内 存寻址，而Linux一般为3G，Windows为2G。然而这些大小的内存并不会全部给JVM的Java Heap使用，它主要会分成三部分：Java Heap，Native Heap，载入资源和类库等所占用的内存。那么由此可见，Native Heap和 Java Heap大小配置是相互制约的，哪一部分分配多了都可能会影响到另外一部分的正常工作，因此如果通过命令行去配置，那么需要确切的了解应用使用情况，否则 采用默认配置自动监测会更好的优化应用使用情况。</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>同样要注意的就是进程的虚拟内存和机器的实际内存还是有区别的，对于机器来说实际内存以及硬盘提供的虚拟内存都是提供给机器上所有进程使用的，因此在设置JVM参数时，它的虚拟内存绝对不应该超过实际内存的大小。<br />
<strong><font size="5"><span style="font-size: 12pt; line-height: 173%">《二》</span></font></strong></div>
</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>这 里首先要说明的是这里提到的JVM是Sun的HotSpot JVM 5和以上的版本。性能优化在应用方面可以有很多手段，包括Cache，多线程，各种算法等等。通常情况下是不建议在没有任何统计和分析的情况下去手动配置 JVM的参数来调整性能，因为在JVM 5以上已经作了根据机器和OS的情况自动配置合适参数的算法，基本能够满足大部分的情况，当然这种自动适配只是一种通用的方式，如果说真的要达到最优，那 么还是需要根据实际的使用情况来手动的配置各种参数设置，提高性能。</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JVM</span>能够对性能产生影响的最大部分就是对于内存的管理。从jdk 1.5以后内存管理和分配有了很多的改善和提高。</div>
<div><strong><font size="4"><span style="font-size: 10.5pt; line-height: 173%">内存分配以及管理的几个基本概念和参数说明：</span></font></strong></div>
<div>Java Hotspot Mode：</div>
<div style="text-indent: 21pt">server 和 client两种模式，如果不配置，JVM会根据应用服务器硬件配置自动选择模式，server模式启动比较慢，但是运行期速度得到了优化，client启动比较快，但是运行期响应没有server模式的优化，适合于个人PC的服务开发和测试。</div>
<div></div>
<div>Garbage Collector Policy：</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>在Jdk 1.5的时候已经提供了三种GC，除了原来提供的串行GC（SerialGC）以外，还提供了两种新的GC：ParallelGC和 ConcMarkSweepGC。ParallelGC采用了多线程并行管理和回收垃圾对象，提高了回收效率，提高了服务器的吞吐量，适合于多处理器的服 务器。ConcMarkSweepGC采用的是并发方式来管理和回收垃圾对象，降低垃圾回收产生的响应暂停时间。这里说一下并发和并行的区别，并发指的是 多个进程并行执行垃圾回收，那么可以很好的利用多处理器，而并行指的是应用程序不需要暂停可以和垃圾回收线程并发工作。串行GC适合小型应用和单处理器系 统（无需多线程交互，效率比较高），后两者适合大型系统。</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>使用方式就是在参数配置中增加-XX:+UseParallelGC等方式来设置。</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>对于这部分的配置在网上有很多的实例可以参考，不过最终采用哪一种GC还是要根据具体的情况来分析和选择。</div>
<div></div>
<div>Heap：</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OOM</span>的 各种经历已经让每一个架构师开发人员看到了了解Heap的重要性。OOM已经是Heap的临界点，不得不引起注意，然而Heap对于性能的潜在影响并未被 引起重视，不过和GC配置一样，在没有对使用情况作仔细分析和研究的情况下，贸然的去修改Heap配置，可能适得其反，这里就来看一下Heap的一些概念 和对于性能的影响。</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>我们的应用所能够得到的最大的Heap受三部分因素的制约：数据处理 模型（32位或者64位操作系统），系统地虚拟内存总数和系统的物理内存总数。首先Heap的大小不能超过不同操作系统的进程寻址范围，当前大部分系统最 高限度是4G，Windows通常是2G，Linux通常是3G。系统的虚拟内存也是分配的依据，首先是不能超过，然后由于操作系统支持硬盘来做部分的虚 拟内存，如果设置过大，那么对于应用响应来说势必有影响。再则就是要考虑同一台服务器上运行多个Java虚拟机所消耗的资源总合也不能超过可用资源。就和 前面OOM分析中的一样，其实由于OS的数据处理模型的限制，机器本身的硬件内存资源和虚拟内存资源并不一定会匹配，那么在有限的资源下如何调整好资源分 配，对于应用来说尤为重要。</div>
<div></div>
<div></div>
<div>关于Heap的几个参数设置：</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>说了Heap的有限资源问题以后，就来看看如何通过配置去改变JVM对于Heap的分配。下面所说的主要是对于Java Heap的分配，那么在申请了Java Heap以后，剩下的可用资源就会被使用到Native Heap。</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Xms: java heap</span>初始化时的大小。默认情况是机器物理内存的1/64。这个主要是根据应用启动时消耗的资源决定，分配少了申请起来会降低启动速度，分配多了也浪费。</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Xmx:java heap</span>的 最大值，默认是机器物理内存的1/4，最大也就到1G。这个值决定了最多可用的Java Heap Memory，分配过少就会在应用需要大量内存作缓存或者零时对象时出现OOM的问题，如果分配过大，那么就会产生上文提到的第二类OOM。所以如何配置 还是根据运行过程中的分析和计算来确定，如果不能确定还是采用默认的配置。</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Xmn:java heap</span>新 生代的空间大小。在GC模型中，根据对象的生命周期的长短，产生了内存分代的设计：青年代（内部也分成三部分，类似于整体划分的作用，可以通过配置来设置 比例），老年代，持久代。每一代的管理和回收策略都不相同，最为活跃的就是青年代，同时这部分的内存分配和管理效率也是最高。通常情况下，对于内存的申请 优先在新生代中申请，当内存不够时会整理新生代，当整理以后还是不能满足申请的内存，就会向老年代移动一些生命周期较长的对象。这种整理和移动会消耗资 源，同时降低系统运行响应能力，因此如果青年代设置的过小，就会频繁的整理和移动，对性能造成影响。那是否把年青代设置的越大越好，其实不然，年青代采用 的是复制搜集算法，这种算法必须停止所有应用程序线程，服务器线程切换时间就会成为应用响应的瓶颈（当然永远不用收集那么就不存在这个问题）。老年代采用 的是串行标记收集的方式，并发收集可以减少对于应用的影响。</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Xss:</span>线程堆栈最大值。允许更多的虚拟内存空间地址被Java Heap使用。</div>
<div></div>
<div>以下是sun公司的性能优化白皮书中提到的几个例子：</div>
<div></div>
<div>1．对于吞吐量的调优。机器配置：4G的内存，32个线程并发能力。</div>
<div style="text-indent: 21pt"><code><strong>java</strong></code><code> -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20</code></div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><code>-Xmx3800m -Xms3800m </code>配置了最大Java Heap来充分利用系统内存。</div>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><code>-Xmn2g </code><code>创建足够大的青年代（可以并行被回收）充分利用系统内存，防止将短期对象复制到老年代。</code></div>
<div><code><span>&nbsp;&nbsp;&nbsp; -Xss128 </span></code><code>减少默认最大的线程栈大小，提供更多的处理虚拟内存地址空间被进程使用。</code></div>
<div><code><span>&nbsp;&nbsp;&nbsp; -XX:+UseParallelGC </span></code><code>采用并行垃圾收集器对年青代的内存进行收集，提高效率。</code></div>
<div><code><span>&nbsp;&nbsp;&nbsp; -XX:ParallelGCThreads=20 </span></code><code>减少垃圾收集线程，默认是和服务器可支持的线程最大并发数相同，往往不需要配置到最大值。</code></div>
<div><code></code></div>
<div><code>2</code><code>．尝试采用对老年代并行收集</code></div>
<div style="text-indent: 21pt"><code><strong>java</strong></code><code> -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC</code></div>
<div style="text-indent: 21pt"><code>-Xmx3550m -Xms3550m </code><code>内存分配被减小，因为<span>ParallelOldGC会增加对于Native Heap的需求，因此需要减小Java Heap来满足需求。</span></code></div>
<div style="text-indent: 21pt"><code>-XX:+UseParallelOldGC </code><code>采用对于老年代并发收集的策略，可以提高收集效率。</code></div>
<div><code></code></div>
<div><code>3</code><code>．提高吞吐量，减少应用停顿时间</code></div>
<div style="text-indent: 21pt"><code><strong>java</strong></code><code> -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:SurvivorRatio=8 -XX:TargetSurvivorRatio=90 -XX:MaxTenuringThreshold=31</code></div>
<div><code></code></div>
<div><code>-XX:+UseConcMarkSweepGC -XX:+UseParNewGC </code><code>选择了并发标记交换收集器，它可以并发执行收集操作，降低应用停止时间，同时它也是并行处理模式，可以有效地利用多处理器的系统的多进程处理。</code></div>
<div></div>
<div><code>-XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=31 </code><code>表示在青年代中<span>Eden和Survivor比例，设置增加了Survivor的大小，越大的survivor空间可以允许短期对象尽量在年青代消亡。</span></code></div>
<div><code></code></div>
<div><code>-XX:TargetSurvivorRatio=90 </code><code>允许<span>90%的空间被占用，超过默认的50%，提高对于survivor的使用率。</span></code></div>
<div><code></code></div>
<div style="text-indent: 21pt"><code>类似的例子网上很多，这儿就不在列下来了，最终是否采取自己配置来替换默认配置还是要根据虚拟机的使用情况来分析和配置。<br />
<br />
</code></div>
<img src ="http://www.blogjava.net/midstr/aggbug/230281.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-09-21 18:13 <a href="http://www.blogjava.net/midstr/archive/2008/09/21/230281.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>主题：分析java.lang.OutOfMemoryError: PermGen space zz</title><link>http://www.blogjava.net/midstr/archive/2008/09/21/230276.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Sun, 21 Sep 2008 09:22:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/09/21/230276.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/230276.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/09/21/230276.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/230276.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/230276.html</trackback:ping><description><![CDATA[<div id="related_topics" style="position: relative" _madepositioned="true" _eventid="2">&nbsp;</div>
<script type="text/javascript">
            new Draggable("related_topics");
          </script>SUN JDK+Tomcat 5.5.20运行服务的时候遇到问题，服务器跑几天后就会挂掉，并报java.lang.OutOfMemoryError: PermGen space异常。<br />
<br />
发现很多人把问题归因于： spring,hibernate,tomcat，因为他们动态产生类,导致JVM中的permanent heap溢出 。然后解决方法众说纷纭，有人说升级 tomcat版本到最新甚至干脆不用tomcat。还有人怀疑spring的问题，在<a href="http://forum.springframework.org/showthread.php?t=21383&amp;highlight=cglib+cache">spring论坛</a>上讨论很激烈，因为spring在AOP时使用CBLIB会动态产生很多类。<br />
<br />
但问题是为什么这些王牌的开源会出现同一个问题呢，那么是不是更基础的原因呢？tomcat在Q&amp;A很隐晦的回答了这一点，<a href="http://tomcat.apache.org/faq/deployment.html">我们知道这个问题，但这个问题是由一个更基础的问题产生。 </a><br />
<br />
<a href="http://www.freshblurbs.com/explaining-java-lang-outofmemoryerror-permgen-space">于是有人对更基础的JVM做了检查</a>，发现了问题的关键。原来SUN 的JVM把内存分了不同的区，其中一个就是permenter区用来存放用得非常多的类和类描述。本来SUN设计的时候认为这个区域在JVM启动的时候就固定了，但他没有想到现在动态会用得这么广泛。而且这个区域有特殊的垃圾收回机制，现在的问题是动态加载类到这个区域后，gc根本没办法回收！ <br />
<br />
2003年的时候就有一个<a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4957990">bug</a>报告给sun，但是到现在，这个<a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4957990">bug</a>还没有close！有人在这个bug加了句评语：&#8220;A bug this critical is open since 2003? Absolutely shameful.&#8221; 我觉得SUN在这个BUG上确实有些丢脸。<br />
<br />
对这个bug最彻底的解决办法就是不要用SUN的JDK，而改用<a href="http://commerce.bea.com/products/weblogicjrockit/jrockit_prod_fam.jsp">BEA的 JRokit.</a><br />
<br />
打不过，还逃不过吗？ 有众多的选择，这就是开源的好。 ：） 
<img src ="http://www.blogjava.net/midstr/aggbug/230276.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-09-21 17:22 <a href="http://www.blogjava.net/midstr/archive/2008/09/21/230276.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JVM启动参数大全 zz</title><link>http://www.blogjava.net/midstr/archive/2008/09/21/230265.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Sun, 21 Sep 2008 07:43:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/09/21/230265.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/230265.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/09/21/230265.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/230265.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/230265.html</trackback:ping><description><![CDATA[<font style="background-color: #cce8cf">jdk1.4.2 JVM官方地址：<font style="background-color: #cce8cf">http://java.sun.com/j2se/1.4.2/docs/guide/vm/index.html</font><br />
<font style="background-color: #cce8cf"><font style="background-color: #cce8cf"><font style="background-color: #cce8cf">标准和非标注参数(for windows)：<a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/java.html">http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/java.html</a> </font></font><br />
<font style="background-color: #cce8cf"><a href="http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp">非stable参数：http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp</a></font></font><br />
<br />
中文地址： <br />
<span style="color: red"><font style="background-color: #cce8cf"><span style="color: red"><font style="background-color: #cce8cf"><span style="color: red"><font style="background-color: #cce8cf"><font style="background-color: #cce8cf"><a href="http://blog.csdn.net/sfdev/archive/2008/01/23/2062042.aspx&nbsp;&nbsp;%20&nbsp;http://blog.csdn.net/sfdev/archive/2008/01/24/2063464.aspx">http://blog.csdn.net/sfdev/archive/2008/01/23/2062042.aspx&nbsp;&nbsp;&nbsp;</a></font><a href="http://blog.csdn.net/sfdev/archive/2008/01/23/2062042.aspx&nbsp;&nbsp;%20&nbsp;http://blog.csdn.net/sfdev/archive/2008/01/24/2063464.aspx"><font style="background-color: #cce8cf"><font color="#000000">&nbsp;</font></a></font><font style="background-color: #cce8cf">&nbsp;</font></font></span></font><font style="background-color: #cce8cf">&nbsp;</font></span></font></span><span style="color: red"><font style="background-color: #cce8cf">&nbsp;&nbsp;</font></span></font><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
<br />
<p>前段时间系统升级时遭遇了OOM，具体解决过程见&nbsp;<a href="http://blog.csdn.net/sfdev/archive/2008/01/18/2051171.aspx">遭遇OutOfMemoryError</a>；<br />
为了巩固对于java启动各项参数的认识，决定将所有参数列举出来，并一一解释，以便后查；</p>
<p>java启动参数共分为三类；<br />
其一是<strong>标准参数</strong>（-），所有的JVM实现都必须实现这些参数的功能，而且向后兼容；<br />
其二是<strong>非标准参数</strong>（-X），默认jvm实现这些参数的功能，但是并不保证所有jvm实现都满足，且不保证向后兼容；<br />
其三是<strong>非Stable参数</strong>（-XX），此类参数各个jvm实现会有所不同，将来可能会随时取消，需要慎重使用；<br />
本文主要描述标准参数部分，剩下的两个部分将会陆续推出；</p>
<p>标准参数列表如下：<br />
<strong>-client <br />
</strong>&nbsp;设置jvm使用client模式，特点是启动速度比较快，但运行时性能和内存管理效率不高，通常用于客户端应用程序或者PC应用开发和调试。</p>
<p><strong>-server</strong><br />
&nbsp;设置jvm使server模式，特点是启动速度比较慢，但运行时性能和内存管理效率很高，适用于生产环境。在具有64位能力的jdk环境下将默认启用该模式，而忽略-client参数。</p>
<p><strong>-agentlib:libname[=options]</strong> <br />
&nbsp;用于装载本地lib包；<br />
&nbsp;其中libname为本地代理库文件名，默认搜索路径为环境变量PATH中的路径，options为传给本地库启动时的参数，多个参数之间用逗号分隔。在Windows平台上jvm搜索本地库名为libname.dll的文件，在linux上jvm搜索本地库名为libname.so的文件，搜索路径环境变量在不同系统上有所不同，比如Solaries上就默认搜索LD_LIBRARY_PATH。<br />
&nbsp;比如：-agentlib:hprof<br />
&nbsp;用来获取jvm的运行情况，包括CPU、内存、线程等的运行数据，并可输出到指定文件中；windows中搜索路径为JRE_HOME/bin/hprof.dll。</p>
<p><strong>-agentpath:pathname[=options]</strong> <br />
&nbsp;按全路径装载本地库，不再搜索PATH中的路径；其他功能和agentlib相同；更多的信息待续，在后续的JVMTI部分会详述。</p>
<p><strong>-classpath classpath <br />
-cp classpath</strong> <br />
&nbsp;告知jvm搜索目录名、jar文档名、zip文档名，之间用分号;分隔；使用-classpath后jvm将不再使用CLASSPATH中的类搜索路径，如果-classpath和CLASSPATH都没有设置，则jvm使用当前路径(.)作为类搜索路径。<br />
&nbsp;jvm搜索类的方式和顺序为：Bootstrap，Extension，User。<br />
&nbsp;Bootstrap中的路径是jvm自带的jar或zip文件，jvm首先搜索这些包文件，用System.getProperty("sun.boot.class.path")可得到搜索路径。<br />
&nbsp;Extension是位于JRE_HOME/lib/ext目录下的jar文件，jvm在搜索完Bootstrap后就搜索该目录下的jar文件，用System.getProperty("java.ext.dirs")可得到搜索路径。<br />
&nbsp;User搜索顺序为当前路径.、CLASSPATH、-classpath，jvm最后搜索这些目录，用System.getProperty("java.class.path")可得到搜索路径。</p>
<p><strong>-Dproperty=value</strong><br />
&nbsp;设置系统属性名/值对，运行在此jvm之上的应用程序可用System.getProperty("property")得到value的值。<br />
&nbsp;如果value中有空格，则需要用双引号将该值括起来，如-Dname="space string"。<br />
&nbsp;该参数通常用于设置系统级全局变量值，如配置文件路径，以便该属性在程序中任何地方都可访问。</p>
<p><strong>-enableassertions[:&lt;package name&gt;"..." | :&lt;class name&gt; ] <br />
-ea[:&lt;package name&gt;"..." | :&lt;class name&gt; ]</strong> <br />
&nbsp;上述参数就用来设置jvm是否启动断言机制（从JDK 1.4开始支持），缺省时jvm关闭断言机制。<br />
&nbsp;用-ea 可打开断言机制，不加&lt;packagename&gt;和classname时运行所有包和类中的断言，如果希望只运行某些包或类中的断言，可将包名或类名加到-ea之后。例如要启动包com.wombat.fruitbat中的断言，可用命令java -ea:com.wombat.fruitbat...&lt;Main Class&gt;。</p>
<p><strong>-disableassertions[:&lt;package name&gt;"..." | :&lt;class ; ] <br />
-da[:&lt;package name&gt;"..." | :&lt;class name&gt; ]</strong><br />
&nbsp;用来设置jvm关闭断言处理，packagename和classname的使用方法和-ea相同，jvm默认就是关闭状态。<br />
&nbsp;该参数一般用于相同package内某些class不需要断言的场景，比如com.wombat.fruitbat需要断言，但是com.wombat.fruitbat.Brickbat该类不需要，则可以如下运行：<br />
&nbsp;java -ea:com.wombat.fruitbat...-da:com.wombat.fruitbat.Brickbat &lt;Main Class&gt;。<br />
&nbsp;<br />
<strong>-enablesystemassertions <br />
-esa</strong> <br />
&nbsp;激活系统类的断言。<br />
&nbsp;<br />
<strong>-disablesystemassertions <br />
-dsa</strong> <br />
&nbsp;关闭系统类的断言。</p>
<p><strong>-jar</strong> <br />
&nbsp;指定以jar包的形式执行一个应用程序。<br />
&nbsp;要这样执行一个应用程序，必须让jar包的manifest文件中声明初始加载的Main-class，当然那Main-class必须有public static void main(String[] args)方法。</p>
<p><strong>-javaagent:jarpath[=options]</strong> <br />
&nbsp;指定jvm启动时装入java语言设备代理。<br />
&nbsp;Jarpath文件中的mainfest文件必须有Agent-Class属性。代理类也必须实现公共的静态public static void premain(String agentArgs, Instrumentation inst)方法（和main方法类似）。当jvm初始化时，将按代理类的说明顺序调用premain方法；具体参见java.lang.instrument软件包的描述。</p>
<p><strong>-verbose <br />
-verbose:class</strong> <br />
&nbsp;输出jvm载入类的相关信息，当jvm报告说找不到类或者类冲突时可此进行诊断。<br />
<strong>-verbose:gc</strong> <br />
&nbsp;输出每次GC的相关情况。<br />
<strong>-verbose:jni</strong> <br />
&nbsp;输出native方法调用的相关情况，一般用于诊断jni调用错误信息。<br />
&nbsp;<br />
<strong>-version</strong> <br />
&nbsp;输出java的版本信息，比如jdk版本、vendor、model。<br />
<strong>-version:release</strong> <br />
&nbsp;指定class或者jar运行时需要的jdk版本信息；若指定版本未找到，则以能找到的系统默认jdk版本执行；一般情况下，对于jar文件，可以在manifest文件中指定需要的版本信息，而不是在命令行。<br />
&nbsp;release中可以指定单个版本，也可以指定一个列表，中间用空格隔开，且支持复杂组合，比如：<br />
&nbsp;-version:"1.5.0_04 1.5*&amp;1.5.1_02+"<br />
&nbsp;指定class或者jar需要jdk版本为1.5.0_04或者是1.5系列中比1.5.1_02更高的所有版本。</p>
<p><strong>-showversion</strong> <br />
&nbsp;输出java版本信息（与-version相同）之后，继续输出java的标准参数列表及其描述。<br />
&nbsp;<br />
<strong>-? <br />
-help</strong> <br />
&nbsp;输出java标准参数列表及其描述。<br />
<br />
<strong>-X</strong> <br />
&nbsp;输出非标准的参数列表及其描述。</p>
<p>以上的这些参数我们经常会在很多情况下用到多个的组合，比如我们在用JProfiler进行跟踪监控时，需要在被监控java启动参数中加上如下配置：<br />
-agentlib:jprofilerti=port=8849&nbsp; -Xbootclasspath/a:/usr/local/jprofiler5/bin/agent.jar<br />
其中就用到两个-agentlib和-X参数，bootclasspath参数的详细信息将会在非标准参数中详细说明。</p>
<br />
<span style="color: red">http://blog.csdn.net/sfdev/archive/2008/01/24/2063464.aspx</span><br />
<br />
<p>非标准参数又称为扩展参数，其列表如下：<br />
<strong>-Xint</strong><br />
&nbsp;设置jvm以解释模式运行，所有的字节码将被直接执行，而不会编译成本地码。<br />
&nbsp;<br />
<strong>-Xbatch</strong><br />
&nbsp;关闭后台代码编译，强制在前台编译，编译完成之后才能进行代码执行；<br />
&nbsp;默认情况下，jvm在后台进行编译，若没有编译完成，则前台运行代码时以解释模式运行。<br />
&nbsp;<br />
<strong>-Xbootclasspath:bootclasspath</strong><br />
&nbsp;让jvm从指定路径（可以是分号分隔的目录、jar、或者zip）中加载bootclass，用来替换jdk的rt.jar；若非必要，一般不会用到；<br />
<strong>-Xbootclasspath/a:path</strong><br />
&nbsp;将指定路径的所有文件追加到默认bootstrap路径中；<br />
<strong>-Xbootclasspath/p:path</strong><br />
&nbsp;让jvm优先于bootstrap默认路径加载指定路径的所有文件；<br />
&nbsp;<br />
<strong>-Xcheck:jni</strong><br />
&nbsp;对JNI函数进行附加check；此时jvm将校验传递给JNI函数参数的合法性，在本地代码中遇到非法数据时，jmv将报一个致命错误而终止；使用该参数后将造成性能下降，请慎用。<br />
&nbsp;<br />
<strong>-Xfuture</strong><br />
&nbsp;让jvm对类文件执行严格的格式检查（默认jvm不进行严格格式检查），以符合类文件格式规范，推荐开发人员使用该参数。<br />
&nbsp;<br />
<strong>-Xnoclassgc</strong><br />
&nbsp;关闭针对class的gc功能；因为其阻止内存回收，所以可能会导致OutOfMemoryError错误，慎用；<br />
&nbsp;<br />
<strong>-Xincgc</strong><br />
&nbsp;开启增量gc（默认为关闭）；这有助于减少长时间GC时应用程序出现的停顿；但由于可能和应用程序并发执行，所以会降低CPU对应用的处理能力。<br />
&nbsp;<br />
<strong>-Xloggc:file</strong><br />
&nbsp;与-verbose:gc功能类似，只是将每次GC事件的相关情况记录到一个文件中，文件的位置最好在本地，以避免网络的潜在问题。<br />
&nbsp;若与verbose命令同时出现在命令行中，则以-Xloggc为准。<br />
&nbsp;<br />
<strong>-Xmsn<br />
</strong>&nbsp;指定jvm堆的初始大小，默认为物理内存的1/64，最小为1M；可以指定单位，比如k、m，若不指定，则默认为字节。<br />
&nbsp;<br />
<strong>-Xmxn</strong><br />
&nbsp;指定jvm堆的最大值，默认为物理内存的1/4或者1G，最小为2M；单位与-Xms一致。<br />
&nbsp;<br />
<strong>-Xprof</strong><br />
&nbsp;跟踪正运行的程序，并将跟踪数据在标准输出输出；适合于开发环境调试。<br />
&nbsp;<br />
<strong>-Xrs</strong><br />
&nbsp;减少jvm对操作系统信号（signals）的使用，该参数从1.3.1开始有效；<br />
&nbsp;从jdk1.3.0开始，jvm允许程序在关闭之前还可以执行一些代码（比如关闭数据库的连接池），即使jvm被突然终止；<br />
&nbsp;jvm关闭工具通过监控控制台的相关事件而满足以上的功能；更确切的说，通知在关闭工具执行之前，先注册控制台的控制handler，然后对CTRL_C_EVENT, CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and CTRL_SHUTDOWN_EVENT这几类事件直接返回true。<br />
&nbsp;但如果jvm以服务的形式在后台运行（比如servlet引擎），他能接收CTRL_LOGOFF_EVENT事件，但此时并不需要初始化关闭程序；为了避免类似冲突的再次出现，从jdk1.3.1开始提供-Xrs参数；当此参数被设置之后，jvm将不接收控制台的控制handler，也就是说他不监控和处理CTRL_C_EVENT, CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, or CTRL_SHUTDOWN_EVENT事件。<br />
&nbsp;<br />
<strong>-Xssn<br />
</strong>&nbsp;设置单个线程栈的大小，一般默认为512k。&nbsp;</p>
<p>上面这些参数中，比如<strong>-Xmsn、-Xmxn&#8230;&#8230;</strong>都是我们性能优化中很重要的参数；<br />
<strong>-Xprof、-Xloggc:file</strong>等都是在没有专业跟踪工具情况下排错的好手；<br />
在上一小节中提到的关于JProfiler的配置中就使用到了<strong>-Xbootclasspath/a:path</strong>；</p>
<br />
<a style="color: red" href="http://blog.csdn.net/sfdev/archive/2008/01/24/2063928.aspx">http://blog.csdn.net/sfdev/archive/2008/01/24/2063928.aspx</a><br />
<br />
前面我们提到用-XX作为前缀的参数列表在jvm中可能是不健壮的，SUN也不推荐使用，后续可能会在没有通知的情况下就直接取消了；但是由于这些参数中的确有很多是对我们很有用的，比如我们经常会见到的-XX:PermSize、-XX:MaxPermSize等等；
<p>下面我们将就Java HotSpot VM中<strong><font color="#ff0000">-XX:</font></strong>的可配置参数列表进行描述；<br />
这些参数可以被松散的聚合成三类：<br />
<strong>行为参数</strong>（Behavioral Options）：用于改变jvm的一些基础行为；<br />
<strong>性能调优</strong>（Performance Tuning）：用于jvm的性能调优；<br />
<strong>调试参数</strong>（Debugging Options）：一般用于打开跟踪、打印、输出等jvm参数，用于显示jvm更加详细的信息；</p>
<p>由于sun官方文档中对各参数的描述也都非常少（大多只有一句话），而且大多涉及OS层面的东西，很难描述清楚，所以以下是挑选了一些我们开发中可能会用得比较多的配置项，若需要查看所有参数列表，可以点击<a href="http://java.sun.com/docs/hotspot/VMOptions.html" dragover="true">HotSpot VM Specific Options</a>.查看原文；</p>
<p>首先来介绍<strong>行为参数</strong>：<br />
<br />
<table height="238" cellspacing="1" cellpadding="1" width="800" align="left" summary="" border="1">
    <tbody>
        <tr>
            <td>参数及其默认值</td>
            <td>描述</td>
        </tr>
        <tr>
            <td>-XX:-DisableExplicitGC</td>
            <td>禁止调用System.gc()；但jvm的gc仍然有效</td>
        </tr>
        <tr>
            <td>-XX:+MaxFDLimit</td>
            <td>最大化文件描述符的数量限制</td>
        </tr>
        <tr>
            <td>-XX:+ScavengeBeforeFullGC</td>
            <td>新生代GC优先于Full GC执行</td>
        </tr>
        <tr>
            <td>-XX:+UseGCOverheadLimit</td>
            <td>在抛出OOM之前限制jvm耗费在GC上的时间比例</td>
        </tr>
        <tr>
            <td><strong>-XX:-UseConcMarkSweepGC</strong></td>
            <td><strong>对老生代采用并发标记交换算法进行GC</strong></td>
        </tr>
        <tr>
            <td><strong>-XX:-UseParallelGC</strong></td>
            <td><strong>启用并行GC</strong></td>
        </tr>
        <tr>
            <td>-XX:-UseParallelOldGC</td>
            <td>对Full GC启用并行，当-XX:-UseParallelGC启用时该项自动启用</td>
        </tr>
        <tr>
            <td><strong>-XX:-UseSerialGC</strong></td>
            <td><strong>启用串行GC</strong></td>
        </tr>
        <tr>
            <td>-XX:+UseThreadPriorities</td>
            <td>启用本地线程优先级</td>
        </tr>
    </tbody>
</table>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
上面表格中黑体的三个参数代表着jvm中GC执行的三种方式，即<strong>串行、并行、并发</strong>；<br />
串行<strong>（SerialGC）</strong>是jvm的默认GC方式，一般适用于小型应用和单处理器，算法比较简单，GC效率也较高，但可能会给应用带来停顿；<br />
并行<strong>（ParallelGC）</strong>是指GC运行时，对应用程序运行没有影响，GC和app两者的线程在并发执行，这样可以最大限度不影响app的运行；<br />
并发<strong>（ConcMarkSweepGC）</strong>是指多个线程并发执行GC，一般适用于多处理器系统中，可以提高GC的效率，但算法复杂，系统消耗较大；</p>
<p><strong><br />
性能调优</strong>参数列表：<br />
</p>
<p>
<table height="272" cellspacing="1" cellpadding="1" width="800" align="left" summary="" border="1">
    <tbody>
        <tr>
            <td>参数及其默认值</td>
            <td>描述</td>
        </tr>
        <tr>
            <td>-XX:LargePageSizeInBytes=4m</td>
            <td>设置用于Java堆的大页面尺寸</td>
        </tr>
        <tr>
            <td>-XX:MaxHeapFreeRatio=70</td>
            <td>GC后java堆中空闲量占的最大比例</td>
        </tr>
        <tr>
            <td><strong>-XX:MaxNewSize=size</strong></td>
            <td><strong>新生成对象能占用内存的最大值</strong></td>
        </tr>
        <tr>
            <td><strong>-XX:MaxPermSize=64m</strong></td>
            <td><strong>老生代对象能占用内存的最大值</strong></td>
        </tr>
        <tr>
            <td>-XX:MinHeapFreeRatio=40</td>
            <td>GC后java堆中空闲量占的最小比例</td>
        </tr>
        <tr>
            <td>-XX:NewRatio=2</td>
            <td>新生代内存容量与老生代内存容量的比例</td>
        </tr>
        <tr>
            <td><strong>-XX:NewSize=2.125m</strong></td>
            <td><strong>新生代对象生成时占用内存的默认值</strong></td>
        </tr>
        <tr>
            <td>-XX:ReservedCodeCacheSize=32m</td>
            <td>保留代码占用的内存容量</td>
        </tr>
        <tr>
            <td>-XX:ThreadStackSize=512</td>
            <td>设置线程栈大小，若为0则使用系统默认值</td>
        </tr>
        <tr>
            <td>-XX:+UseLargePages</td>
            <td>使用大页面内存</td>
        </tr>
    </tbody>
</table>
</p>
<p><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
</p>
<p>我们在日常性能调优中基本上都会用到以上黑体的这几个属性；&nbsp;<br />
<br />
</p>
<p><strong>调试参数</strong>列表：</p>
<p>
<table style="width: 800px; height: 426px" height="426" cellspacing="1" cellpadding="1" width="800" align="left" summary="" border="1">
    <tbody>
        <tr>
            <td>参数及其默认值</td>
            <td>描述</td>
        </tr>
        <tr>
            <td>-XX:-CITime</td>
            <td>打印消耗在JIT编译的时间</td>
        </tr>
        <tr>
            <td>-XX:ErrorFile=./hs_err_pid&lt;pid&gt;.log</td>
            <td>保存错误日志或者数据到文件中</td>
        </tr>
        <tr>
            <td>-XX:-ExtendedDTraceProbes</td>
            <td>开启solaris特有的dtrace探针</td>
        </tr>
        <tr>
            <td><strong>-XX:HeapDumpPath=./java_pid&lt;pid&gt;.hprof</strong></td>
            <td><strong>指定导出堆信息时的路径或文件名</strong></td>
        </tr>
        <tr>
            <td><strong>-XX:-HeapDumpOnOutOfMemoryError</strong></td>
            <td><strong>当首次遭遇OOM时导出此时堆中相关信息</strong></td>
        </tr>
        <tr>
            <td>-XX:OnError="&lt;cmd args&gt;;&lt;cmd args&gt;"</td>
            <td>出现致命ERROR之后运行自定义命令</td>
        </tr>
        <tr>
            <td>-XX:OnOutOfMemoryError="&lt;cmd args&gt;;&lt;cmd args&gt;"</td>
            <td>当首次遭遇OOM时执行自定义命令</td>
        </tr>
        <tr>
            <td>-XX:-PrintClassHistogram</td>
            <td>遇到Ctrl-Break后打印类实例的柱状信息，与jmap -histo功能相同</td>
        </tr>
        <tr>
            <td><strong>-XX:-PrintConcurrentLocks</strong></td>
            <td><strong>遇到Ctrl-Break后打印并发锁的相关信息，与jstack -l功能相同</strong></td>
        </tr>
        <tr>
            <td>-XX:-PrintCommandLineFlags</td>
            <td>打印在命令行中出现过的标记</td>
        </tr>
        <tr>
            <td>-XX:-PrintCompilation</td>
            <td>当一个方法被编译时打印相关信息</td>
        </tr>
        <tr>
            <td>-XX:-PrintGC</td>
            <td>每次GC时打印相关信息</td>
        </tr>
        <tr>
            <td>-XX:-PrintGC Details</td>
            <td>每次GC时打印详细信息</td>
        </tr>
        <tr>
            <td>-XX:-PrintGCTimeStamps</td>
            <td>打印每次GC的时间戳</td>
        </tr>
        <tr>
            <td>-XX:-TraceClassLoading</td>
            <td>跟踪类的加载信息</td>
        </tr>
        <tr>
            <td>-XX:-TraceClassLoadingPreorder</td>
            <td>跟踪被引用到的所有类的加载信息</td>
        </tr>
        <tr>
            <td>-XX:-TraceClassResolution</td>
            <td>跟踪常量池</td>
        </tr>
        <tr>
            <td>-XX:-TraceClassUnloading</td>
            <td>跟踪类的卸载信息</td>
        </tr>
        <tr>
            <td>-XX:-TraceLoaderConstraints</td>
            <td>跟踪类加载器约束的相关信息</td>
        </tr>
    </tbody>
</table>
</p>
<p><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
当系统出现问题的时候，又不能使用外部跟踪工具（比如JProfiler&#8230;&#8230;）的情况下，以上的这些参数就会发挥重大作用了，比如dump堆信息、打印并发锁&#8230;&#8230;</p>
<br />
</font>
<img src ="http://www.blogjava.net/midstr/aggbug/230265.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-09-21 15:43 <a href="http://www.blogjava.net/midstr/archive/2008/09/21/230265.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>遭遇OutOfMemoryError zz</title><link>http://www.blogjava.net/midstr/archive/2008/09/21/230264.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Sun, 21 Sep 2008 07:14:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/09/21/230264.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/230264.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/09/21/230264.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/230264.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/230264.html</trackback:ping><description><![CDATA[<font style="background-color: #cce8cf"><a href="http://blog.csdn.net/sfdev/archive/2008/01/18/2051171.aspx">原文地址：http://blog.csdn.net/sfdev/archive/2008/01/18/2051171.aspx</a></font><br />
<br />
<p>这几天，网店系统基础架构进行了一次大的升级，升级之后例行的进行了压力测试，以前几次大的项目发布压力测试都没有任何问题，没想到这次出事故啦，而且是内存泄露？</p>
<p>系统运行环境：<br />
硬件：Intel(R) Xeon(R) CPU 2.0G、4G RAM、Linux 2.6.9-42.ELsmp #1 SMP <br />
软件：jboss-4.0.5.GA [Java HotSpot(TM) Server VM (build 1.5.0_10-b03, mixed mode)]<br />
JAVA运行参数-server -Xms2048m -Xmx2048m -XX:NewSize=768m -XX:PermSize=128m -XX:MaxPermSize=128m</p>
<p>现象是这样的：<br />
对系统压力测试大约4个小时左右，系统突然down掉，抛错为java.lang.OutOfMemoryError: requested 12 bytes for intptr_t in /BUILD_AREA/jdk1.5.0_10/hotspot/src/share/vm/runtime/deoptimization.cpp. Out of swap space?<br />
由于是晚上进行，所以没有观察到任何比较奇怪的现象出现，再次压力测试，仍然抛错，但稍微有些不同java.lang.OutOfMemoryError: requested 32756 bytes for ChunkPool::allocate. Out of swap space?<br />
经多次压力，现象100%可以重现；</p>
<p>解决过程：<br />
1、use jvmstat first<br />
&nbsp;&nbsp;这是SUN自己的性能跟踪工具，他占用server资源很少；监控的结果令我们失望，因为JVM表现完全正常，我们分配的2G内存还有很多剩余，并没有耗尽；GC也很正常，没有出现明显的Full GC或者是每次GC时间太长的情况；<br />
&nbsp;&nbsp;用top命令查看占用内存不到3G，也还算富裕；而且系统并没有JNI的使用；为什么会报OutOfMemoryError呢？未果！<br />
2、search Out of swap space<br />
&nbsp;&nbsp;更多都是遭遇了相同的问题，但是好像都没有一个很可行的解决办法，甚至有人怀疑是JDK的bug，也有人说可以用-Xss参数设置stack size大小，ss默认大小为512k，但是从监控上看我们的进程也没有那么多，但还是尝试了一把，再次压力问题仍然未解决！<br />
3、try to see heap dump<br />
&nbsp;&nbsp;添加参数-XX:+HeapDumpOnOutOfMemoryError，让系统出现OutOfMemoryError时将当时JVM内所有heap dump出来，使用jHAT分析；<br />
&nbsp;&nbsp;很可惜，1.5中对该参数的支持超级有限，记录下来的信息很少，并没有我们想象的那么多，那么有用，基本上这些信息是无用的；再次失败！<br />
4、back to OutOfMemoryError<br />
&nbsp;&nbsp;由于jvmstat 能看见的JVM内部信息有限，所以我们打算用专业工具JProfiler来进行详查；环境搞定之后，再次压力，不到2小时情况就重现了，但是从JProfiler中观察到的信息显示JVM内部的确没有任何异常，结论和Jconsole观察后完全一样，JVM内部没有任何问题！但为什么会有此错误？想不通&#8230;&#8230;<br />
5、focus on java heap with linux<br />
&nbsp;&nbsp;再次search了linux环境下面java heap的相关工作原理及组成信息，有发现了！<br />
&nbsp;&nbsp;其实java heap由2部分组成：其一为我们熟悉的JVM heap，其二为和OS相关的Native heap；<br />
&nbsp;&nbsp;JVM heap完全由GC掌控，我们可以通过参数-Xms、-Xmx指定其大小，并且可以用工具对其进行监控；他管理的东西就是我们所有的Java Object；<br />
&nbsp;&nbsp;而Native heap是平台相关的，我们既不能设置其使用大小也不能干预他的使用状态；他管理的东西一般都是很底层的，比如JIT使用的buffer、GC的底层data structures、JNI调用的所有相关对象、SWING/AWT调用需要的buffer和data structures&#8230;&#8230;<br />
&nbsp;&nbsp;由此想到，是否我们分配的JVM heap太大了，于是设置参数变为-Xms1536m -Xmx1536m再次压力，问题解决了！！！</p>
<p>虽然问题解决了，但是我们还是没能从根本上解释此次故障，因为系统可用的内存还有很多，并没有耗尽？<br />
难道32位的JAVA所能操作的内存只有2G？JVM heap全部占完了会导致Native heap无法allocate memory？后续还需要进一步研究此事；</p>
<p>PS：<br />
1、上面我们提到专业级的性能监控工具JProfiler，他的介绍及其安装使用可以参考<a href="http://blog.chinaunix.net/u/11765/showart_239554.html">http://blog.chinaunix.net/u/11765/showart_239554.html</a>；<br />
&nbsp;&nbsp;有两点可以注意下；其一：sh安装方式下linux默认安装目录一般为/usr/local/jprofilerX；其二为${JPROFILER_HOME}/bin/linux-x86目录不一定要放在单独项LD_LIBRARY_PATH中，只要classpath中能找到即可；<br />
2、JProfiler、JProbe Profiler、Java Profiler三者是同一个产品么？<br />
&nbsp;&nbsp;答案当然为否；三者都是业内非常优秀的Java性能监控工具，他们分别属于不同的公司；<br />
&nbsp;&nbsp;JProfiler：<a href="http://www.ej-technologies.com/">http://www.ej-technologies.com</a><br />
&nbsp;&nbsp;JProbe Profiler：<a href="http://www.quest.com/">http://www.quest.com</a>；TOAD就是该公司的产品之一；<br />
&nbsp;&nbsp;Java Profiler：<a href="http://www.yourkit.com/">http://www.yourkit.com</a><br />
<br />
<br />
<br />
</p>
<dd>其实现在回过头来看下这个问题，简直太easy了，java官方文档中明确阐述了heap的两种类别，分别会导致两类的oom，一类当然是我们非常熟悉的jvm oom，另外一类就是native heap oom；<br />
这也提醒之后遇到问题时第一时间找的不一定是search，可能官方文档更有效；</dd>
<img src ="http://www.blogjava.net/midstr/aggbug/230264.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-09-21 15:14 <a href="http://www.blogjava.net/midstr/archive/2008/09/21/230264.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java虚拟机的最大内存是多少 zz</title><link>http://www.blogjava.net/midstr/archive/2008/09/21/230262.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Sun, 21 Sep 2008 07:01:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/09/21/230262.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/230262.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/09/21/230262.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/230262.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/230262.html</trackback:ping><description><![CDATA[<span style="color: #000000">今天分析了当前比较流行的几个不同公司不同版本JVM的最大内存，得出来的结果如下：<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />公司&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JVM版本&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;最大内存(兆)client&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;最大内存(兆)server<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />SUN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.5.x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1492&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1520<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />SUN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.5.5(Linux)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2634&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2660<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />SUN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.4.2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1564&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1564<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />SUN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.4.2(Linux)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1900&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1260<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />IBM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.4.2(Linux)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2047&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N/A<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />BEA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JRockit&nbsp;1.5&nbsp;(U3)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1909&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1902<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />除非特别说明，否则JVM版本都运行在Windows操作系统下<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />附：如何获得JVM的最大可用内存<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />在命令行下用&nbsp;java&nbsp;-XmxXXXXM&nbsp;-version&nbsp;命令来进行测试，然后逐渐的增大XXXX的值，如果执行正常就表示指定的内存大小可用，否则会打印错误信息。<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />实际发现版本上有细微差别的JDK最大容许内存值都不尽相同，因此在实际的应用中还是要自己试验一下看到底内存能达到什么样的值。<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />通过这个表想说明的是，如果你的机器的内存太多的话，只能通过多运行几个实例来提供机器的利用率了，例如跑Tomcat，你可以多装几个Tomcat并做集群，依此类推。</span> <br />
<br />
<br />
&#8801;&#8801;&#8801; 网友评论 &#8801;&#8801;&#8801; <br />
东子 网友说: <br />
Windows下的最大内存应该跟NT内核对地址空间的保留也有关系, 好像默认情况下NT内核要占用高2G的地址空间, 所以应用程序撑死能获得的内存不会超过2G; 记得有一个参数可以让NT只占1G内存, 这样应用程序就有3G地址空间可用, 相应环境下JVM能允许的最大内存可能也会升高. <br />
<br />
at 05-10-06 00:04 <br />
purpureleaf 网友说: <br />
windows的每个应用（不是寻址）的寻址空间一般是2g或者3g，取决于一个参数。但是只要使用一组特定的函数分配内存，每个应用的寻址空间可以远远超过4g <br />
<br />
jdk可能是设置不了那个大的内存，但那不是windows造成的，是jdk造成的，在linux上一样设置不了。看来做java的朋友对windows还是不熟 
<img src ="http://www.blogjava.net/midstr/aggbug/230262.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-09-21 15:01 <a href="http://www.blogjava.net/midstr/archive/2008/09/21/230262.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对字符编码与Unicode,ISO 10646,UCS,UTF8,UTF16,GBK,GB2312的理解 zz</title><link>http://www.blogjava.net/midstr/archive/2008/09/20/230163.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Sat, 20 Sep 2008 09:37:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/09/20/230163.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/230163.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/09/20/230163.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/230163.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/230163.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf"><a title="原文地址" href="http://www.donews.net/holen/archive/2004/11/30/188182.aspx"><font style="background-color: #cce8cf"></font>&nbsp;</a><font style="background-color: #cce8cf"><a href="http://www.donews.net/holen/archive/2004/11/30/188182.aspx">http://www.donews.net/holen/archive/2004/11/30/188182.aspx</a><br />
<br />
<br />
<strong>&nbsp; </p>
<p>-------------------------------<br />
</p>
<p>Unicode: <br />
<br />
</strong>unicode.org制定的编码机制, 要将全世界常用文字都函括进去.<br />
在1.0中是16位编码, 由U+0000到U+FFFF. 每个2byte码对应一个字符; 在2.0开始抛弃了16位限制, 原来的16位作为基本位平面, 另外增加了16个位平面, 相当于20位编码, 编码范围0到0x10FFFF.<br />
<br />
<strong>UCS: </strong><br />
<br />
ISO制定的ISO10646标准所定义的 Universal Character Set, 采用4byte编码.<br />
<br />
<strong>Unicode与UCS的关系:</strong><br />
<br />
ISO与unicode.org是两个不同的组织, 因此最初制定了不同的标准; 但自从unicode2.0开始, unicode采用了与ISO 10646-1相同的字库和字码, ISO也承诺ISO10646将不会给超出0x10FFFF的UCS-4编码赋值, 使得两者保持一致.<br />
<br />
<strong>UCS的编码方式:</strong><br />
<br />
</p>
<li>UCS-2, 与unicode的2byte编码基本一样. <br />
<li>UCS-4, 4byte编码, 目前是在UCS-2前加上2个全零的byte.<br />
<br />
<strong>UTF: </strong>Unicode/UCS Transformation Format<br />
<li>UTF-8, 8bit编码, ASCII不作变换, 其他字符做变长编码, 每个字符1-3 byte. 通常作为外码. 有以下优点:<br />
* 与CPU字节顺序无关, 可以在不同平台之间交流<br />
* 容错能力高, 任何一个字节损坏后, 最多只会导致一个编码码位损失, 不会链锁错误(如GB码错一个字节就会整行乱码) <br />
<li>UTF-16, 16bit编码, 是变长码, 大致相当于20位编码, 值在0到0x10FFFF之间, 基本上就是unicode编码的实现. 它是变长码, 与CPU字序有关, 但因为最省空间, 常作为网络传输的外码.<br />
UTF-16是unicode的preferred encoding. <br />
<li>UTF-32, 仅使用了unicode范围(0到0x10FFFF)的32位编码, 相当于UCS-4的子集.<br />
<br />
<strong>UTF与unicode的关系:</strong><br />
<br />
Unicode是一个字符集, 可以看作为内码.<br />
而UTF是一种编码方式, 它的出现是因为unicode不适宜在某些场合直接传输和处理. UTF-16直接就是unicode编码, 没有变换, 但它包含了0x00在编码内, 头256字节码的第一个byte都是0x00, 在操作系统(C语言)中有特殊意义, 会引起问题. 采用UTF-8编码对unicode的直接编码作些变换可以避免这问题, 并带来一些优点.<br />
<br />
<strong>中国国标编码:</strong><br />
<li>GB 13000: 完全等同于ISO 10646-1/Unicode 2.1, 今后也将随ISO 10646/Unicode的标准更改而同步更改.<br />
<li>GBK: 对GB2312的扩充, 以容纳GB2312字符集范围以外的Unicode 2.1的统一汉字部分, 并且增加了部分unicode中没有的字符. <br />
<li>GB 18030-2000: 基于GB 13000, 作为Unicode 3.0的GBK扩展版本, 覆盖了所有unicode编码, 地位等同于UTF-8, UTF-16, 是一种unicode编码形式. 变长编码, 用单字节/双字节/4字节对字符编码. GB18030向下兼容GB2312/GBK. <br />
GB 18030是中国所有非手持/嵌入式计算机系统的强制实施标准.
<p><br />
-------------------------------<br />
</p>
<p><br />
&nbsp;</p>
<h2>什么是 UCS 和 ISO 10646?</h2>
<p>国际标准 <strong>ISO 10646</strong> 定义了 <strong>通用字符集 (Universal Character Set, UCS)</strong>. UCS 是所有其他字符集标准的一个超集. 它保证与其他字符集是双向兼容的. 就是说, 如果你将任何文本字符串翻译到 UCS格式, 然后再翻译回原编码, 你不会丢失任何信息.</p>
<p>UCS 包含了用于表达所有已知语言的字符. 不仅包括拉丁语,希腊语, 斯拉夫语,希伯来语,阿拉伯语,亚美尼亚语和乔治亚语的描述, 还包括中文, 日文和韩文这样的象形文字, 以及 平假名, 片假名, 孟加拉语, 旁遮普语果鲁穆奇字符(Gurmukhi), 泰米尔语, 印.埃纳德语(Kannada), Malayalam, 泰国语, 老挝语, 汉语拼音(Bopomofo), Hangul, Devangari, Gujarati, Oriya, Telugu 以及其他数也数不清的语. 对于还没有加入的语言, 由于正在研究怎样在计算机中最好地编码它们, 因而最终它们都将被加入. 这些语言包括 Tibetian, 高棉语, Runic(古代北欧文字), 埃塞俄比亚语, 其他象形文字, 以及各种各样的印-欧语系的语言, 还包括挑选出来的艺术语言比如 Tengwar, Cirth 和 克林贡语(Klingon). UCS 还包括大量的图形的, 印刷用的, 数学用的和科学用的符号, 包括所有由 TeX, Postscript, MS-DOS，MS-Windows, Macintosh, OCR 字体, 以及许多其他字处理和出版系统提供的字符.</p>
<p>ISO 10646 定义了一个 31 位的字符集. 然而, 在这巨大的编码空间中, 迄今为止只分配了前 65534 个码位 (0x0000 到 0xFFFD). 这个 UCS 的 16位子集称为 <strong>基本多语言面 (Basic Multilingual Plane, BMP)</strong>. 将被编码在 16 位 BMP 以外的字符都属于非常特殊的字符(比如象形文字), 且只有专家在历史和科学领域里才会用到它们. 按当前的计划, 将来也许再也不会有字符被分配到从 0x000000 到 0x10FFFF 这个覆盖了超过 100 万个潜在的未来字符的 21 位的编码空间以外去了. ISO 10646-1 标准第一次发表于 1993 年, 定义了字符集与 BMP 中内容的架构. 定义 BMP 以外的字符编码的第二部分 ISO 10646-2 正在准备中, 但也许要过好几年才能完成. 新的字符仍源源不断地加入到 BMP 中, 但已经存在的字符是稳定的且不会再改变了.</p>
<p>UCS 不仅给每个字符分配一个代码, 而且赋予了一个正式的名字. 表示一个 UCS 或 Unicode 值的十六进制数, 通常在前面加上 "U+", 就象 U+0041 代表字符"拉丁大写字母A". UCS 字符 U+0000 到 U+007F 与 US-ASCII(ISO 646) 是一致的, U+0000 到 U+00FF 与 ISO 8859-1(Latin-1) 也是一致的. 从 U+E000 到 U+F8FF, 已经 BMP 以外的大范围的编码是为私用保留的.</p>
<h2>什么是组合字符?</h2>
<p>UCS里有些编码点分配给了 <strong>组合字符</strong>.它们类似于打字机上的无间隔重音键. 单个的组合字符不是一个完整的字符. 它是一个类似于重音符或其他指示标记, 加在前一个字符后面. 因而, 重音符可以加在任何字符后面. 那些最重要的被加重的字符, 就象普通语言的正字法(orthographies of common languages)里用到的那种, 在 UCS 里都有自己的位置, 以确保同老的字符集的向后兼容性. 既有自己的编码位置, 又可以表示为一个普通字符跟随一个组合字符的被加重字符, 被称为 <strong>预作字符(precomposed characters)</strong>. UCS 里的预作字符是为了同没有预作字符的旧编码, 比如 ISO 8859, 保持向后兼容性而设的. 组合字符机制允许在任何字符后加上重音符或其他指示标记, 这在科学符号中特别有用, 比如数学方程式和国际音标字母, 可能会需要在一个基本字符后组合上一个或多个指示标记.</p>
<p>组合字符跟随着被修饰的字符. 比如, 德语中的元音变音字符 ("拉丁大写字母A 加上分音符"), 既可以表示为 UCS 码 U+00C4 的预作字符, 也可以表示成一个普通 "拉丁大写字母A" 跟着一个"组合分音符":U+0041 U+0308 这样的组合. 当需要堆叠多个重音符, 或在一个基本字符的上面和下面都要加上组合标记时, 可以使用多个组合字符. 比如在泰国文中, 一个基本字符最多可加上两个组合字符.</p>
<h2>什么是 UCS 实现级别?</h2>
<p>不是所有的系统都需要支持象组合字符这样的 UCS 里所有的先进机制. 因此 ISO 10646 指定了下列三种实现级别:
<dl>
<dt>级别1
<dd>不支持组合字符和 Hangul Jamo 字符 (一种特别的, 更加复杂的韩国文的编码, 使用两个或三个子字符来编码一个韩文音节)
<dt>级别2
<dd>类似于级别1, 但在某些文字中, 允许一列固定的组合字符 (例如, 希伯来文, 阿拉伯文, Devangari, 孟加拉语, 果鲁穆奇语, Gujarati, Oriya, 泰米尔语, Telugo, 印.埃纳德语, Malayalam, 泰国语和老挝语). 如果没有这最起码的几个组合字符, UCS 就不能完整地表达这些语言.
<dt>级别3
<dd>支持所有的 UCS 字符, 例如数学家可以在任意一个字符上加上一个 tilde(颚化符号,西班牙语字母上面的～)或一个箭头(或两者都加). </dd></dl>
<h2>什么是 Unicode?</h2>
<p>历史上, 有两个独立的, 创立单一字符集的尝试. 一个是<a href="http://www.iso.ch/">国际标准化组织(ISO)</a>的 ISO 10646 项目, 另一个是由(一开始大多是美国的)多语言软件制造商组成的协会组织的 <a href="http://www.unicode.org/">Unicode 项目</a>. 幸运的是, 1991年前后, 两个项目的参与者都认识到, 世界不需要两个不同的单一字符集. 它们合并双方的工作成果, 并为创立一个单一编码表而协同工作. 两个项目仍都存在并独立地公布各自的标准, 但 Unicode 协会和 ISO/IEC JTC1/SC2 都同意保持 Unicode 和 ISO 10646 标准的码表兼容, 并紧密地共同调整任何未来的扩展.</p>
<h2>那么 Unicode 和 ISO 10646 不同在什么地方?</h2>
<p>Unicode 协会公布的 <a href="http://www.unicode.org/unicode/standard/standard.html">Unicode 标准</a> 严密地包含了 ISO 10646-1 实现级别3的基本多语言面. 在两个标准里所有的字符都在相同的位置并且有相同的名字.</p>
<p>Unicode 标准额外定义了许多与字符有关的语义符号学, 一般而言是对于实现高质量的印刷出版系统的更好的参考. Unicode 详细说明了绘制某些语言(比如阿拉伯语)表达形式的算法, 处理双向文字(比如拉丁与希伯来文混合文字)的算法和 排序与字符串比较 所需的算法, 以及其他许多东西.</p>
<p>另一方面, ISO 10646 标准, 就象广为人知的 ISO 8859 标准一样, 只不过是一个简单的字符集表. 它指定了一些与标准有关的术语, 定义了一些编码的别名, 并包括了规范说明, 指定了怎样使用 UCS 连接其他 ISO 标准的实现, 比如 ISO 6429 和 ISO 2022. 还有一些与 ISO 紧密相关的, 比如 ISO 14651 是关于 UCS 字符串排序的.</p>
<p>考虑到 Unicode 标准有一个易记的名字, 且在任何好的书店里的 Addison-Wesley 里有, 只花费 ISO 版本的一小部分, 且包括更多的辅助信息, 因而它成为使用广泛得多的参考也就不足为奇了. 然而, 一般认为, 用于打印 ISO 10646-1 标准的字体在某些方面的质量要高于用于打印 Unicode 2.0的. 专业字体设计者总是被建议说要两个标准都实现, 但一些提供的样例字形有显著的区别. ISO 10646-1 标准同样使用四种不同的风格变体来显示表意文字如中文, 日文和韩文 (CJK), 而 Unicode 2.0 的表里只有中文的变体. 这导致了普遍的认为 Unicode 对日本用户来说是不可接收的传说, 尽管是错误的.</p>
<h2>什么是 UTF-8?</h2>
<p>首先 UCS 和 Unicode 只是分配整数给字符的编码表. 现在存在好几种将一串字符表示为一串字节的方法. 最显而易见的两种方法是将 Unicode 文本存储为 2 个 或 4 个字节序列的串. 这两种方法的正式名称分别为 UCS-2 和 UCS-4. 除非另外指定, 否则大多数的字节都是这样的(Bigendian convention). 将一个 ASCII 或 Latin-1 的文件转换成 UCS-2 只需简单地在每个 ASCII 字节前插入 0x00. 如果要转换成 UCS-4, 则必须在每个 ASCII 字节前插入三个 0x00.</p>
<p>在 Unix 下使用 UCS-2 (或 UCS-4) 会导致非常严重的问题. 用这些编码的字符串会包含一些特殊的字符, 比如 '\0' 或 '/', 它们在 文件名和其他 C 库函数参数里都有特别的含义. 另外, 大多数使用 ASCII 文件的 UNIX 下的工具, 如果不进行重大修改是无法读取 16 位的字符的. 基于这些原因, 在文件名, 文本文件, 环境变量等地方, <strong>UCS-2</strong> 不适合作为 <strong>Unicode</strong> 的外部编码.</p>
<p>在 ISO 10646-1 <a href="http://www.cl.cam.ac.uk/~mgk25/ucs/ISO-10646-UTF-8.html">Annex R</a> 和 <a href="ftp://ftp.funet.fi/mirrors/nic.nordu.net/rfc/rfc2279.txt">RFC 2279</a> 里定义的 <strong>UTF-8</strong> 编码没有这些问题. 它是在 Unix 风格的操作系统下使用 Unicode 的明显的方法.</p>
<p>UTF-8 有一下特性:
<ul>
    <li>UCS 字符 U+0000 到 U+007F (ASCII) 被编码为字节 0x00 到 0x7F (ASCII 兼容). 这意味着只包含 7 位 ASCII 字符的文件在 ASCII 和 UTF-8 两种编码方式下是一样的.
    <li>所有 &gt;U+007F 的 UCS 字符被编码为一个多个字节的串, 每个字节都有标记位集. 因此, ASCII 字节 (0x00-0x7F) 不可能作为任何其他字符的一部分.
    <li>表示非 ASCII 字符的多字节串的第一个字节总是在 0xC0 到 0xFD 的范围里, 并指出这个字符包含多少个字节. 多字节串的其余字节都在 0x80 到 0xBF 范围里. 这使得重新同步非常容易, 并使编码无国界, 且很少受丢失字节的影响.
    <li>可以编入所有可能的 2<sup>31</sup>个 UCS 代码
    <li>UTF-8 编码字符理论上可以最多到 6 个字节长, 然而 16 位 BMP 字符最多只用到 3 字节长.
    <li>Bigendian UCS-4 字节串的排列顺序是预定的.
    <li>字节 0xFE 和 0xFF 在 UTF-8 编码中从未用到. </li>
</ul>
<p>下列字节串用来表示一个字符. 用到哪个串取决于该字符在 Unicode 中的序号.</p>
<div align="center">
<center>
<table border="1">
    <tbody>
        <tr>
            <td>U-00000000 - U-0000007F: </td>
            <td>0<em>xxxxxxx</em> </td>
        </tr>
        <tr>
            <td>U-00000080 - U-000007FF: </td>
            <td>110<em>xxxxx</em> 10<em>xxxxxx</em> </td>
        </tr>
        <tr>
            <td>U-00000800 - U-0000FFFF: </td>
            <td>1110<em>xxxx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em> </td>
        </tr>
        <tr>
            <td>U-00010000 - U-001FFFFF: </td>
            <td>11110<em>xxx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em> </td>
        </tr>
        <tr>
            <td>U-00200000 - U-03FFFFFF: </td>
            <td>111110<em>xx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em> </td>
        </tr>
        <tr>
            <td>U-04000000 - U-7FFFFFFF: </td>
            <td>1111110<em>x</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em> 10<em>xxxxxx</em> </td>
        </tr>
    </tbody>
</table>
</center></div>
<p>xxx 的位置由字符编码数的二进制表示的位填入. 越靠右的 x 具有越少的特殊意义. 只用最短的那个足够表达一个字符编码数的多字节串. 注意在多字节串中, 第一个字节的开头"1"的数目就是整个串中字节的数目.</p>
<p><strong>例如</strong>: Unicode 字符 U+00A9 = 1010 1001 (版权符号) 在 UTF-8 里的编码为:</p>
<blockquote>
<p>11000010 10101001 = 0xC2 0xA9</p>
</blockquote>
<p>而字符 U+2260 = 0010 0010 0110 0000 (不等于) 编码为:</p>
<blockquote>
<p>11100010 10001001 10100000 = 0xE2 0x89 0xA0</p>
</blockquote>
<p>这种编码的官方名字拼写为 UTF-8, 其中 UTF 代表 <strong>U</strong>CS <strong>T</strong>ransformation <strong>F</strong>ormat. 请勿在任何文档中用其他名字 (比如 utf8 或 UTF_8) 来表示 UTF-8, 当然除非你指的是一个变量名而不是这种编码本身.</p>
<h2>什么编程语言支持 Unicode?</h2>
<p>在大约 1993 年之后开发的大多数现代编程语言都有一个特别的数据类型, 叫做 Unicode/ISO 10646-1 字符. 在 Ada95 中叫 Wide_Character, 在 Java 中叫 char.</p>
<p>ISO C 也详细说明了处理多字节编码和宽字符 (wide characters) 的机制, 1994 年 9 月 <a href="http://www.lysator.liu.se/c/na1.html">Amendment 1 to ISO C</a> 发表时又加入了更多. 这些机制主要是为各类东亚编码而设计的, 它们比处理 UCS 所需的要健壮得多. UTF-8 是 ISO C 标准调用多字节字符串的编码的一个例子, <em>wchar_t</em> 类型可以用来存放 Unicode 字符.</p>
<br />
<br />
<p id="TBPingURL">Trackback: http://tb.donews.net/TrackBack.aspx?PostId=188182</p>
</li>
</font></font>
<img src ="http://www.blogjava.net/midstr/aggbug/230163.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-09-20 17:37 <a href="http://www.blogjava.net/midstr/archive/2008/09/20/230163.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>字符集问题研究--字符集编码 zz</title><link>http://www.blogjava.net/midstr/archive/2008/09/20/230160.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Sat, 20 Sep 2008 09:18:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/09/20/230160.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/230160.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/09/20/230160.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/230160.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/230160.html</trackback:ping><description><![CDATA[<div class="t_msgfont" id="postmessage_1961"><strong><font size="4">1. 概述</font></strong><br />
本文主要包括以下几个方面：编码基本知识，java，系统软件，url，工具软件等。<br />
在下面的描述中，将以"中文"两个字为例，经查表可以知道其GB2312编码是"d6d0 cec4"，Unicode编码为"4e2d 6587"，UTF编码就是"e4b8ad e69687"。注意，这两个字没有iso8859-1编码，但可以用iso8859-1编码来"表示"。<br />
<br />
<strong><font size="4">2. 编码基本知识</font></strong><br />
最早的编码是iso8859-1，和ascii编码相似。但为了方便表示各种各样的语言，逐渐出现了很多标准编码，重要的有如下几个。<br />
<br />
<strong><font size="4">2.1. iso8859-1</font></strong><br />
属于单字节编码，最多能表示的字符范围是0-255，应用于英文系列。比如，字母'a'的编码为0x61=97。<br />
很明显，iso8859-1编码表示的字符范围很窄，无法表示中文字符。但是，由于是单字节编码，和计算机最基础的表示单位一致，所以很多时候，仍旧使用iso8859-1编码来表示。而且在很多协议上，默认使用该编码。比如，虽然"中文"两个字不存在iso8859-1编码，以gb2312编码为例，应该是"d6d0 cec4"两个字符，使用iso8859-1编码的时候则将它拆开为4个字节来表示："d6 d0 ce c4"（事实上，在进行存储的时候，也是以字节为单位处理的）。而如果是UTF编码，则是6个字节"e4 b8 ad e6 96 87"。很明显，这种表示方法还需要以另一种编码为基础。<br />
<br />
<strong><font size="3">2.2. GB2312/GBK</font></strong><br />
这就是汉子的国标码，专门用来表示汉字，是双字节编码，而英文字母和iso8859-1一致（兼容iso8859-1编码）。其中gbk编码能够用来同时表示繁体字和简体字，而gb2312只能表示简体字，gbk是兼容gb2312编码的。<br />
<br />
<strong><font size="3">2.3. unicode</font></strong><br />
这是最统一的编码，可以用来表示所有语言的字符，而且是定长双字节（也有四字节的）编码，包括英文字母在内。所以可以说它是不兼容iso8859-1编码的，也不兼容任何编码。不过，相对于iso8859-1编码来说，uniocode编码只是在前面增加了一个0字节，比如字母'a'为"00 61"。<br />
需要说明的是，定长编码便于计算机处理（注意GB2312/GBK不是定长编码），而unicode又可以用来表示所有字符，所以在很多软件内部是使用unicode编码来处理的，比如java。<br />
<br />
<strong><font size="3">2.4. UTF</font></strong><br />
考虑到unicode编码不兼容iso8859-1编码，而且容易占用更多的空间：因为对于英文字母，unicode也需要两个字节来表示。所以unicode不便于传输和存储。因此而产生了utf编码，utf编码兼容iso8859-1编码，同时也可以用来表示所有语言的字符，不过，utf编码是不定长编码，每一个字符的长度从1-6个字节不等。另外，utf编码自带简单的校验功能。一般来讲，英文字母都是用一个字节表示，而汉字使用三个字节。<br />
注意，虽然说utf是为了使用更少的空间而使用的，但那只是相对于unicode编码来说，如果已经知道是汉字，则使用GB2312/GBK无疑是最节省的。不过另一方面，值得说明的是，虽然utf编码对汉字使用3个字节，但即使对于汉字网页，utf编码也会比unicode编码节省，因为网页中包含了很多的英文字符。<br />
<br />
<strong><font size="4">3. java对字符的处理</font></strong><br />
在java应用软件中，会有多处涉及到<u><strong><font color="#ff0000">字符集</font></strong></u>编码，有些地方需要进行正确的设置，有些地方需要进行一定程度的处理。<br />
<br />
<strong><font size="3">3.1. getBytes(charset)</font></strong><br />
这是java字符串处理的一个标准函数，其作用是将字符串所表示的字符按照charset编码，并以字节方式表示。注意字符串在java内存中总是按unicode编码存储的。比如"中文"，正常情况下（即没有错误的时候）存储为"4e2d 6587"，如果charset为"gbk"，则被编码为"d6d0 cec4"，然后返回字节"d6 d0 ce c4"。如果charset为"utf8"则最后是"e4 b8 ad e6 96 87"。如果是"iso8859-1"，则由于无法编码，最后返回 "3f 3f"（两个问号）。<br />
<br />
<strong><font size="3">3.2. new String(charset)</font></strong><br />
这是java字符串处理的另一个标准函数，和上一个函数的作用相反，将字节数组按照charset编码进行组合识别，最后转换为unicode存储。参考上述getBytes的例子，"gbk" 和"utf8"都可以得出正确的结果"4e2d 6587"，但iso8859-1最后变成了"003f 003f"（两个问号）。<br />
因为utf8可以用来表示/编码所有字符，所以new String( str.getBytes( "utf8" ), "utf8" ) === str，即完全可逆。<br />
<br />
<strong><font size="3">3.3. setCharacterEncoding()</font></strong><br />
该函数用来设置http请求或者相应的编码。<br />
对于request，是指提交内容的编码，指定后可以通过getParameter()则直接获得正确的字符串，如果不指定，则默认使用iso8859-1编码，需要进一步处理。参见下述"表单输入"。值得注意的是在执行setCharacterEncoding()之前，不能执行任何getParameter()。java doc上说明：This method must be called prior to reading request parameters or reading input using getReader()。而且，该指定只对POST方法有效，对GET方法无效。分析原因，应该是在执行第一个getParameter()的时候，java将会按照编码分析所有的提交内容，而后续的getParameter()不再进行分析，所以setCharacterEncoding()无效。而对于GET方法提交表单是，提交的内容在URL中，一开始就已经按照编码分析所有的提交内容，setCharacterEncoding()自然就无效。<br />
对于response，则是指定输出内容的编码，同时，该设置会传递给浏览器，告诉浏览器输出内容所采用的编码。<br />
<br />
<strong><font size="3">3.4. 处理过程</font></strong><br />
下面分析两个有代表性的例子，说明java对编码有关问题的处理方法。<br />
<br />
<strong><font size="2">3.4.1. 表单输入</font></strong><br />
User input&nbsp;&nbsp;*(gbk:d6d0 cec4)&nbsp;&nbsp;browser&nbsp;&nbsp;*(gbk:d6d0 cec4)&nbsp;&nbsp;web server&nbsp;&nbsp;iso8859-1(00d6 00d 000ce 00c4)&nbsp;&nbsp;class，需要在class中进行处理：getbytes("iso8859-1")为d6 d0 ce c4，new String("gbk")为d6d0 cec4，内存中以unicode编码则为4e2d 6587。<br />
 用户输入的编码方式和页面指定的编码有关，也和用户的操作系统有关，所以是不确定的，上例以gbk为例。<br />
 从browser到web server，可以在表单中指定提交内容时使用的<u><strong><font color="#ff0000">字符集</font></strong></u>，否则会使用页面指定的编码。而如果在url中直接用?的方式输入参数，则其编码往往是操作系统本身的编码，因为这时和页面无关。上述仍旧以gbk编码为例。<br />
 Web server接收到的是字节流，默认时（getParameter）会以iso8859-1编码处理之，结果是不正确的，所以需要进行处理。但如果预先设置了编码（通过request. setCharacterEncoding ()），则能够直接获取到正确的结果。<br />
 在页面中指定编码是个好习惯，否则可能失去控制，无法指定正确的编码。<br />
<br />
<strong><font size="2">3.4.2. 文件编译</font></strong><br />
假设文件是gbk编码保存的，而编译有两种编码选择：gbk或者iso8859-1，前者是中文windows的默认编码，后者是linux的默认编码，当然也可以在编译时指定编码。<br />
Jsp&nbsp;&nbsp;*(gbk:d6d0 cec4)&nbsp;&nbsp;java file&nbsp;&nbsp;*(gbk:d6d0 cec4)&nbsp;&nbsp;compiler read&nbsp;&nbsp;uincode(gbk: 4e2d 6587; iso8859-1: 00d6 00d 000ce 00c4)&nbsp;&nbsp;compiler write&nbsp;&nbsp;utf(gbk: e4b8ad e69687; iso8859-1: *)&nbsp;&nbsp;compiled file&nbsp;&nbsp;unicode(gbk: 4e2d 6587; iso8859-1: 00d6 00d 000ce 00c4)&nbsp;&nbsp;class。所以用gbk编码保存，而用iso8859-1编译的结果是不正确的。<br />
class&nbsp;&nbsp;unicode(4e2d 6587)&nbsp;&nbsp;system.out / jsp.out&nbsp;&nbsp;gbk(d6d0 cec4)&nbsp;&nbsp;os console / browser。<br />
 文件可以以多种编码方式保存，中文windows下，默认为ansi/gbk。<br />
 编译器读取文件时，需要得到文件的编码，如果未指定，则使用系统默认编码。一般class文件，是以系统默认编码保存的，所以编译不会出问题，但对于jsp文件，如果在中文windows下编辑保存，而部署在英文linux下运行/编译，则会出现问题。所以需要在jsp文件中用pageEncoding指定编码。<br />
 Java编译的时候会转换成统一的unicode编码处理，最后保存的时候再转换为utf编码。<br />
 当系统输出字符的时候，会按指定编码输出，对于中文windows下，System.out将使用gbk编码，而对于response（浏览器），则使用jsp文件头指定的contentType，或者可以直接为response指定编码。同时，会告诉browser网页的编码。如果未指定，则会使用iso8859-1编码。对于中文，应该为browser指定输出字符串的编码。<br />
 browser显示网页的时候，首先使用response中指定的编码（jsp文件头指定的contentType最终也反映在response上），如果未指定，则会使用网页中meta项指定中的contentType。<br />
<br />
<strong><font size="3">3.5. 几处设置</font></strong><br />
对于web应用程序，和编码有关的设置或者函数如下。<br />
<br />
<strong><font size="2">3.5.1. jsp编译</font></strong><br />
指定文件的存储编码，很明显，该设置应该置于文件的开头。例如：&lt;%@page pageEncoding="GBK"%&gt;。另外，对于一般class文件，可以在编译的时候指定编码。<br />
<br />
<strong><font size="2">3.5.2. jsp输出</font></strong><br />
指定文件输出到browser是使用的编码，该设置也应该置于文件的开头。例如：&lt;%@ page contentType="text/html; charset= GBK" %&gt;。该设置和response.setCharacterEncoding("GBK")等效。<br />
<br />
<strong><font size="2">3.5.3. meta设置</font></strong><br />
指定网页使用的编码，该设置对静态网页尤其有作用。因为静态网页无法采用jsp的设置，而且也无法执行response.setCharacterEncoding()。例如：&lt;META http-equiv="Content-Type" content="text/html; charset=GBK" /&gt;<br />
如果同时采用了jsp输出和meta设置两种编码指定方式，则jsp指定的优先。因为jsp指定的直接体现在response中。<br />
需要注意的是，apache有一个设置可以给无编码指定的网页指定编码，该指定等同于jsp的编码指定方式，所以会覆盖静态网页中的meta指定。所以有人建议关闭该设置。<br />
<br />
<strong><font size="2">3.5.4. form设置</font></strong><br />
当浏览器提交表单的时候，可以指定相应的编码。例如：&lt;form accept-charset= "gb2312"&gt;。一般不必不使用该设置，浏览器会直接使用网页的编码。<br />
<br />
<strong><font size="4">4. 系统软件</font></strong><br />
下面讨论几个相关的系统软件。<br />
<br />
<strong><font size="3">4.1. mysql数据库</font></strong><br />
很明显，要支持多语言，应该将数据库的编码设置成utf或者unicode，而utf更适合与存储。但是，如果中文数据中包含的英文字母很少，其实unicode更为适合。<br />
数据库的编码可以通过mysql的配置文件设置，例如default-character-set=utf8。还可以在数据库链接URL中设置，例如： useUnicode=true&amp;characterEncoding=UTF-8。注意这两者应该保持一致，在新的sql版本里，在数据库链接URL里可以不进行设置，但也不能是错误的设置。<br />
<br />
<strong><font size="3">4.2. apache</font></strong><br />
appache和编码有关的配置在httpd.conf中，例如AddDefaultCharset UTF-8。如前所述，该功能会将所有静态页面的编码设置为UTF-8，最好关闭该功能。<br />
另外，apache还有单独的模块来处理网页响应头，其中也可能对编码进行设置。<br />
<br />
<strong><font size="3">4.3. linux默认编码</font></strong><br />
这里所说的linux默认编码，是指运行时的环境变量。两个重要的环境变量是LC_ALL和LANG，默认编码会影响到java URLEncode的行为，下面有描述。<br />
建议都设置为"zh_CN.UTF-8"。<br />
<br />
<strong><font size="3">4.4. 其它</font></strong><br />
为了支持中文文件名，linux在加载磁盘时应该指定<u><strong><font color="#ff0000">字符集</font></strong></u>，例如：mount /dev/hda5 /mnt/hda5/ -t ntfs -o iocharset=gb2312。<br />
另外，如前所述，使用GET方法提交的信息不支持request.setCharacterEncoding()，但可以通过tomcat的配置文件指定<u><strong><font color="#ff0000">字符集</font></strong></u>，在tomcat的server.xml文件中，形如：&lt;Connector ... URIEncoding="GBK"/&gt;。这种方法将统一设置所有请求，而不能针对具体页面进行设置，也不一定和browser使用的编码相同，所以有时候并不是所期望的。<br />
<br />
<strong><font size="4">5. URL地址</font></strong><br />
URL地址中含有中文字符是很麻烦的，前面描述过使用GET方法提交表单的情况，使用GET方法时，参数就是包含在URL中。<br />
<br />
<strong><font size="3">5.1. URL编码</font></strong><br />
对于URL中的一些特殊字符，浏览器会自动进行编码。这些字符除了"/?&amp;"等外，还包括unicode字符，比如汉子。这时的编码比较特殊。<br />
IE有一个选项"总是使用UTF-8发送URL"，当该选项有效时，IE将会对特殊字符进行UTF-8编码，同时进行URL编码。如果改选项无效，则使用默认编码"GBK"，并且不进行URL编码。但是，对于URL后面的参数，则总是不进行编码，相当于UTF-8选项无效。比如"中文.html?a=中文"，当UTF-8选项有效时，将发送链接"%e4%b8%ad%e6%96%87.html?a=\x4e\x2d\x65\x87"；而UTF-8选项无效时，将发送链接"\x4e\x2d\x65\x87.html?a=\x4e\x2d\x65\x87"。注意后者前面的"中文"两个字只有4个字节，而前者却有18个字节，这主要时URL编码的原因。<br />
当web server（tomcat）接收到该链接时，将会进行URL解码，即去掉"%"，同时按照ISO8859-1编码（上面已经描述，可以使用URLEncoding来设置成其它编码）识别。上述例子的结果分别是"\ue4\ub8\uad\ue6\u96\u87.html?a=\u4e\u2d\u65\u87"和"\u4e\u2d\u65\u87.html?a=\u4e\u2d\u65\u87"，注意前者前面的"中文"两个字恢复成了6个字符。这里用"\u"，表示是unicode。<br />
所以，由于客户端设置的不同，相同的链接，在服务器上得到了不同结果。这个问题不少人都遇到，却没有很好的解决办法。所以有的网站会建议用户尝试关闭UTF-8选项。不过，下面会描述一个更好的处理办法。<br />
<br />
<strong><font size="3">5.2. rewrite</font></strong><br />
熟悉的人都知道，apache有一个功能强大的rewrite模块，这里不描述其功能。需要说明的是该模块会自动将URL解码（去除%），即完成上述web server（tomcat）的部分功能。有相关文档介绍说可以使用[NE]参数来关闭该功能，但我试验并未成功，可能是因为版本（我使用的是apache 2.0.54）问题。另外，当参数中含有"?&amp; "等符号的时候，该功能将导致系统得不到正常结果。<br />
rewrite本身似乎完全是采用字节处理的方式，而不考虑字符串的编码，所以不会带来编码问题。<br />
<br />
<strong><font size="3">5.3. URLEncode.encode()</font></strong><br />
这是Java本身提供对的URL编码函数，完成的工作和上述UTF-8选项有效时浏览器所做的工作相似。值得说明的是，java已经不赞成不指定编码来使用该方法（deprecated）。应该在使用的时候增加编码指定。<br />
当不指定编码的时候，该方法使用系统默认编码，这会导致软件运行结果得不确定。比如对于"中文"，当系统默认编码为"gb2312"时，结果是"%4e%2d%65%87"，而默认编码为"UTF-8"，结果却是"%e4%b8%ad%e6%96%87"，后续程序将难以处理。另外，这儿说的系统默认编码是由运行tomcat时的环境变量LC_ALL和LANG等决定的，曾经出现过tomcat重启后就出现乱码的问题，最后才郁闷的发现是因为修改修改了这两个环境变量。<br />
建议统一指定为"UTF-8"编码，可能需要修改相应的程序。<br />
<br />
<strong><font size="3">5.4. 一个解决方案</font></strong><br />
上面说起过，因为浏览器设置的不同，对于同一个链接，web server收到的是不同内容，而软件系统有无法知道这中间的区别，所以这一协议目前还存在缺陷。<br />
针对具体问题，不应该侥幸认为所有客户的IE设置都是UTF-8有效的，也不应该粗暴的建议用户修改IE设置，要知道，用户不可能去记住每一个web server的设置。所以，接下来的解决办法就只能是让自己的程序多一点智能：根据内容来分析编码是否UTF-8。<br />
比较幸运的是UTF-8编码相当有规律，所以可以通过分析传输过来的链接内容，来判断是否是正确的UTF-8字符，如果是，则以UTF-8处理之，如果不是，则使用客户默认编码（比如"GBK"），下面是一个判断是否UTF-8的例子，如果你了解相应规律，就容易理解。
<div class="blockcode"><span class="headactions" onclick="copycode($('code0'));">复制内容到剪贴板</span>
<h5>代码:</h5>
<code id="code0">public static boolean isValidUtf8(byte[] b,int aMaxCount){<br />
&nbsp; &nbsp;&nbsp; &nbsp; int lLen=b.length,lCharCount=0;<br />
&nbsp; &nbsp;&nbsp; &nbsp; for(int i=0;i&lt;lLen &amp;&amp; lCharCount&lt;aMaxCount;++lCharCount){<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;byte lByte=b[i++];//to fast operation, ++ now, ready for the following for(;;)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;if(lByte&gt;=0) continue;//&gt;=0 is normal ascii<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;if(lByte&lt;(byte)0xc0 || lByte&gt;(byte)0xfd) return false;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;int lCount=lByte&gt;(byte)0xfc?5:lByte&gt;(byte)0xf8?4<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;:lByte&gt;(byte)0xf0?3:lByte&gt;(byte)0xe0?2:1;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;if(i+lCount&gt;lLen) return false;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;for(int j=0;j&lt;lCount;++j,++i) if(b[i]&gt;=(byte)0xc0) return false;<br />
&nbsp; &nbsp;&nbsp; &nbsp; }<br />
&nbsp; &nbsp;&nbsp; &nbsp; return true;<br />
}</code></div>
相应地，一个使用上述方法的例子如下：
<div class="blockcode"><span class="headactions" onclick="copycode($('code1'));">复制内容到剪贴板</span>
<h5>代码:</h5>
<code id="code1">public static String getUrlParam(String aStr,String aDefaultCharset)<br />
throws UnsupportedEncodingException{<br />
&nbsp; &nbsp;&nbsp; &nbsp; if(aStr==null) return null;<br />
&nbsp; &nbsp;&nbsp; &nbsp; byte[] lBytes=aStr.getBytes("ISO-8859-1");<br />
&nbsp; &nbsp;&nbsp; &nbsp; return new String(lBytes,StringUtil.isValidUtf8(lBytes)?"utf8":aDefaultCharset);<br />
}</code></div>
不过，该方法也存在缺陷，如下两方面：<br />
 没有包括对用户默认编码的识别，这可以根据请求信息的语言来判断，但不一定正确，因为我们有时候也会输入一些韩文，或者其他文字。<br />
 可能会错误判断UTF-8字符，一个例子是"学习"两个字，其GBK编码是" \xd1\xa7\xcf\xb0"，如果使用上述isValidUtf8方法判断，将返回true。可以考虑使用更严格的判断方法，不过估计效果不大。<br />
有一个例子可以证明google也遇到了上述问题，而且也采用了和上述相似的处理方法，比如，如果在地址栏中输入"http://www.google.com/search?hl=zh-CN&amp;newwindow=1&amp;q=学习"，google将无法正确识别，而其他汉字一般能够正常识别。<br />
最后，应该补充说明一下，如果不使用rewrite规则，或者通过表单提交数据，其实并不一定会遇到上述问题，因为这时可以在提交数据时指定希望的编码。另外，中文文件名确实会带来问题，应该谨慎使用。<br />
<br />
<strong><font size="4">6. 其它</font></strong><br />
下面描述一些和编码有关的其他问题。<br />
<br />
<strong><font size="3">6.1. SecureCRT</font></strong><br />
除了浏览器和控制台与编码有关外，一些客户端也很有关系。比如在使用SecureCRT连接linux时，应该让SecureCRT的显示编码（不同的session，可以有不同的编码设置）和linux的编码环境变量保持一致。否则看到的一些帮助信息，就可能是乱码。<br />
另外，mysql有自己的编码设置，也应该保持和SecureCRT的显示编码一致。否则通过SecureCRT执行sql语句的时候，可能无法处理中文字符，查询结果也会出现乱码。<br />
对于Utf-8文件，很多编辑器（比如记事本）会在文件开头增加三个不可见的标志字节，如果作为mysql的输入文件，则必须要去掉这三个字符。（用linux的vi保存可以去掉这三个字符）。一个有趣的现象是，在中文windows下，创建一个新txt文件，用记事本打开，输入"连通"两个字，保存，再打开，你会发现两个字没了，只留下一个小黑点。<br />
<br />
<strong><font size="3">6.2. 过滤器</font></strong><br />
如果需要统一设置编码，则通过filter进行设置是个不错的选择。在filter class中，可以统一为需要的请求或者回应设置编码。参加上述setCharacterEncoding()。这个类apache已经给出了可以直接使用的例子SetCharacterEncodingFilter。<br />
<br />
<strong><font size="3">6.3. POST和GET</font></strong><br />
很明显，以POST提交信息时，URL有更好的可读性，而且可以方便的使用setCharacterEncoding()来处理<u><strong><font color="#ff0000">字符集</font></strong></u>问题。但GET方法形成的URL能够更容易表达网页的实际内容，也能够用于收藏。<br />
从统一的角度考虑问题，建议采用GET方法，这要求在程序中获得参数是进行特殊处理，而无法使用setCharacterEncoding()的便利，如果不考虑rewrite，就不存在IE的UTF-8问题，可以考虑通过设置URIEncoding来方便获取URL中的参数。<br />
<br />
<strong><font size="3">6.4. 简繁体编码转换</font></strong><br />
GBK同时包含简体和繁体编码，也就是说同一个字，由于编码不同，在GBK编码下属于两个字。有时候，为了正确取得完整的结果，应该将繁体和简体进行统一。可以考虑将UTF、GBK中的所有繁体字，转换为相应的简体字，BIG5编码的数据，也应该转化成相应的简体字。当然，仍旧以UTF编码存储。<br />
例如，对于"语言 語言"，用UTF表示为"\xE8\xAF\xAD\xE8\xA8\x80 \xE8\xAA\x9E\xE8\xA8\x80"，进行简繁体编码转换后应该是两个相同的 "\xE8\xAF\xAD\xE8\xA8\x80&gt;"。</div>
<img src ="http://www.blogjava.net/midstr/aggbug/230160.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-09-20 17:18 <a href="http://www.blogjava.net/midstr/archive/2008/09/20/230160.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>碰到一个jsp中文传参乱码的问题</title><link>http://www.blogjava.net/midstr/archive/2008/09/20/230157.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Sat, 20 Sep 2008 09:03:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/09/20/230157.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/230157.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/09/20/230157.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/230157.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/230157.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 维护一个古董级的项目，在jsp传参的时候乱码了，如下：<br />
&nbsp;&nbsp;&nbsp;
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="color: #0000ff">&lt;</span><span style="color: #800000">jsp:forward&nbsp;</span><span style="color: #ff0000">page</span><span style="color: #0000ff">="/pub/msgpage/MsgTo.jsp"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">&lt;</span><span style="color: #800000">jsp:param&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="msg_Title"</span><span style="color: #ff0000">&nbsp;value</span><span style="color: #0000ff">='&lt;%=Form.getFES("回复成功")%</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">'/&gt;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">&lt;</span><span style="color: #800000">jsp:param&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="msg_Content"</span><span style="color: #ff0000">&nbsp;value</span><span style="color: #0000ff">='&lt;%=Form.getFES("回复成功,正在操作")%</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">'/&gt;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">&lt;</span><span style="color: #800000">jsp:param&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="url_to"</span><span style="color: #ff0000">&nbsp;value</span><span style="color: #0000ff">='&lt;%=addpic_url%</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">'/&gt;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">jsp:forward</span><span style="color: #0000ff">&gt;</span></div>
&nbsp;&nbsp; 使用request得到的都是问号，最后在网上找到了下面的一段话，才解开了我心中的谜团。<br />
&nbsp;&nbsp;
<table style="width: 836px; height: 118px" cellspacing="2" cellpadding="2" width="836" align="center" border="0">
    <tbody>
        <tr>
            <td><font style="background-color: #cce8cf">最近在做GGLook的时候,发现&lt;jsp:forword&gt;被tomcat generate成了...pageContent.forword(...java.util.URLEncoder.encode("" + ... )); 看了函数原形java.util.URLEncoder.encode有两种形式:1.encode(String s)&nbsp; 2.encode(String s, String enc).对于第二个,我们可以对编码进行设置.但是对于第一个,j2sdk实现的默认编码却是iso-8859-1.没搞懂为什么内部编码为UNICODE的java要把他实现成为iso-8859-1.还有就是tomcat为什么不采用配置文件的方式使我们自己能设定其编码方式.现在一跳转到errorpage.jsp就是乱码.没办法,要吗改j2sdk,要吗改tomcat.最后,确定下载tomcat原代码包,将Generator.java改掉,重新编译,现在一切运行正常!</font></td>
        </tr>
    </tbody>
</table>
&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp; 原来是因为url里面没有指定编码，会默认使用ISO-8859-1进行编码，而ISO-8859-1是不支持中文的，即URLEncoder.encode之后&nbsp; 都会显示<font style="background-color: #cce8cf">%3F%3F%3F，所以之后无论使用何种字符集解码都是问号了。。。</font><br />
&nbsp;&nbsp; 最后的解决方案有一下几种，其中第四种没有成功：<br />
<ol>
    <li><font style="background-color: #cce8cf">写个filter，然后在filter里面进行<font style="background-color: #cce8cf">request.setCharacterEncoding("GBK")</font></font>
    <li><font style="background-color: #cce8cf"><font style="background-color: #cce8cf">每个jsp页面的头部都写上request.setCharacterEncoding("GBK")，原理和1是一样的</font></font>
    <li><font style="background-color: #cce8cf"><font style="background-color: #cce8cf">传参数前先对中文进行encode，得到参数后再使用对应的decode，这样的话传递的参数就不会丢失，但是比较麻烦</font></font>
    <li><font style="background-color: #cce8cf"><font style="background-color: #cce8cf">修改tomcat的server.xml配置文件，在<font style="background-color: #cce8cf">&lt;Connector</font>&gt;节点增加一个属性：URIEncoding="GBK"，但是感觉这个参数没有起作用，官方文档是这么描述的&#8220;This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used. &#8221;</font></font> </li>
</ol>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 我的理解是要区分你是怎么提交数据的，如果是Post的话，则会使用过滤器；如果是Get方式的话，tomcat默认会使用URIEncoding----是tomcat的server.xml配置文件，在&lt;Connector&gt;节点有一个URIEncoding的属性，如果不配置的话默认是：URIEncoding="ISO-8859-1"，官方文档是这么描述的&#8220;This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used. &#8221;<br />
因为ajaxAnywhere.getAJAX是通过Get提交数据的（sends a GET request to the server.），所以还是使用了ISO-8859-1编码。<br />
<br />
<span style="font-size: 10pt; color: #3366ff">&nbsp;HTTP 定义了与服务器交互的不同方法，最基本的方法是 GET 和 POST。事实上 GET 适用于多数请求，而保留 POST 仅用于更新站点。根据 HTTP 规范，GET 用于信息获取，而且应该是 安全的和 幂等的。所谓安全的意味着该操作用于获取信息而非修改信息。换句话说，GET 请求一般不应产生副作用。幂等的意味着对同一 URL 的多个请求应该返回同样的结果。完整的定义并不像看起来那样严格。从根本上讲，其目标是当用户打开一个链接时，她可以确信从自身的角度来看没有改变资源。比如，新闻站点的头版不断更新。虽然第二次请求会返回不同的一批新闻，该操作仍然被认为是安全的和幂等的，因为它总是返回当前的新闻。反之亦然。POST 请求就不那么轻松了。POST 表示可能改变服务器上的资源的请求。仍然以新闻站点为例，读者对文章的注解应该通过 POST 请求实现，因为在注解提交之后站点已经不同了（比方说文章下面出现一条注解）；<br />
&nbsp;<br />
在FORM提交的时候，如果不指定Method，则默认为GET请求，Form中提交的数据将会附加在url之后，以?分开与url分开。字母数字字符原样发送，但空格转换为&#8220;+&#8220;号，其它符号转换为%XX,其中XX为该符号以16进制表示的ASCII（或ISO Latin-1）值。GET请求请提交的数据放置在HTTP请求协议头中，而POST提交的数据则放在实体数据中； <br />
<br />
GET方式提交的数据最多只能有1024字节，而POST则没有此限制。</span><br />
<br />
&nbsp; </p>
<img src ="http://www.blogjava.net/midstr/aggbug/230157.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-09-20 17:03 <a href="http://www.blogjava.net/midstr/archive/2008/09/20/230157.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>soloaris环境下tomcat日志奇怪问题</title><link>http://www.blogjava.net/midstr/archive/2008/09/12/228582.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Fri, 12 Sep 2008 06:11:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/09/12/228582.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/228582.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/09/12/228582.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/228582.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/228582.html</trackback:ping><description><![CDATA[<div class="t_msgfont" id="postmessage_47903">在soloaris环境下<br />
在使用过程中后台报了很多如下的<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B4%ED%CE%F3">错误</span>，目前还不能确定该错误和<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%D3%A6%D3%C3">应用</span>程序的操作有什么关系，并且在<br />
该错误的前后一般都没有报其他系统异常。<br />
<br />
2007-9-6 0:14:30 org.apache.tomcat.util.net.TcpWorkerThread runIt<br />
严重: Remote Host /172.16.16.94 SocketException: 无效的自<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B1%E4%C1%BF">变量</span><br />
2007-9-6 0:14:30 org.apache.tomcat.util.net.TcpWorkerThread runIt<br />
严重: Remote Host /172.16.16.94 SocketException: 无效的自变量<br />
<br />
目前从网上找到一种说法是给soloaris打补丁，因为2.61的soloaris是最新的，所以还没有试用该方法。<br />
不知道大家有什么碰到过？给些意见和经验</div>
<br />
<br />
找到下面这篇文章，基本可以确定这个错应该忽略，实际使用过程中也没有因为这个日志错而导致什么问题出现。<br />
<a href="http://www.diybl.com/course/4_webprogram/jsp/jsp_js/200855/113650.html" target="_blank">Tomcat的SEVERE: Remote Host / SocketException: Connection reset原因分析及解决办法</a>
<div class="quote">
<h5>引用:</h5>
<blockquote>昨天在测试帮助文件时发现一直打不开，好像是一直再刷新，于是就到服务器上查看Tomcat的日志，就发现了下面的信息：<br />
Apr 21, 2008 9:27:34 AM org.apache.tomcat.util.net.TcpWorkerThread runIt<br />
SEVERE: Remote Host /172.16.128.248 SocketException: Connection reset<br />
并且这两条信息几乎是每个1-2秒就出现一次，很是频繁。于是就搜索了一下，就找到了下面的内容：<br />
The usual cause is that the browser''s stopped a HTTP request part-way through, <br />
generally because the user''s navigated to another page before the first page has<br />
completely downloaded. The browser closes the connection, with the result that <br />
Tomcat gets an exception when it next tries to write data to the socket. <br />
Arguably it shouldn''t be logged as a SEVERE error on production systems, but <br />
getting that log message during development and stress testing can be very <br />
handy! 于是就查看它引用的JavaScript文件，发现好多不存在。终于明白，是因为有些变量不存在，导致了这里的反复重载。重新加入这些JavaScript文件后，问题解决。<br />
<br />
Fix it by any of the following (in increasing order of difficulty): <br />
<br />
1) Ignore it (and change any log-reading scripts that look for SEVERE errors to <br />
ignore this one); <br />
<br />
2) Grab the source for 5.0.28, find the line where this is logged and change the<br />
logging level in the case of a connection reset error, then recompile Tomcat; <br />
<br />
3) Educate your users that they are supposed to sit on their hands until the <br />
page has completely loaded (by far the hardest ;-) ). <br />
<br />
后面还有别人的补充：<br />
If it happens that often and you don''t have a high traffic site, it might be a monitor script, that does only check if it can do a TCP connect and drop the connection before a full HTTP request-response cycle has finished. <br />
<br />
不过我的情况和上面所说的都不符合，于是就查看了源文件，发现了如下代码：<br />
<br />
<br />
<br />
if (!window.gbWhVer||!window.gbWhUtil||!window.gbWhMsg)<br />
&nbsp; &nbsp; document.location.reload();</blockquote></div>
<img src ="http://www.blogjava.net/midstr/aggbug/228582.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-09-12 14:11 <a href="http://www.blogjava.net/midstr/archive/2008/09/12/228582.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate和Spring的延迟加载和DAO模式 zz</title><link>http://www.blogjava.net/midstr/archive/2008/09/11/228404.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Thu, 11 Sep 2008 09:01:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/09/11/228404.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/228404.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/09/11/228404.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/228404.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/228404.html</trackback:ping><description><![CDATA[<div class="cnt" id="blog_text">
<h1 class="block_title"><font size="3">Hibernate和Spring的延迟加载和DAO模式</font></h1>
<div class="post">
<div class="postcontent">转载于：http://spaces.msn.com/members/zcgly/Blog/cns!1pQwDnSfBx4siamZpHR2gqMQ!121.entry<br />
<br />
<div>Hibernate和Spring的延迟加载和DAO模式<br />
原文：<font color="#095801">http://www.jroller.com/page/kbaum/20040708</font><br />
作者：Karl Baum<br />
译者：zcgly</div>
<div>时间：2005－07－13</div>
<div>Hibernate和延迟加载<br />
Hibernate对象关系映射提供了两种对象初始化模式：延迟加载和非延迟加载。非延迟加载在加载时获取对象本身以及它关联的所有对象</div>
<div>。这可能导致在获取一个实例时，执行成百上千的select语句。当使用双向关联时，这个问题被放大，常常出现初始化请求时，整个数据</div>
<div>库都被载入。显然检查每个对象的关系，并手工删除他们会费点事，但最终我们可能会因此丢失使用ORM工具的优势。</div>
<div>一个明细的解决方式是使用hibernate提供的延迟载入机制。这种初始化策略在类成员被访问时只载入它的一个对象的一对多和多对多关</div>
<div>系。对开发人员来说，这种方式是透明的，并且只有最少数量的请求发生，这样就获得了最佳的性能。这种技术的一个缺点是延迟载入要</div>
<div>求当对象还在使用中时，Hibernate的Session必须保持打开状态。当尝试通过DAO模式抽象持久层时，这会引起一个重要问题。为了充分</div>
<div>地抽象持久层，所有的数据库逻辑，包括打开、关闭Session都不能在应用层出现。最常见的是，这些逻辑隐藏在DAO的实现类中。快速和</div>
<div>差一些的方案是：避免采用DAO模式，在应用层中包含数据连接的逻辑。这在小应用中是可行的，但在大系统中，这会是一个设计缺陷，</div>
<div>它损害了应用的扩展性。</div>
<div>在Web层使用延迟加载<br />
幸运的是，Spring框架已经提供了一个DAO模式结合Hibernate延迟加载的Web方案。对于任何不熟悉Spring框架结合Hibernate人来说，我</div>
<div>在这里不会深入细节，但是我希望你去阅读&#8220;结合Spring框架的Hibernate数据库访问&#8221;章节。这个案例是一个Web应用，Spring提供了</div>
<div>OpenSessionInViewerFilter和OpenSessionInViewInterceptor。使用它们中的任一个都能获得同样的功能。这两者唯一不同的是</div>
<div>interceptor在Spring容器中运行，并且在web应用的上下文中配置；fitler在Spring前运行，并且在web.xml中配置。不管使用哪一个，</div>
<div>他们都会在请求绑定到Session的当前线程期间打开Hibernate Session。一旦绑定到线程，打开的Hibernate Session能被DAO的实现类透</div>
<div>明地使用。Session会持续打开允许延迟加载访问数据库。一旦View逻辑完成，hibernate session会被关闭，无论是在Filter的doFilter</div>
<div>方法中还是在Interceptor的postHandle方法中。下面是一个配置实例：<br />
Interceptor配置</div>
<div>&lt;beans&gt; <br />
&lt;bean id="urlMapping"&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"&gt;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="interceptors"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;list&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref bean="openSessionInViewInterceptor"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/list&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="mappings"&gt;<br />
...<br />
&lt;/bean&gt;<br />
...<br />
&lt;bean name="openSessionInViewInterceptor" <br />
&nbsp;&nbsp;&nbsp; class="org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="sessionFactory"&gt;&lt;ref bean="sessionFactory"/&gt;&lt;/property&gt;<br />
&lt;/bean&gt;<br />
&lt;/beans&gt;</div>
<div>Filter配置</div>
<div>&lt;web-app&gt;<br />
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;filter&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;filter-name&gt;hibernateFilter&lt;/filter-name&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;filter-class&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.springframework.orm.hibernate.support.OpenSessionInViewFilter<br />
&nbsp;&nbsp;&nbsp; &lt;/filter-class&gt;<br />
&nbsp;&nbsp; &lt;/filter&gt;<br />
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;filter-mapping&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;filter-name&gt;hibernateFilter&lt;/filter-name&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;*.spring&lt;/url-pattern&gt;<br />
&lt;/filter-mapping&gt;<br />
...<br />
&lt;/web-app&gt;<br />
使用打开的session的HibernateDAO实现类很简单。实际上，如果你已经使用Spring框架实现Hibernate的DAO对象，最有可能的是，你不</div>
<div>需要做任何改动。DAO必须通过方便的HibernateTemplate工具访问Hibernate，这对数据库访问来说就是小菜一碟。下面是一个DAO的实例</div>
<div>。<br />
DAO实例</div>
<div>public class HibernateProductDAO extends HibernateDaoSupport implements ProductDAO {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Product getProduct(Integer productId) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (Product)getHibernateTemplate().load(Product.class, productId);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Integer saveProduct(Product product) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (Integer) getHibernateTemplate().save(product);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void updateProduct(Product product) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getHibernateTemplate().update(product);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
}</div>
<div>在业务层使用延迟加载<br />
甚至在表现层外，Spring框架也通过AOP拦截器HibernateInterceptor提供了便利的延迟加载支持。hibernate拦截器透明地拦截了配置在</div>
<div>Spring应用上下文中的业务对象的调用，在调用前打开hibernate session，在调用结束时关闭这个session。让我们通过一个简单的例子</div>
<div>来说明。假设我们有一个interface叫做BussinessObject：<br />
public interface BusinessObject { <br />
&nbsp;&nbsp;&nbsp;&nbsp; public void doSomethingThatInvolvesDaos(); <br />
}<br />
类BusinessObjectImpl实现了BusinessObject接口：<br />
public class BusinessObjectImpl implements BusinessObject {<br />
&nbsp;&nbsp;&nbsp; public void doSomethingThatInvolvesDaos() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // lots of logic that calls<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // DAO classes Which access <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // data objects lazily<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
通过Spring上下文的一些配置，我们可以让HibernateInterceptor拦截对BusinessObjectImpl的调用，允许它的方法延迟访问数据对象。</div>
<div>看一下下面的片断：<br />
&lt;beans&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;bean id="hibernateInterceptor" class="org.springframework.orm.hibernate.HibernateInterceptor"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="sessionFactory"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref bean="sessionFactory"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;bean id="businessObjectTarget" class="com.acompany.BusinessObjectImpl"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="someDAO"&gt;&lt;ref bean="someDAO"/&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;bean id="businessObject" class="org.springframework.aop.framework.ProxyFactoryBean"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="target"&gt;&lt;ref bean="businessObjectTarget"/&gt;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="proxyInterfaces"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;com.acompany.BusinessObject&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="interceptorNames"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;list&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;hibernateInterceptor&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/list&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/bean&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&lt;/beans&gt;<br />
当businessObject的实例被引用，HibernateInterceptor打开一个hibernate session并允许对BussinessObjectImpl的调用。当</div>
<div>BusinessOjbectImpl执行完成，HibernateInterceptor透明的关闭这个session。应用代码并不知道任何持久层逻辑，但它仍然能够使用</div>
<div>延迟加载访问数据对象。</div>
<div>在单元测试中使用延迟加载<br />
最后，我们要在JUnit中测试我们的延迟加载应用。覆盖TestCase类的setUp和tearDown方法非常容易。我更喜欢将这段代码放在一个简便</div>
<div>的抽象TestCase类中，作为我所有测试的基类。<br />
public abstract class MyLazyTestCase extends TestCase {</div>
<div><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setUp() throws Exception {<br />
&nbsp;&nbsp;&nbsp;&nbsp; super.setUp();<br />
&nbsp;&nbsp;&nbsp;&nbsp; SessionFactory sessionFactory = (SessionFactory) getBean("sessionFactory");<br />
&nbsp;&nbsp;&nbsp;&nbsp; Session s = sessionFactory.openSession();<br />
&nbsp;&nbsp;&nbsp;&nbsp; TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s));</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; protected Object getBean(String beanName) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Code to get objects from Spring application context<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void tearDown() throws Exception {<br />
&nbsp;&nbsp;&nbsp;&nbsp; super.tearDown();<br />
&nbsp;&nbsp;&nbsp;&nbsp; SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);<br />
&nbsp;&nbsp;&nbsp;&nbsp; Session s = holder.getSession(); <br />
&nbsp;&nbsp;&nbsp;&nbsp; s.flush();<br />
&nbsp;&nbsp;&nbsp;&nbsp; TransactionSynchronizationManager.unbindResource(sessionFactory);<br />
&nbsp;&nbsp;&nbsp;&nbsp; SessionFactoryUtils.closeSessionIfNecessary(s, sessionFactory);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
</div>
</div>
</div>
<br />
<br />
<br />
<br />
<span style="color: red"><br />
附一个比较好的使用连接。<br />
<a style="color: red" href="http://chen-516888.javaeye.com/blog/231519">http://chen-516888.javaeye.com/blog/231519</a></span></div>
<img src ="http://www.blogjava.net/midstr/aggbug/228404.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-09-11 17:01 <a href="http://www.blogjava.net/midstr/archive/2008/09/11/228404.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tomcat连接池的三个重要参数</title><link>http://www.blogjava.net/midstr/archive/2008/09/07/227483.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Sun, 07 Sep 2008 01:43:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/09/07/227483.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/227483.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/09/07/227483.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/227483.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/227483.html</trackback:ping><description><![CDATA[<div class="quote">
<h5>引用:</h5>
<blockquote>a.&nbsp; &nbsp;如果设为true则tomcat自动检查恢复重新利用，没有正常关闭的Connection.（默认是false）<br />
&nbsp;&nbsp;&lt;parameter&gt;<br />
&nbsp;&nbsp;&lt;name&gt;removeAbandoned&lt;/name&gt;<br />
&nbsp;&nbsp;&lt;value&gt;true&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/parameter&gt;<br />
b.&nbsp; &nbsp;设定连接在多少秒内被认为是放弃的连接，即可进行恢复利用。<br />
&nbsp;&nbsp;&lt;parameter&gt;<br />
&nbsp;&nbsp;&lt;name&gt;removeAbandonedTimeout&lt;/name&gt;<br />
&nbsp;&nbsp;&lt;value&gt;60&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/parameter&gt;<br />
c.&nbsp; &nbsp;输出回收的<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%C8%D5%D6%BE">日志</span>，可以详细打印出异常从而发现是在那里发生了泄漏<br />
&nbsp;&nbsp;&lt;parameter&gt;<br />
&nbsp;&nbsp;&lt;name&gt;logAbandoned&lt;/name&gt;<br />
&nbsp;&nbsp;&lt;value&gt;true&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/parameter&gt; </blockquote></div>
实验<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%BB%B7%BE%B3">环境</span>，tomcat配置连接池，最大连接数为5.<br />
<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B4%FA%C2%EB">代码</span>如下：
<div class="quote">&nbsp;
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #0000ff">&lt;</span><span style="color: #800000">parameter</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">maxActive</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">5</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">parameter</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">parameter</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">maxIdle</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">1</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">parameter</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">parameter</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">maxWait</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">20000</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">parameter</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">parameter</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">removeAbandoned</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">true</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">parameter</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">parameter</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">removeAbandonedTimeout</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">60</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">parameter</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">parameter</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">logAbandoned</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">name</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">true</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">parameter</span><span style="color: #0000ff">&gt;</span></div>
</div>
使用如下代码进行实验（每一次不关闭连接）：
<div class="blockcode">
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #0000ff">try</span><span style="color: #000000">&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;Connection&nbsp;con&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;getJdbcDAO().getDataSource().getConnection();<br />
&nbsp;&nbsp;&nbsp;&nbsp;ResultSet&nbsp;rs&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;con.createStatement().executeQuery(</span><span style="color: #000000">"</span><span style="color: #000000">select&nbsp;*&nbsp;from&nbsp;K_MS..B_MSPBXX</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;(rs.next())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(rs.getString(</span><span style="color: #000000">1</span><span style="color: #000000">));<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(SQLException&nbsp;e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
}<br />
</span></div>
<br />
当该连续执行5次之后，后台就报连接池满的错： </div>
<div class="quote">
<h5>2008-09-06 14:31:02,471 [org.hibernate.util.JDBCExceptionReporter]-[WARN] <span class="t_tag" onclick="tagshow(event)" href="tag.php?name=SQL">SQL</span> Error: 0, SQLState: null<br />
2008-09-06 14:31:02,471 [org.hibernate.util.JDBCExceptionReporter]-[ERROR] Cannot get a connection, pool exhausted<br />
2008-09-06 14:31:02,580 [org.hibernate.util.JDBCExceptionReporter]-[WARN] SQL Error: 0, SQLState: null<br />
2008-09-06 14:31:02,580 [org.hibernate.util.JDBCExceptionReporter]-[ERROR] Cannot get a connection, pool exhausted</h5>
</div>
根据如下脚本查<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CA%FD%BE%DD%BF%E2"><span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CA%FD%BE%DD">数据</span>库</span>连接
<div class="quote">
<h5>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="color: #0000ff">declare</span><span style="color: #000000">&nbsp;cur_spid&nbsp;</span><span style="color: #0000ff">cursor</span><span style="color: #000000">&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">for</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">select</span><span style="color: #000000">&nbsp;spid&nbsp;</span><span style="color: #0000ff">from</span><span style="color: #000000">&nbsp;sysprocesses&nbsp;</span><span style="color: #0000ff">where</span><span style="color: #000000">&nbsp;ipaddr</span><span style="color: #808080">=</span><span style="color: #ff0000">'</span><span style="color: #ff0000">172.16.16.145</span><span style="color: #ff0000">'</span><span style="color: #000000">&nbsp;</span><span style="color: #808080">and</span><span style="color: #000000">&nbsp;program_name&nbsp;</span><span style="color: #808080">&lt;&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #ff0000">'</span><span style="color: #ff0000">SQL_Advantage</span><span style="color: #ff0000">'</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">go</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">declare</span><span style="color: #000000">&nbsp;</span><span style="color: #008000">@spid</span><span style="color: #000000">&nbsp;</span><span style="font-weight: bold; color: #000000">Integer</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">open</span><span style="color: #000000">&nbsp;&nbsp;cur_spid<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">fetch</span><span style="color: #000000">&nbsp;cur_spid&nbsp;</span><span style="color: #0000ff">into</span><span style="color: #000000">&nbsp;</span><span style="color: #008000">@spid</span><span style="color: #000000">&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;</span><span style="font-weight: bold; color: #008000">@@sqlstatus</span><span style="color: #808080">=</span><span style="font-weight: bold; color: #800000">0</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">begin</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">print</span><span style="color: #000000">&nbsp;</span><span style="color: #ff0000">'</span><span style="color: #ff0000">%1!</span><span style="color: #ff0000">'</span><span style="color: #000000">&nbsp;,&nbsp;</span><span style="color: #008000">@spid</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;</span><span style="color: #0000ff">dbcc</span><span style="color: #000000">&nbsp;traceon(</span><span style="font-weight: bold; color: #800000">3604</span><span style="color: #000000">)<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;</span><span style="color: #0000ff">dbcc</span><span style="color: #000000">&nbsp;sqltext(</span><span style="color: #008000">@spid</span><span style="color: #000000">&nbsp;)<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;</span><span style="color: #0000ff">fetch</span><span style="color: #000000">&nbsp;cur_spid&nbsp;</span><span style="color: #0000ff">into</span><span style="color: #000000">&nbsp;</span><span style="color: #008000">@spid</span><span style="color: #000000">&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">end</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">close</span><span style="color: #000000">&nbsp;cur_spid<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div>
&nbsp;</h5>
</div>
得到类似如下的五条记录，即有5个连接没有释放
<div class="quote">
<h5>引用:</h5>
<blockquote>95<br />
DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role. <br />
SQL Text: select * from K_MS..B_MSPBXX <br />
DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role. </blockquote></div>
如果继续执行该代码，后台就报如下错，提示哪里的代码没有关闭连接(已经具体到那一行代码获取的连接没有关闭，这个很重要！！！下面红颜色标注的异常点信息就是具体连接没有释放的代码信息）
<div class="quote">
<h5>&nbsp;</h5>
<blockquote>DBCP object created 2008-09-06 14:27:32 by the following code was never closed:<br />
java.lang.Exception<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;at org.apache.commons.dbcp.AbandonedTrace.init(AbandonedTrace.java:96)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;at org.apache.commons.dbcp.AbandonedTrace.&lt;init&gt;(AbandonedTrace.java:79)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;at org.apache.commons.dbcp.DelegatingResultSet.&lt;init&gt;(DelegatingResultSet.java:71)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;at org.apache.commons.dbcp.DelegatingResultSet.wrapResultSet(DelegatingResultSet.java:80)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;at org.apache.commons.dbcp.DelegatingStatement.executeQuery(DelegatingStatement.java:205)<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<font color="red">at com.thunisoft.fy.spxt.SpxtBaseLogic.createPbxx(SpxtBaseLogic.java:5772</font>)</blockquote></div>
如果时间超过removeAbandonedTimeout设置的时间，再直接使用上面的sql脚本查看数据库连接发现已经都被释放了，并且如果再进行其他数据库操作已经不报连接池满的<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CE%CA%CC%E2">问题</span>。说明过了60秒之后，tomcat会把那些它认为没有释放的连接进行释放。<br />
<br />
&nbsp; &nbsp; 然后同样的java代码，把tomcat连接池的那三个<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B2%CE%CA%FD">参数</span>去掉之后，执行5次之后也报连接池满，但是再次执行就不能获取新的连接，并且后台的日志都是连接池满的信息，而没有具体那一行代码的连接没有释放的异常信息。<br />
<br />
&nbsp; &nbsp; 因为生产环境还是出现连接池满的问题（基本上两天报一次），准备把这三个参数放到实际环境中试试然后看看后台日志，一是想得到具体是哪些地方的代码没有释放，二是如果设置removeAbandonedTimeout参数，可以避免连接没有释放的问题。当然个人认为最终部署环境是不需要该参数的，在程序中把连接释放才是解决问题的最根本办法，另外目前还不知道这三个参数会对tomcat性能造成什么影响，应该不大。<br />
<img src ="http://www.blogjava.net/midstr/aggbug/227483.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-09-07 09:43 <a href="http://www.blogjava.net/midstr/archive/2008/09/07/227483.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>tomcat连接池泄露的监控和解决 zz</title><link>http://www.blogjava.net/midstr/archive/2008/09/03/226782.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Wed, 03 Sep 2008 13:22:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/09/03/226782.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/226782.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/09/03/226782.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/226782.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/226782.html</trackback:ping><description><![CDATA[1.&nbsp;&nbsp; 问题描述<br />
Web程序在tomcat刚开始运行时速度很快，但过一段时间后发现速度变得很慢。<br />
检查日志输出，发现异常如下:<br />
org.apache.commons.dbcp.SQLNestedException:&nbsp;&nbsp; Cannot&nbsp;&nbsp; get&nbsp;&nbsp; a&nbsp;&nbsp; connection,&nbsp;&nbsp; pool&nbsp;&nbsp; exhausted,&nbsp;&nbsp; cause:&nbsp;&nbsp;<br />
java.util.NoSuchElementException:&nbsp;&nbsp; Timeout&nbsp;&nbsp; waiting&nbsp;&nbsp; for&nbsp;&nbsp; idle&nbsp;&nbsp; object<br />
同时在SQLServer事件探查器中发现，每执行一次sql语句都要产生Audit&nbsp;&nbsp; login事件，语句执行后产生<br />
Audit&nbsp;&nbsp; logout事件。说明每一次tomcat都是重新打开新的连接。<br />
<br />
2.&nbsp;&nbsp; 问题解决<br />
tomcat&nbsp;&nbsp; 的数据源定义提供了三个参数：<br />
a.&nbsp;&nbsp; 如果设为true则tomcat自动检查恢复重新利用，没有正常关闭的Connection.（默认是false）<br />
&lt;parameter&gt;<br />
&lt;name&gt;removeAbandoned&lt;/name&gt;<br />
&lt;value&gt;true&lt;/value&gt;<br />
&lt;/parameter&gt;<br />
b.&nbsp;&nbsp; 设定连接在多少秒内被认为是放弃的连接，即可进行恢复利用。<br />
&lt;parameter&gt;<br />
&lt;name&gt;removeAbandonedTimeout&lt;/name&gt;<br />
&lt;value&gt;60&lt;/value&gt;<br />
&lt;/parameter&gt;<br />
c.&nbsp;&nbsp; 输出回收的日志，可以详细打印出异常从而发现是在那里发生了泄漏<br />
&lt;parameter&gt;<br />
&lt;name&gt;logAbandoned&lt;/name&gt;<br />
&lt;value&gt;true&lt;/value&gt;<br />
&lt;/parameter&gt;&nbsp;&nbsp;<br />
<img src ="http://www.blogjava.net/midstr/aggbug/226782.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-09-03 21:22 <a href="http://www.blogjava.net/midstr/archive/2008/09/03/226782.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数据库连接池满的问题</title><link>http://www.blogjava.net/midstr/archive/2008/08/30/225743.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Sat, 30 Aug 2008 07:03:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/08/30/225743.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/225743.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/08/30/225743.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/225743.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/225743.html</trackback:ping><description><![CDATA[XX系统在生产环境使用一定时间后表现出用户不能登录，后台tomcat日志报如下错：<br />
&nbsp;&nbsp;&nbsp;
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">&nbsp;</span><span style="color: #000000">2008</span><span style="color: #000000">-</span><span style="color: #000000">08</span><span style="color: #000000">-</span><span style="color: #000000">14</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">12</span><span style="color: #000000">:</span><span style="color: #000000">31</span><span style="color: #000000">:</span><span style="color: #000000">35</span><span style="color: #000000">,</span><span style="color: #000000">029</span><span style="color: #000000">&nbsp;[org.hibernate.util.JDBCExceptionReporter]</span><span style="color: #000000">-</span><span style="color: #000000">[WARN]&nbsp;SQL&nbsp;Error:&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;SQLState:&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">2008</span><span style="color: #000000">-</span><span style="color: #000000">08</span><span style="color: #000000">-</span><span style="color: #000000">14</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">12</span><span style="color: #000000">:</span><span style="color: #000000">31</span><span style="color: #000000">:</span><span style="color: #000000">35</span><span style="color: #000000">,</span><span style="color: #000000">029</span><span style="color: #000000">&nbsp;[org.hibernate.util.JDBCExceptionReporter]</span><span style="color: #000000">-</span><span style="color: #000000">[ERROR]&nbsp;Cannot&nbsp;get&nbsp;a&nbsp;connection,&nbsp;pool&nbsp;exhausted<br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">2008</span><span style="color: #000000">-</span><span style="color: #000000">08</span><span style="color: #000000">-</span><span style="color: #000000">14</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">12</span><span style="color: #000000">:</span><span style="color: #000000">31</span><span style="color: #000000">:</span><span style="color: #000000">35</span><span style="color: #000000">,</span><span style="color: #000000">029</span><span style="color: #000000">&nbsp;[org.hibernate.util.JDBCExceptionReporter]</span><span style="color: #000000">-</span><span style="color: #000000">[WARN]&nbsp;SQL&nbsp;Error:&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;SQLState:&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">2008</span><span style="color: #000000">-</span><span style="color: #000000">08</span><span style="color: #000000">-</span><span style="color: #000000">14</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">12</span><span style="color: #000000">:</span><span style="color: #000000">31</span><span style="color: #000000">:</span><span style="color: #000000">35</span><span style="color: #000000">,</span><span style="color: #000000">029</span><span style="color: #000000">&nbsp;[org.hibernate.util.JDBCExceptionReporter]</span><span style="color: #000000">-</span><span style="color: #000000">[ERROR]&nbsp;Cannot&nbsp;get&nbsp;a&nbsp;connection,&nbsp;pool&nbsp;exhausted<br />
</span></div>
<br />
&nbsp;&nbsp;&nbsp;显然是连接池满了，驻地工程师重启之后就可以正常使用了。因为我们的tomcat连接池的配置连接<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B2%CE%CA%FD">参数</span>好像很大，所以应该肯定是程序出<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CE%CA%CC%E2">问题</span>了。后来在测试那也出现了同样的问题，因为测试的人比较多，所以那两天基本上一两个小时连接池就满了，当时只能一次一次的重启tomcat。<br />
&nbsp; &nbsp;因为XX系统之前已经修改过一次因为<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B4%FA%C2%EB">代码</span>的<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B4%ED%CE%F3">错误</span>而导致的<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CA%FD%BE%DD%BF%E2"><span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CA%FD%BE%DD">数据</span>库</span>连接没有释放的问题，所以这一次的问题比较不好定位，不能知道是哪些操作的连接池没有释放。<br />
&nbsp; &nbsp;后来由zhxy提供了如下的查看当前数据库（<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=sybase">sybase</span>）哪些连接没有被释放的脚本，其中的ip为tomcat的发布地址（因为数据库连接都是由tomcat发起）：
<div class="blockcode">
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #0000ff">declare</span><span style="color: #000000">&nbsp;cur_spid&nbsp;</span><span style="color: #0000ff">cursor</span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #0000ff">for</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">select</span><span style="color: #000000">&nbsp;spid&nbsp;</span><span style="color: #0000ff">from</span><span style="color: #000000">&nbsp;sysprocesses&nbsp;</span><span style="color: #0000ff">where</span><span style="color: #000000">&nbsp;ipaddr</span><span style="color: #808080">=</span><span style="color: #ff0000">'</span><span style="color: #ff0000">172.16.7.8</span><span style="color: #ff0000">'</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">go</span><span style="color: #000000"><br />
<br />
</span><span style="color: #0000ff">declare</span><span style="color: #000000">&nbsp;</span><span style="color: #008000">@spid</span><span style="color: #000000">&nbsp;</span><span style="font-weight: bold; color: #000000">Integer</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">open</span><span style="color: #000000">&nbsp;&nbsp;cur_spid<br />
</span><span style="color: #0000ff">fetch</span><span style="color: #000000">&nbsp;cur_spid&nbsp;</span><span style="color: #0000ff">into</span><span style="color: #000000">&nbsp;</span><span style="color: #008000">@spid</span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;</span><span style="font-weight: bold; color: #008000">@@sqlstatus</span><span style="color: #808080">=</span><span style="font-weight: bold; color: #800000">0</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">begin</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">print</span><span style="color: #000000">&nbsp;</span><span style="color: #ff0000">'</span><span style="color: #ff0000">%1!</span><span style="color: #ff0000">'</span><span style="color: #000000">&nbsp;,&nbsp;</span><span style="color: #008000">@spid</span><span style="color: #000000"><br />
&nbsp;&nbsp;</span><span style="color: #0000ff">dbcc</span><span style="color: #000000">&nbsp;traceon(</span><span style="font-weight: bold; color: #800000">3604</span><span style="color: #000000">)<br />
&nbsp;&nbsp;</span><span style="color: #0000ff">dbcc</span><span style="color: #000000">&nbsp;sqltext(</span><span style="color: #008000">@spid</span><span style="color: #000000">&nbsp;)<br />
&nbsp;&nbsp;</span><span style="color: #0000ff">fetch</span><span style="color: #000000">&nbsp;cur_spid&nbsp;</span><span style="color: #0000ff">into</span><span style="color: #000000">&nbsp;</span><span style="color: #008000">@spid</span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #0000ff">end</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">close</span><span style="color: #000000">&nbsp;cur_spid<br />
</span></div>
<br />
使用该脚本只能之后，执行结果都是打印出大量类似的下面的三行： </div>
<div class="blockcode">
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="font-weight: bold; color: #800000">184</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">DBCC</span><span style="color: #000000">&nbsp;execution&nbsp;completed.&nbsp;</span><span style="color: #0000ff">If</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">DBCC</span><span style="color: #000000">&nbsp;printed&nbsp;error&nbsp;messages,&nbsp;contact&nbsp;a&nbsp;</span><span style="color: #ff00ff">user</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">with</span><span style="color: #000000">&nbsp;System&nbsp;Administrator&nbsp;(SA)&nbsp;role.&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />SQL&nbsp;</span><span style="font-weight: bold; color: #000000">Text</span><span style="color: #000000">:&nbsp;</span><span style="color: #0000ff">set</span><span style="color: #000000">&nbsp;CHAINED&nbsp;</span><span style="color: #0000ff">off</span><span style="color: #000000">&nbsp;</span></div>
</div>
直接使用上面的脚本打印的结果是当前占用数据库连接池的spid（第一行），以及连接正在执行的sql（第三行）。&nbsp; &nbsp;<br />
&nbsp;&nbsp;后来发现每登录一次审判系统，使用上面的脚本执行结果就会有一个连接没有被释放（一般连接会在一段时间之后释放），除非是重启tomcat否则一直占用。<br />
&nbsp;&nbsp;跟踪<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B5%C7%C2%BD">登陆</span>代码发现有如下的写法（调用存储过程）：
<div class="blockcode">
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">Session&nbsp;session&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.getSession();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Transaction&nbsp;tx&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;session.beginTransaction();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Connection&nbsp;con&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;session.connection();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">try</span><span style="color: #000000">&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&#8230;&#8230;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CallableStatement&nbsp;cstmt&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;con.prepareCall(</span><span style="color: #000000">"</span><span style="color: #000000">{call&nbsp;K_TJ..PR_GET_AjCount(?,?,?,?,?,?,?,?,?,?,?,?)&nbsp;}</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&#8230;&#8230;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ResultSet&nbsp;resultSet&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;cstmt.executeQuery();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tx.commit();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(resultSet.next())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ajCount&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;resultSet.getInt(</span><span style="color: #000000">1</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultSet.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(Exception&nbsp;e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tx.rollback();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff">finally</span><span style="color: #000000">{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">try</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(SQLException&nbsp;e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span></div>
<br />
这里有几个问题，一是把hibernate和connection的用法使用混乱了；二是使用session获取的连接不需要自己关闭，应该关闭session（一个session对应一个connection），这里刚好用使用反了。<br />
&nbsp; &nbsp;&nbsp; &nbsp;后来试着把con.close()改成session.close()问题就没有了，后来经zhangjy提醒，如果是使用spring提供的getSession()获取的连接，最好是使用releaseSession()方法进行释放。引用原话&#8220;release不一定是关闭连接，就像连接池的连接一样。release只是放回池中，你要关闭了 就不能放回池中了 而且 直接close可能会抛异常，release不会抛异常 因为里边有对<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%BB%B7%BE%B3">环境</span>的判断&#8221;，把con.close()改成releaseSession()问题也解决了。<br />
&nbsp; &nbsp;&nbsp; &nbsp;但是我们的项目中使用了spring，对存储过程调用最好是使用jdbcTemplate。退一步如果要获取一个connection，最好能使用<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=Summer">Summer</span>提供的jdbcDao获取，即jdbcdao.getDataSource().getConnection()，当然这样的连接完全就需要自己手工关闭了。<br />
&nbsp; &nbsp;&nbsp; &nbsp;最后搜了一下代码，把程序中如上调用存储过程的地方全部改为使用jdbcTemplate问题解决。最终代码如下: </div>
<div class="blockcode">
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">getJdbcDAO().getJdbcTemplate().execute(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">{call&nbsp;K_TJ..PR_GET_AjCount(?,?,?,?,?,?,?,?,?,?,?,?)&nbsp;}</span><span style="color: #000000">"</span><span style="color: #000000">,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;CallableStatementCallback()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Object&nbsp;doInCallableStatement(CallableStatement&nbsp;cstmt)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;SQLException,&nbsp;DataAccessException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&#8230;&#8230;</span><span style="color: #008000"><br />
</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ResultSet&nbsp;resultSet&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;cstmt.executeQuery();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(resultSet.next())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Integer(resultSet.getInt(</span><span style="color: #000000">1</span><span style="color: #000000">));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;&#8230;&#8230;</span><span style="color: #008000"><br />
</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});</span></div>
</div>
连接池的问题解决。<br />
<img src ="http://www.blogjava.net/midstr/aggbug/225743.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-08-30 15:03 <a href="http://www.blogjava.net/midstr/archive/2008/08/30/225743.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个存储过程执行一半莫名退出的解决（zz）</title><link>http://www.blogjava.net/midstr/archive/2008/08/30/225742.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Sat, 30 Aug 2008 06:57:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/08/30/225742.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/225742.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/08/30/225742.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/225742.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/225742.html</trackback:ping><description><![CDATA[<div class="t_msgfont" id="postmessage_9795">使用java定时调用存储过程，存储过程的功能是修改表A中字段F&nbsp;&nbsp;is null的记录，设置字段F＝X，正常执行是执行一次后表A中将不会有F is null的记录，<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CE%CA%CC%E2">问题</span>是：每次执行都只修改了表A的2或3条记录<br />
<br />
而这个存储过程在<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CA%FD%BE%DD%BF%E2"><span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CA%FD%BE%DD">数据</span>库</span>客户端<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B9%A4%BE%DF">工具</span>中直接执行是正确的。<br />
<br />
<strong>解决方法</strong><br />
如果你的存储过程中包括insert、delete、update操作，切记：<br />
（1）如果是<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=jdbc">jdbc</span>调用，使用statement.executeUpdate("sp_xxxx")，千万不能使用statement.execute("sp_xxxx")<br />
（2）如果使用spring的dao框架：使用jdbcDao.getJDBCTemplate.update("sp_xxxx")，同样不要使用jdbcDao.getJDBCTemplate.execute("sp_xxxx")</div>
<br />
<br />
<h2>三期开发中也遇到了类似的问题</h2>
<div class="t_msgfont" id="postmessage_47378">案件从在审库转未立库的时候，存储过程执行了一半就退出了，查了好久，幸好在这里找到答案了：）<br />
之前我们一直这么用<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">String&nbsp;procedure&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">{call&nbsp;K_FY..PR_ZS2WL_</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;getAJLBShortName(iAjlb)&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">(?)&nbsp;}</span><span style="color: #000000">"</span><span style="color: #000000">;<br />
getJdbcDAO().getJdbcTemplate().execute(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;procedure,&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;CallableStatementCallback()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Object&nbsp;doInCallableStatement(CallableStatement&nbsp;cstmt)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;SQLException,&nbsp;DataAccessException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cstmt.setLong(</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;lAjbh);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cstmt.execute();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});<br />
</span></div>
<br />
我把<font color="red">cstmt.execute();</font>改成<font color="red">cstmt.executeUpdate();</font>之后就可以了<br />
但是奇怪的是 案件从在审库转到审结库的时候确是正常执行，没有任何<font size="5"><font color="darkorchid">异常迹象</font></font><br />
ps：在审转未立和在审转审结这两个存储过程的结构是一样的，有很多insert、update和delete的操作</div>
<br />
<br />
<div class="t_msgfont" id="postmessage_47386">这个是在sybase下发生的问题。jdbc的标准虽然是那么定的－－execute()中调用了executeUpdate()，但sybase实现的com.sybase.jdbc3.jdbc.SybDriver就不好说了</div>
<img src ="http://www.blogjava.net/midstr/aggbug/225742.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-08-30 14:57 <a href="http://www.blogjava.net/midstr/archive/2008/08/30/225742.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java调用存储过程的传递Date参数的问题</title><link>http://www.blogjava.net/midstr/archive/2008/08/30/225740.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Sat, 30 Aug 2008 06:53:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/08/30/225740.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/225740.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/08/30/225740.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/225740.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/225740.html</trackback:ping><description><![CDATA[建了一个存储过程
<div class="blockcode">
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #0000ff">create</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">procedure</span><span style="color: #000000">&nbsp;PR_YDFT_GETFT_TIME&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: #008000">@AJLB</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-weight: bold; color: #000000">tinyint</span><span style="color: #000000">,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008080">--</span><span style="color: #008080">&nbsp;案件类别&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008080"><br />
</span><span style="color: #000000">&nbsp;&nbsp;</span><span style="color: #008000">@AJBHLIST</span><span style="color: #000000">&nbsp;&nbsp;</span><span style="font-weight: bold; color: #000000">varchar</span><span style="color: #000000">(</span><span style="font-weight: bold; color: #800000">1500</span><span style="color: #000000">),&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008080">--</span><span style="color: #008080">&nbsp;案件编号列表</span><span style="color: #008080"><br />
</span><span style="color: #000000">&nbsp;&nbsp;</span><span style="color: #008000">@KSSJ</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-weight: bold; color: #000000">datetime</span><span style="color: #000000">,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008080">--</span><span style="color: #008080">&nbsp;开始时间</span><span style="color: #008080"><br />
</span><span style="color: #000000">&nbsp;&nbsp;</span><span style="color: #008000">@JSSJ</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-weight: bold; color: #000000">datetime</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008080">--</span><span style="color: #008080">&nbsp;结束时间&nbsp;</span><span style="color: #008080"><br />
</span><span style="color: #000000"><br />
</span><span style="color: #0000ff">as</span><span style="color: #000000">&nbsp;<br />
</span><span style="color: #0000ff">begin</span><span style="color: #000000"><br />
&#8230;&#8230;&#8230;&#8230;<br />
</span><span style="color: #0000ff">select</span><span style="color: #000000">&nbsp;BH,&nbsp;AH&nbsp;</span><span style="color: #0000ff">from</span><span style="color: #000000">&nbsp;K_ZS..B_ZX&nbsp;</span><span style="color: #0000ff">where</span><span style="color: #000000"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><img src="http://www.blogjava.net/Images/dot.gif"  alt="" />(这里返回一个结果集)<br />
</span><span style="color: #0000ff">end</span><span style="color: #000000"><br />
</span></div>
<br />
在java代码中如下调用（时间类型为java.sql.Date），即使<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CA%FD%BE%DD%BF%E2"><span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CA%FD%BE%DD">数据</span>库</span>有数据，也不能正确返回结果集： </div>
<div class="blockcode"><code id="code1">
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Object&nbsp;doInCallableStatement(CallableStatement&nbsp;cs)&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;SQLException,&nbsp;DataAccessException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cs.setDate(</span><span style="color: #000000">3</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;java.sql.Date(kssj.getTime()));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cs.setDate(</span><span style="color: #000000">4</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;java.sql.Date(jssj.getTime()));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
</span><span style="color: #000000">}<br />
</span></div>
</code></div>
但是将方法改为如下（时间类型为String），就可以正常返回结果集：
<div class="blockcode"><code id="code2">
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img id="Codehighlighter1_99_270_Open_Image" onclick="this.style.display='none'; Codehighlighter1_99_270_Open_Text.style.display='none'; Codehighlighter1_99_270_Closed_Image.style.display='inline'; Codehighlighter1_99_270_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_99_270_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_99_270_Closed_Text.style.display='none'; Codehighlighter1_99_270_Open_Image.style.display='inline'; Codehighlighter1_99_270_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Object&nbsp;doInCallableStatement(CallableStatement&nbsp;cs)&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;SQLException,&nbsp;DataAccessException&nbsp;</span><span id="Codehighlighter1_99_270_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_99_270_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cs.setString(</span><span style="color: #000000">3</span><span style="color: #000000">,&nbsp;kssj);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;cs.setString(</span><span style="color: #000000">4</span><span style="color: #000000">,&nbsp;jssj);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
<br />
&nbsp;&nbsp;&nbsp; </code>另外在<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=sybase">sybase</span>的sqladv中如下两种调用方式均可正确返回结果： </div>
<div class="blockcode">
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">use</span><span style="color: #000000">&nbsp;K_RW<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">go</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />PR_YDFT_GETFT_TIME&nbsp;</span><span style="font-weight: bold; color: #800000">2</span><span style="color: #000000">,&nbsp;"</span><span style="font-weight: bold; color: #800000">109052298</span><span style="color: #000000">;",&nbsp;"</span><span style="font-weight: bold; color: #800000">2008</span><span style="color: #808080">-</span><span style="font-weight: bold; color: #800000">08</span><span style="color: #808080">-</span><span style="font-weight: bold; color: #800000">19</span><span style="color: #000000">&nbsp;</span><span style="font-weight: bold; color: #800000">14</span><span style="color: #000000">:</span><span style="font-weight: bold; color: #800000">00</span><span style="color: #000000">:</span><span style="font-weight: bold; color: #800000">00</span><span style="color: #000000">",&nbsp;"</span><span style="font-weight: bold; color: #800000">2008</span><span style="color: #808080">-</span><span style="font-weight: bold; color: #800000">08</span><span style="color: #808080">-</span><span style="font-weight: bold; color: #800000">19</span><span style="color: #000000">&nbsp;</span><span style="font-weight: bold; color: #800000">17</span><span style="color: #000000">:</span><span style="font-weight: bold; color: #800000">00</span><span style="color: #000000">:</span><span style="font-weight: bold; color: #800000">00</span><span style="color: #000000">"<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
</div>
<div class="blockcode">
<h5>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">use</span><span style="color: #000000">&nbsp;K_RW<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">go</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">declare</span><span style="color: #000000">&nbsp;</span><span style="color: #008000">@KSSJ</span><span style="color: #000000">&nbsp;</span><span style="font-weight: bold; color: #000000">datetime</span><span style="color: #000000">&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">declare</span><span style="color: #000000">&nbsp;</span><span style="color: #008000">@JSSJ</span><span style="color: #000000">&nbsp;</span><span style="font-weight: bold; color: #000000">datetime</span><span style="color: #000000">&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">select</span><span style="color: #000000">&nbsp;</span><span style="color: #008000">@KSSJ</span><span style="color: #000000">&nbsp;</span><span style="color: #808080">=</span><span style="color: #000000">&nbsp;</span><span style="color: #ff00ff">convert</span><span style="color: #000000">(</span><span style="font-weight: bold; color: #000000">datetime</span><span style="color: #000000">,"</span><span style="font-weight: bold; color: #800000">2008</span><span style="color: #808080">-</span><span style="font-weight: bold; color: #800000">08</span><span style="color: #808080">-</span><span style="font-weight: bold; color: #800000">19</span><span style="color: #000000">&nbsp;</span><span style="font-weight: bold; color: #800000">14</span><span style="color: #000000">:</span><span style="font-weight: bold; color: #800000">00</span><span style="color: #000000">:</span><span style="font-weight: bold; color: #800000">00</span><span style="color: #000000">")<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">select</span><span style="color: #000000">&nbsp;</span><span style="color: #008000">@JSSJ</span><span style="color: #000000">&nbsp;</span><span style="color: #808080">=</span><span style="color: #000000">&nbsp;&nbsp;</span><span style="color: #ff00ff">convert</span><span style="color: #000000">(</span><span style="font-weight: bold; color: #000000">datetime</span><span style="color: #000000">,"</span><span style="font-weight: bold; color: #800000">2008</span><span style="color: #808080">-</span><span style="font-weight: bold; color: #800000">08</span><span style="color: #808080">-</span><span style="font-weight: bold; color: #800000">19</span><span style="color: #000000">&nbsp;</span><span style="font-weight: bold; color: #800000">17</span><span style="color: #000000">:</span><span style="font-weight: bold; color: #800000">00</span><span style="color: #000000">:</span><span style="font-weight: bold; color: #800000">00</span><span style="color: #000000">")<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">execute</span><span style="color: #000000">&nbsp;PR_YDFT_GETFT_TIME&nbsp;</span><span style="font-weight: bold; color: #800000">2</span><span style="color: #000000">,&nbsp;"</span><span style="font-weight: bold; color: #800000">109052298</span><span style="color: #000000">;",&nbsp;</span><span style="color: #008000">@KSSJ</span><span style="color: #000000">&nbsp;,</span><span style="color: #008000">@JSSJ</span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
</h5>
在java代码中调用只是将java.sql.Date参数类型改为String传递就能正常返回结果集，是不是因为sybase的<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%C7%FD%B6%AF">驱动</span>有<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CE%CA%CC%E2">问题</span>？<br />
<br />
<br />
问题原因找到了，是因为使用cs.setDate()给数据库传参数只会日期部分。<br />
如果改用如下代码就可以： </div>
<div class="blockcode">
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">cs.setTimestamp(</span><span style="color: #000000">3</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;java.sql.Timestamp(dKssj.getTime()));<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />cs.setTimestamp(</span><span style="color: #000000">4</span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;java.sql.Timestamp(dJssj.getTime()));</span></div>
</div>
cs.setTimestamp()可以将日期和时间部分都传给数据库。 
<img src ="http://www.blogjava.net/midstr/aggbug/225740.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-08-30 14:53 <a href="http://www.blogjava.net/midstr/archive/2008/08/30/225740.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java性能测试工具</title><link>http://www.blogjava.net/midstr/archive/2008/05/22/202202.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Thu, 22 May 2008 08:36:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/05/22/202202.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/202202.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/05/22/202202.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/202202.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/202202.html</trackback:ping><description><![CDATA[&nbsp; 商业工具&nbsp;&nbsp;<a title="三款java分析器点评" href="http://www.yesky.com/SoftChannel/72342371961929728/20031005/1733975.shtml">三款java分析器点评</a><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、Jprofiler ej-techologies&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、Borland Optimizeit Suite <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3、Quest Jprobe Quest Software&nbsp;<br />
<br />
&nbsp; 免费工具<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4、Eclipse&nbsp;Profiler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font style="background-color: #cce8cf"><a href="http://sourceforge.net/projects/eclipsecolorer/">http://sourceforge.net/projects/eclipsecolorer/</a></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5、netbeans Profile&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<font style="background-color: #cce8cf"><a href="http://profiler.netbeans.org/index.html">http://profiler.netbeans.org/index.html</a></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6、Eclipse TPTP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font style="background-color: #cce8cf"><a href="http://www.eclipse.org/tptp/">http://www.eclipse.org/tptp/</a></font><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<a title="open source profiler for java" href="http://www.manageability.org/blog/stuff/open-source-profilers-for-java/view">open source profiler for java</a>&nbsp;&nbsp; zz
<blockquote>
<ul>
    <li><a href="http://profiler.cougaar.org/">Cougaar Memory Profiler<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - The Cougaar memory profiler is a tool for debugging memory usage and leaks in any Java application. It features a scalable 100% Java design that is lighter weight than existing JVMPI-based profilers. The profiler tracks memory usage within the application by using tables of WeakReferences.
    <li><a href="http://oss.metaparadigm.com/jmemprof/">JMemProf<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - JMemProf is a live Java memory profiler suitable for deployment in web containers such as JBoss, Tomcat and others. JMemProf allows you to retrieve memory profile information while your application is running. JMemProf aims to add dynamic visibility to memory usage in Java web applications; memory profile information can be viewed easily through a Servlet based web interface while the application is running. It is much more dynamic and easily understandable than that of the hprof heap profiler bundled with the J2SDK.
    <li><a href="http://www.khelekore.org/jmp/">JMP<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - JMP is a profiler for java that can be used to trace objects usage and method timings. JMP uses the JVMPI interface to gather statistics and interact with the JVM. JMP uses a GTK+ interface to show the status.
    <li><a href="http://ejp.sourceforge.net/">Extensible Java Profiler<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - Extensible Java Profiler (EJP) is a profiling tool for Java with a scalable and extensible architecture, allowing its usage for exotic programming languages that use a Java backend. EJP is based on the Java Virtual Machine Profiler Interface (JVMPI). It can be used to trace the execution of small parts of Java programs and display it in hierarchical trees with some elements hidden or highlighted.
    <li><a href="http://www.javaperformancetuning.com/tools/jamon/index.shtml">JAMon <img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a>- The Java Application Monitor (JAMon) is a free, simple, high performance, thread safe, Java API that allows developers to easily monitor production applications. JAMon can be used to determine application performance bottlenecks, user/application interactions, and application scalability. JAMon gathers summary statistics such as hits, execution times (total, average, minimum, maximum, standard deviation), and simultaneous application requests. JAMon statistics are displayed in the sortable JAMon report.
    <li><a href="http://jmechanic.sourceforge.net/">jMechanic<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - jMechanic is an Eclipse Java IDE plugin providing Java Profiling tools. Tools such as CPU Sampling and Heap Summary allow the Java developer to tune up the performance of their Java programs all within the comfort of the Eclipse IDE.
    <li><a href="http://jrat.sourceforge.net/">JRat<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - JRat is the Java Runtime Analysis Toolkit. Its purpose is to enable developers to better understand the runtime behavior of their Java programs. There are currently a number of ways JRat can monitor an application (i.e. Bytecode instrumentation, JBoss AOP, Dynamic Proxies, JDI).
    <li><a href="http://eclipsecolorer.sourceforge.net/index_profiler.html">Eclipse Profiler<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - This is a plugin for the Eclipse platform which allows java code profiling.
    <li><a href="http://xdprof.sourceforge.net/">xdProf<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - xdProf is a cross-platform tool that captures and analyzes stack traces sent at a fixed interval from Java Virtual Machines in a distributed system. The performance impact of the xdProf client sending data over a local area network is minimal: less than a 8% increase in total elapsed time for a set of standard benchmarks.
    <li><a href="http://www.eclipse.org/hyades/">Hyades<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - Hyades is an integrated test, trace and monitoring environment, based on Eclipse, that provides standards, tools and tool interoperability across the test process.
    <li><a href="http://www.experimentalstuff.com/Technologies/GCspy/">GCSpy <img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a>- The Garbage Collector Spy Tool, or GCspy for short, is a generic and highly-adaptable heap visualisation framework, designed to visualise a wide range of memory management systems, whether they depend on garbage collection or implement explicit de-allocation.
    <li><a href="http://www.virtualmachine.de/">heapprofile<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - A zero-overhead JVMPI plugin for finding first indications of memory leaks in production environments. Where commercial tools kill the performance of your application by collecting uninteresting performance data (such as 'who allocated this object'), this plugin stays inactive during runtime and simply dumps a very simple image of the Java heap on request.
    <li><a href="http://www.sable.mcgill.ca/~bdufou1/AdaptJ/main.html">AdaptJ<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - The AdaptJ Agent allows to collect event trace data from a Java program running in a Java Virtual Machine. The AdaptJ Analysis Tool allows to read and analyze the traces generated by the agent, using either the built-in analyses or custom ones.
    <li><a href="http://jcoverage.sourceforge.net/">JavaTreeProfiler<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - JVMPI based visualization using a TreeMap.
    <li><a href="http://besee.sourceforge.net/index.html">beeSee 2<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - beSee 2 provides a mechanism to plug a class preprocessor instrumentation layer in any classloader hierarchy, thus supporting java 1.3, 1.4, J2SE and J2EE environment. beSee 2 is the ground 0 lightweight layer of the next generation AOP architecture. It provides a bytecode kit independant solution and comes ready to use with two implementation: BCEL and Javassist.
    <li><a href="http://www.lambdacs.com/debugger/debugger.html">Omniscient Debugging<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - The debugger works by collecting "time stamps" which record everything that happens in a program. A GUI then allows you to navigate backwards in time to look at objects, variables, method calls, etc. Although focused on debugging, technique may be applicable for Profilers.
    <li><a href="http://developers.sun.com/dev/coolstuff/hotswap/">HotSwap Client Tool<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - This is a GUI client tool that provides access to the HotSwap functionality. Using this tool, you can dramatically improve the time of the usual "test - find a bug - stop the program - change - recompile - restart the program" development cycle by removing the "stop" and "restart" elements from it. Furthermore, you can use it to patch "on-the-fly" deployed applications that need to run uninterrupted.
    <li><a href="http://www.sable.mcgill.ca/step/">STEP<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - Extsnible Program Trace Encoding. STEP providins a standard method for encoding general program trace data in a flexible and compact format. The system consists of a trace data definition language along with a compiler for the language and an encoding architecture that implements a number of common trace reduction techniques. The system simplifies the development and interoperability of trace clients by encapsulating the encoding process and presenting the data as an abstract object stream.
    <li><a href="http://appstats.sourceforge.net/">AppStats <img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a>- AppStats is a lightweight, open source framework developed and used by Grand Central Communications, Inc. to capture, analyze, and publicize health, performance, and monitoring statistics for Java applications.
    <li><a href="http://www.p6spy.com/index.html">P6Spy<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - P6Spy is an open source framework for applications that intercept and optionally modify database statements. P6Log intercepts and logs the database statements of any application that uses JDBC. P6Outage detects long-running statements that may be indicative of a database outage proble and will log any statement that surpasses the configurable time boundary during its execution. P6Outage was designed to minimize any logging performance penalty by logging only long running statements.
    <li><a href="http://profiler.netbeans.org/index.html">NetBeans Profiler<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - NetBeans Profiler is a project to integrate the JFluid profiling technoglogy, which is being developed by Sun, into the NetBeans IDE. The JFluid technology addresses this issue by providing a mechanism in the JVM(tm), which allows the user to turn profiling on and off at any time, and, equally important, to profile just a small subset of the code, that they are currently interested in. The profiled subset of the code and the type of profiling (CPU, memory, etc.) can be changed at any moment at run time. This is achieved mainly through dynamic bytecode instrumentation. Features include low overhead profiling, attaching to running applications, CPU Performance profiling, memory profiling, memory leak debugging and task-based profiling.
    <li><a href="http://fprofiler.sourceforge.net/">FProfiler<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - FProfiler is a Java Profiler using BCEL and log4j. Its very fast because it inserts the needed instructions into the Bytecode of the classes. It can be used to find Hotspots in Java programs, libs and servlet environments simply every Java class.
    <li><span class="link-https"><a href="https://hat.dev.java.net/">Heap Analysis Tool(HAT)</a></span> - The Heap Analysis Tool (HAT) helps to debug unnecessary object retention (sometimes called "memory leaks") by providing a convenient means to browse the object topology in a heap snapshot, which is generated by the Java VM. HAT reads a hprof file, then sets itself up as a web server--therefore allowing you to run queries against a heap dump contained within the hprof file.
    <li><a href="http://infrared.sourceforge.net/">InfraRED<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - InfraRED is a tool for monitoring performance of a J2EE application and diagnosing performance problems. It collects metrics about various aspects of an application&#8217;s performance and makes it available for quantitative analysis of the application. InfraRED uses AOP to weave the performance monitoring code into the application.
    <li><span class="link-https"><a href="https://glassbox-inspector.dev.java.net/">Glassbox Inspector</a></span> - The Glassbox Inspector project combines AspectJ and JMX for a flexible, modular approach to monitoring performance for enterprise systems. It provides correlated information to allow you to identify specific problems, but with low enough overhead to be used in production environments. It lets you capture statistics such as total counts, total time, and worst-case performance for requests, and will also let let you drill down into that information for database calls within a request.
    <li><a href="http://jiprof.sourceforge.net/">JIP<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - JIP is a code profiling tool much like the hprof tool that ships with the JDK. JIP allows you to turn the profiler on and off while the JVM is running. JIP is pure Java. It takes advantage of the Java5&#8482; feature which allows you to hook the classloader. When the profiler is turned off, there is almost no overhead associated with using JIP. JIP allows real world timings for every class in your code.
    <li><a href="http://www.mcs.vuw.ac.nz/~djp/djprof/">DJProf<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -1058px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/silver/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" alt="" src="http://i.ixnp.com/images/v3.30/t.gif" /></a> - DJProf is an experimental Java profiling tool which employs AspectJ to insert the necessary instrumentation for profiling rather than, for example, the Java Machine Profiler Interface (JVMPI). DJProf can be used to profile Java programs without modification (i.e. there is no need to recompile them for profiling) and does not require the user to have any knowledge of AspectJ. The Load-Time Weaving capability of AspectJ is utilised to make this possible. It supports several different modes of profiling such as heap usage, object lifetime, wasted time and time spent. </li>
</ul>
</blockquote>
<img src ="http://www.blogjava.net/midstr/aggbug/202202.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-05-22 16:36 <a href="http://www.blogjava.net/midstr/archive/2008/05/22/202202.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>增加静态方法要重启tomcat？</title><link>http://www.blogjava.net/midstr/archive/2008/04/21/194488.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Mon, 21 Apr 2008 04:54:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/04/21/194488.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/194488.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/04/21/194488.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/194488.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/194488.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在开发过程中，给 <font style="background-color: #cce8cf">com.thunisoft.fy.business.sp.SelectListUtils 新增加了一个public static方法 <font style="background-color: #cce8cf">getTestSelectList()。在页面的处理的logic类里面使用的时候代码提示都可以提示出来，调用方法也没有报编译期错误。刷新界面后，后台运行到刚才调用的地方就报如下错误：</font></font><br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">2008</span><span style="color: #000000">-</span><span style="color: #000000">04</span><span style="color: #000000">-</span><span style="color: #000000">21</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">12</span><span style="color: #000000">:</span><span style="color: #000000">30</span><span style="color: #000000">:</span><span style="color: #000000">27</span><span style="color: #000000">,</span><span style="color: #000000">032</span><span style="color: #000000">&nbsp;[com.thunisoft.summer.web.action.BaseAction]</span><span style="color: #000000">-</span><span style="color: #000000">[ERROR]&nbsp;runtime&nbsp;exception<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />java.lang.NoSuchMethodError:&nbsp;com.thunisoft.fy.business.sp.SelectListUtils.getTestSelectList()Lcom</span><span style="color: #000000">/</span><span style="color: #000000">thunisoft</span><span style="color: #000000">/</span><span style="color: #000000">fy</span><span style="color: #000000">/</span><span style="color: #000000">support</span><span style="color: #000000">/</span><span style="color: #000000">selectObj</span><span style="color: #000000">/</span><span style="color: #000000">SelectList;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;com.thunisoft.fy.spxt.pub.ajxq.AjxqLogic.displayZxAjxq_right(AjxqLogic.java:</span><span style="color: #000000">736</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;com.thunisoft.fy.spxt.pub.ajxq.AjxqLogic.displayAjxq_right(AjxqLogic.java:</span><span style="color: #000000">116</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;sun.reflect.NativeMethodAccessorImpl.invoke0(Native&nbsp;Method)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:</span><span style="color: #000000">39</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:</span><span style="color: #000000">25</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.lang.reflect.Method.invoke(Method.java:</span><span style="color: #000000">324</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;com.thunisoft.summer.web.action.MemoryAction.execute(MemoryAction.java:</span><span style="color: #000000">102</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.springframework.web.struts.DelegatingActionProxy.execute(DelegatingActionProxy.java:</span><span style="color: #000000">106</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:</span><span style="color: #000000">430</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;com.thunisoft.fy.web.struts.SummerRequestProcessor.process(SummerRequestProcessor.java:</span><span style="color: #000000">134</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.struts.action.ActionServlet.process(ActionServlet.java:</span><span style="color: #000000">1196</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:</span><span style="color: #000000">414</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;javax.servlet.http.HttpServlet.service(HttpServlet.java:</span><span style="color: #000000">689</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;javax.servlet.http.HttpServlet.service(HttpServlet.java:</span><span style="color: #000000">802</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:</span><span style="color: #000000">237</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:</span><span style="color: #000000">157</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;com.thunisoft.summer.web.filter.UserAASFilter.doFilter(UserAASFilter.java:</span><span style="color: #000000">111</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:</span><span style="color: #000000">186</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:</span><span style="color: #000000">157</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.ajaxanywhere.AAFilter.doFilter(AAFilter.java:</span><span style="color: #000000">46</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:</span><span style="color: #000000">186</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:</span><span style="color: #000000">157</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;com.thunisoft.summer.web.filter.CharsetFilter.doFilter(CharsetFilter.java:</span><span style="color: #000000">48</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:</span><span style="color: #000000">186</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:</span><span style="color: #000000">157</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:</span><span style="color: #000000">214</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:</span><span style="color: #000000">104</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:</span><span style="color: #000000">520</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:</span><span style="color: #000000">198</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:</span><span style="color: #000000">152</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:</span><span style="color: #000000">104</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:</span><span style="color: #000000">520</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:</span><span style="color: #000000">137</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:</span><span style="color: #000000">104</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:</span><span style="color: #000000">118</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:</span><span style="color: #000000">102</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:</span><span style="color: #000000">520</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:</span><span style="color: #000000">109</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:</span><span style="color: #000000">104</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:</span><span style="color: #000000">520</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:</span><span style="color: #000000">929</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:</span><span style="color: #000000">160</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:</span><span style="color: #000000">799</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:</span><span style="color: #000000">705</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:</span><span style="color: #000000">577</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:</span><span style="color: #000000">683</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;at&nbsp;java.lang.Thread.run(Thread.java:</span><span style="color: #000000">534</span><span style="color: #000000">)<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
&nbsp;&nbsp;&nbsp;&nbsp; 咨询同事，得到的是&#8220;增加静态方法&#8221;要重启tomcat服务。我重启了tomcat果然就没有问题了：）<br />
&nbsp;&nbsp;&nbsp;&nbsp; 有点不太明白，为什么增加静态方法就要重启tomcat服务？这样在开发过程中如果经常增加static方法岂不是每次都要重启，然后就会很浪费时间了。另外，为什么如果我只是修改了原来已经存在的static方法的实现，则可以正常调试。
<img src ="http://www.blogjava.net/midstr/aggbug/194488.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-04-21 12:54 <a href="http://www.blogjava.net/midstr/archive/2008/04/21/194488.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>开发中常用的几个eclipse插件</title><link>http://www.blogjava.net/midstr/archive/2008/03/16/186592.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Sun, 16 Mar 2008 04:20:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2008/03/16/186592.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/186592.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2008/03/16/186592.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/186592.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/186592.html</trackback:ping><description><![CDATA[<ol>
    <li><font style="background-color: #cce8cf">Myeclipse 主要用于eclipse的web开发，虽然它不是免费的，但我们一直在免费使用，因为网上的注册码太多了。</font>
    <li><font style="background-color: #cce8cf">Fatjar 一个易用的打包工具，会将编译用到的所有资源进行打包。如果是web项目打包，还是用myeclispe的export-&gt;WAR（EAR）</font>
    <li><font style="background-color: #cce8cf">Jode 反编译功能很好用。</font>
    <li>Hibernate Sychronizer（HibernateTools） 据说很好用。
    <li>JSEclipse（A<font style="background-color: #cce8cf">ptana</font>） 效果正在试用中。
    <li><font style="background-color: #cce8cf">PropertiesEditor</font> 属性文件编辑器&nbsp; <font style="background-color: #cce8cf"><a href="http://propedit.sourceforge.jp/eclipse/updates/">http://propedit.sourceforge.jp/eclipse/updates/</a></font>
    <li>SpringIDE&nbsp;&nbsp;&nbsp; <font style="background-color: #cce8cf"><a href="http://springide.org">http://springide.org</a></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://springide.org/updatesite/">http://springide.org/updatesite/</a>
    <li>EclEmma 最近才开始了解。</li>
</ol>
<img src ="http://www.blogjava.net/midstr/aggbug/186592.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2008-03-16 12:20 <a href="http://www.blogjava.net/midstr/archive/2008/03/16/186592.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java容器类分析zz</title><link>http://www.blogjava.net/midstr/archive/2007/08/14/136770.html</link><dc:creator>岁月如歌</dc:creator><author>岁月如歌</author><pubDate>Tue, 14 Aug 2007 11:56:00 GMT</pubDate><guid>http://www.blogjava.net/midstr/archive/2007/08/14/136770.html</guid><wfw:comment>http://www.blogjava.net/midstr/comments/136770.html</wfw:comment><comments>http://www.blogjava.net/midstr/archive/2007/08/14/136770.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/midstr/comments/commentRss/136770.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/midstr/services/trackbacks/136770.html</trackback:ping><description><![CDATA[<h2>Java容器类分析－数组（转载）</h2>
<div class=t_msgfont id=postmessage_2891>数组是Java语言内置的类型，除此之外，Java有多种保存对象引用的方式。Java类库提供了一套相当完整的容器类，使用这些类的方法可以保存和操纵对象。下面分别进行讨论，在研究Java容器类之前，先了解一下Java数组的基本功能和<span class=t_tag onclick=tagshow(event) href="tag.php?name=%CC%D8%D0%D4">特性</span>。<br><br>1.&nbsp;&nbsp;数组的基本特性<br><br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;数组与其它种类的容器(List/Set/Map)之间的区别在于效率、确定的类型和保存基本类型<span class=t_tag onclick=tagshow(event) href="tag.php?name=%CA%FD%BE%DD">数据</span>的能力。数组是一种高效的存储和随机访问对象引用序列的方式，使用数组可以快速的访问数组中的元素。但是当创建一个数组对象(注意和对象数组的区别)后，数组的大小也就固定了，当数组空间不足的时候就再创建一个新的数组，把旧的数组中所有的引用<span class=t_tag onclick=tagshow(event) href="tag.php?name=%B8%B4%D6%C6">复制</span>到新的数组中。<br><br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;Java中的数组和容器都需要进行边界检查，如果越界就会得到一个RuntimeException异常。这点和C++中有所不同，C++中vector的操作符[]不会做边界检查，这在速度上会有一定的提高，Java的数组和容器会因为时刻存在的边界检查带来一些<span class=t_tag onclick=tagshow(event) href="tag.php?name=%D0%D4%C4%DC">性能</span>上的开销。<br><br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;Java中通用的容器类不会以具体的类型来处理对象，容器中的对象都是以Object类型处理的，这是Java中所有类的基类。另外，数组可以保存基本类型，而容器不能，它只能保存任意的Java对象。<br><br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;一般情况下，考虑到效率与类型检查，应该尽可能考虑使用数组。如果要解决一般化的问题，数组可能会受到一些限制，这时可以使用Java提供的容器类。 <br><br>2.&nbsp;&nbsp;操作数组的实用功能<br><br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;在java.util.Arrays类中，有许多static静态方法，提供了操作数组的一些基本功能：<br><br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;equals()方法----用于比较两个数组是否相等，相等的条件是两个数组的元素个数必须相等，并且对应位置的元素也相等。<br><br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;fill()方法----用以某个值填充整个数组，这个方法有点笨。<br><br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;asList()方法----接受任意的数组为<span class=t_tag onclick=tagshow(event) href="tag.php?name=%B2%CE%CA%FD">参数</span>，将其转变为List容器。<br><br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;binarySearch()方法----用于在已经排序的数组中查找元素，需要注意的是必须是已经排序过的数组。当Arrays.binarySearch()找到了查找目标时，该方法将返回一个等于或大于0的值，否则将返回一个负值，表示在该数组目前的排序状态下此目标元素所应该插入的位置。负值的计算公式是&#8220;-x-1&#8221;。x指的是第一个大于查找对象的元素在数组中的位置，如果数组中所有的元素都小于要查找的对象，则x = a.size()。如果数组中包含重复的元素，则无法保证找到的是哪一个元素，如果需要对没有重复元素的数组排序，可以使用TreeSet或者LinkedHashSet。另外，如果使用Comparator排序了某个对象数组，在使用该方法时必须提供同样的Comparator类型的参数。需要注意的是，基本类型数组无法使用Comparator进行排序。<br><br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;sort()方法----对数组进行升序排序。<br><br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;在Java标准类库中，另有static方法System.arraycopy()用来复制数组，它针对所有类型做了重载。<br><br><br>3.&nbsp;&nbsp;数组的排序<br><br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;在Java1.0和1.1两个版本中，类库缺少基本的算法操作，包括排序的操作，Java2对此进行了改善。在进行排序的操作时，需要根据对象的实际类型执行比较操作，如果为每种不同的类型各自编写一个不同的排序方法，将会使得<span class=t_tag onclick=tagshow(event) href="tag.php?name=%B4%FA%C2%EB">代码</span>很难被复用。一般的程序<span class=t_tag onclick=tagshow(event) href="tag.php?name=%C9%E8%BC%C6">设计</span>目标应是&#8220;将保持不变的事物与会发改变的事物相分离&#8221;。在这里，不变的是通用的排序算法，变化的是各种对象相互比较的方式。<br><br>Java有两种方式来实现比较的功能，一种是实现java.lang.Comparable接口，该接口只有一个compareTo()方法，并以一个Object类为参数，如果当前对象小于参数则返回负值，如果相等返回零，如果当前对象大于参数则返回正值。另一种比较方法是采用策略(strategy)设计模式，将会发生变化的代码封装在它自己的类(策略对象)中，再将策略对象交给保持不变的代码中，后者使用此策略实现它的算法。因此，可以为不同的比较方式生成不同的对象，将它们用在同样的排序程序中。在此情况下，通过定义一个实现了Comparator接口的类而创建了一个策略，这个策略类有compare()和equals()两个方法，一般情况下实现compare()方法即可。<br><br>使用上述两种方法即可对任意基本类型的数组进行排序，也可以对任意的对象数组进行排序。再提示一遍，基本类型数组无法使用Comparator进行排序。<br><br>Java标准类库中的排序算法针对排序的类型进行了优化——针对基本类型设计了&#8220;快速排序&#8221;，针对对象设计的&#8220;稳定归并排序&#8221;。一般不用担心其性能。<br><br>
<h2>Java容器分析--List和Set</h2>
<div class=t_msgfont id=postmessage_2892>容器类可以大大提高编程效率和编程能力，在Java2中，所有的容器都由SUN公司的Joshua Bloch进行了重新设计，丰富了容器类库的功能。<br><br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;Java2容器类类库的用途是&#8220;保存对象&#8221;，它分为两类：<br><br>Collection----一组独立的元素，通常这些元素都服从某种规则。List必须保持元素特定的顺序，而Set不能有重复元素。<br><br>Map----一组成对的&#8220;键值对&#8221;对象，即其元素是成对的对象，最典型的应用就是数据字典，并且还有其它广泛的应用。另外，Map可以返回其所有键组成的Set和其所有值组成的Collection，或其键值对组成的Set，并且还可以像数组一样扩展多维Map，只要让Map中键值对的每个&#8220;值&#8221;是一个Map即可。<br><br>1.迭代器<br><br>&nbsp; &nbsp;&nbsp; &nbsp; 迭代器是一种设计模式，它是一个对象，它可以遍历并选择序列中的对象，而开发人员不需要了解该序列的底层结构。迭代器通常被称为&#8220;轻量级&#8221;对象，因为创建它的代价小。<br><br>&nbsp; &nbsp;&nbsp; &nbsp; Java中的Iterator功能比较简单，并且只能单向移动：<br><br>(1)&nbsp; &nbsp; 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时，它返回序列的第一个元素。<br><br>(2)&nbsp; &nbsp; 使用next()获得序列中的下一个元素。<br><br>(3)&nbsp; &nbsp; 使用hasNext()检查序列中是否还有元素。<br><br>(4)&nbsp; &nbsp; 使用remove()将迭代器新返回的元素删除。<br><br>Iterator是Java迭代器最简单的实现，为List设计的ListIterator具有更多的功能，它可以从两个方向遍历List，也可以从List中插入和删除元素。<br><br>2.List的功能方法<br><br>List(interface): 次序是List最重要的特点；它确保维护元素特定的顺序。List为Collection添加了许多方法，使得能够向List中间插入与移除元素(只推荐LinkedList使用)。一个List可以生成ListIterator，使用它可以从两个方向遍历List，也可以从List中间插入和删除元素。<br><br>ArrayList: 由数组实现的List。它允许对元素进行快速随机访问，但是向List中间插入与移除元素的速度很慢。ListIterator只应该用来由后向前遍历ArrayList，而不是用来插入和删除元素，因为这比LinkedList开销要大很多。<br><br>LinkedList: 对顺序访问进行了优化，向List中间插入与删除得开销不大，随机访问则相对较慢(可用ArrayList代替)。它具有方法addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast()，这些方法(没有在任何接口或基类中定义过)使得LinkedList可以当作堆栈、队列和双向队列使用。<br><br>3.Set的功能方法<br><br>Set(interface): 存入Set的每个元素必须是唯一的，因为Set不保存重复元素。加入Set的Object必须定义equals()方法以确保对象的唯一性。Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。<br><br>HashSet: 为快速查找而设计的Set。存入HashSet的对象必须定义hashCode()。<br><br>TreeSet: 保持次序的Set，底层为树结构。使用它可以从Set中提取有序的序列。<br><br>LinkedHashSet: 具有HashSet的查询速度，且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时，结果会按元素插入的次序显示。<br><br>&nbsp; &nbsp;&nbsp; &nbsp; HashSet采用散列函数对元素进行排序，这是专门为快速查询而设计的；TreeSet采用红黑树的数据结构进行排序元素；LinkedHashSet内部使用散列以加快查询速度，同时使用链表维护元素的次序，使得看起来元素是以插入的顺序保存的。需要注意的是，生成自己的类时，Set需要维护元素的存储顺序，因此要实现Comparable接口并定义compareTo()方法。</div>
<br><br><br>
<h2>Java容器分析--Map</h2>
<div class=t_msgfont id=postmessage_2893>标准的Java类库中包含了几种类型的Map，它们都拥有同样的基本接口Map，但是行为特性各不相同，主要表现在效率、键值对的保存、元素呈现次序、对象的保存周期和判定键是否等价的策略等方面。<br><br>1.Map的功能方法<br><br>Map(interface): 维护label和value的关联性，使得可以通过label查找value。<br><br>HashMap: Map基于散列表的实现，取代了Hashtable。插入和查询label/value的开销是固定的，并且可以通过构造器设置容量和负载因子，以调整容器的性能。<br><br>LinkedHashMap: 在HashMap的基础上做了一些改进，在迭代遍历它时，取得label/value的顺序是其插入的次序，或者是最近最少使用(LRU)的次序，速度上比HashMap要慢一点，但在迭代访问时速度会更快，主要原因是它使用了链表维护内部次序。<br><br>TreeMap: 查看label或label/value时，元素会被排序，其次序由Comparable或Comparator决定，因此查询所得到的结果是经过排序的。另外，它是唯一带有subMap()方法的Map具体类，即返回一个子树。它也是SortedMap接口的唯一实现，subMap()方法也是从该接口继承的。<br><br>WeakHashMap: Weak Key映射，允许释放映射所指向的对象。当映射之外没有引用指向某个label时，此label可以被垃圾收集器回收。<br><br>IdentityHashMap: 使用==代替equals()对label进行比较的散列映射。<br><br>2.hashCode()<br><br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;当使用标准库中的类Integer作为HashMap的label时，程序能够正常运行，但是使用自己创建的类作为HashMap的label时，通常犯一个错误。<br><br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;在HashMap中通过label查找value时，实际上是计算label对象地址的散列码来确定value的。一般情况下，我们是使用基类Object的方法hashCode()来生成散列码，它默认是使用对象的地址来计算的，因此由第一个对象new Apple(5)和第二个对象new Apple(5)生成的散列码是不同的，不能完成正确的查找。通常，我们可以编写自己的hashCode()方法来覆盖基类的原始方法，但与此同时，我们必须同时实现equals()方法来判断当前的label是否与表中存在的label相同。正确的equals()方法满足五个条件：<br><br>(1)&nbsp; &nbsp;&nbsp;&nbsp;自反性。对于任意的x，x.equals(x)一定返回true。<br><br>(2)&nbsp; &nbsp;&nbsp;&nbsp;对称性。对于任意的x和y，如果y.equals(x)返回true，则x.equals(y)也返回true。<br><br>(3)&nbsp; &nbsp;&nbsp;&nbsp;传递性。对于任意的x、y、z，如果有x.equals(y)返回true，y.equals(z)返回true，则x.equals(z)一定返回true。<br><br>(4)&nbsp; &nbsp;&nbsp;&nbsp;一致性。对于任意的x和y，如果对象中用于等价比较的信息没有改变，那么无论调用x.equals(y)多少次，返回的结果应该保持一致，要么一直是true，要么一直是false。<br><br>(5)&nbsp; &nbsp;&nbsp;&nbsp;对任何不是null的x，x.equals(null)一定返回false。<br><br>equals()比较的是对象的地址，如果要使用自己的类作为HashMap的label，必须同时重载hashCode()和equals()方法。<br><br>使用散列的目的：想要使用一个对象来查找另一个对象。使用TreeSet或TreeMap也能实现此目的。另外，还可以自己实现一个Map，此时，必须提供Map.entrySet()方法来生成Map.Entry对象的Set。<br><br>使用散列的价值：速度，散列使得查询可以快速进行。散列将label保存载数组中方便快速查询，因为存储一组元素最快的数据结构是数组，用它来表示label的信息(后面有信息的描述)，而不是label本身。通过label对象计算得到一个数字，作为数组的下标，这个数字就是散列码(即前面所述的信息)。该散列码具体是通过定义在基类Object中，可能由程序员自定义的类覆盖的hashCode()方法，即散列函数生成。为了解决数组容量带来的限制，可以使不同的label生成相同的下标，保存在一个链表list中，每一个链表就是数组的一个元素。查询label时就可以通过对list中的信息进行查找，当散列函数比较好，数组的每个位置中的list长度较短，则可以快速查找到数组元素list中的某个位置，提高了整体速度。<br><br>散列表中的slot通常称为bucket，为了使散列分步均匀，bucket的值一般取质数。但事实证明，质数实际上并不是散列bucket的理想容量，近来Java散列实现都使用2的幂，具体如何验证以后再续。<br><br>3.HashMap的性能因子<br><br>容量(capacity): 散列表中bucket的数量。<br><br>初始化容量(initial capacity): 创建散列表时bucket的数量。可以在构造方法中指定HashMap和HashSet的初始化容量。<br><br>尺寸(size): 散列表中记录的数量。(数组的元素个数，非list中元素总和)<br><br>负载因子(load factor): 尺寸/容量。负载因子为0，表示空的散列表，0.5表示半满的散列表。轻负载的散列表具有冲突少，适宜插入与查询的特点，但是使用迭代器遍历会比较慢。较高的负载会减少所需空间大小。当负载达到指定值时，容器会自动成倍地增加容量，并将原有的对象重新分配，存入新的bucket中，这个过程称为&#8220;重散列&#8221;。<br><br>4.重写hashCode()的关键<br><br>(1)&nbsp; &nbsp;&nbsp;&nbsp;对同一个对象调用hashCode()都应该生成同样的值。<br><br>(2)&nbsp; &nbsp;&nbsp;&nbsp;hashCode()方法不要依赖于对象中易变的数据，当数据发生变化时，hashCode()就会生成一个不同的散列码，即产生了一个不同的label。<br><br>(3)&nbsp; &nbsp;&nbsp;&nbsp;hashCode()不应依赖于具有唯一性的对象信息，例如对象地址。<br><br>(4)&nbsp; &nbsp;&nbsp;&nbsp;散列码应该更关心速度，而不是唯一性，因为散列码不必是唯一的。<br><br>(5)&nbsp; &nbsp;&nbsp;&nbsp;好的hashCode()应该产生分步均匀的散列码。在Effective Java(Addison-Wesley 2001)中，Joshua Bloch给hashCode()给出了设计指导，可以参考。<br><br>编写正确高效的hashCode()和equals()可以参考Apache的Jakarta Commons项目中的工具。</div>
<br></div><img src ="http://www.blogjava.net/midstr/aggbug/136770.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/midstr/" target="_blank">岁月如歌</a> 2007-08-14 19:56 <a href="http://www.blogjava.net/midstr/archive/2007/08/14/136770.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>