﻿<?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-惨淡人生，平淡生活</title><link>http://www.blogjava.net/jackjhy/</link><description>The Feature Is Stupid</description><language>zh-cn</language><lastBuildDate>Wed, 08 Apr 2026 21:02:11 GMT</lastBuildDate><pubDate>Wed, 08 Apr 2026 21:02:11 GMT</pubDate><ttl>60</ttl><item><title>实现web服务的三个误区 读后感</title><link>http://www.blogjava.net/jackjhy/archive/2009/03/16/260022.html</link><dc:creator>季失羽</dc:creator><author>季失羽</author><pubDate>Mon, 16 Mar 2009 06:55:00 GMT</pubDate><guid>http://www.blogjava.net/jackjhy/archive/2009/03/16/260022.html</guid><wfw:comment>http://www.blogjava.net/jackjhy/comments/260022.html</wfw:comment><comments>http://www.blogjava.net/jackjhy/archive/2009/03/16/260022.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackjhy/comments/commentRss/260022.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackjhy/services/trackbacks/260022.html</trackback:ping><description><![CDATA[<p><strong></strong></p>
<p><strong>我的消息吃了我的服务器！</strong>Kyle指出，通常，Web服务开发者开始经历&#8220;内存溢出&#8221;的错误或者奇怪的&#8220;性能问题&#8221;时，总是会发现服
务器拥有极高的处理负载，CPU使用率接近100%，以及较低的吞吐量和高网络延迟。导致这些症状的典型原因是非常大的（有时会达到50
MB或者更大）消息。而且，这些大消息往往包含了非常大的、作为XML消息主体的、采用base-64编码的二进制编码信息。导致其发生的原因通常是：</p>
<blockquote> &#8230;&#8230;开发者不理解技术的局限性：XML处理对解决许多问题都有用，但是你必须认识到消息是要被解析的——并且在大多数&#8230;&#8230;产品中，这就意味着许多或者所有的消息都会驻留在内存中。</blockquote>
<p>Kyle建议采用如下方法来改善这种情况：</p>
<blockquote>
<ul>
    <li>不要发送冗余信息。在许多情况下，发送二进制数据时，你可能会发现消息高度重复。如果是这样，你可能就要考虑在HTTP层面使用压缩技术来改善你的网络延迟。虽然这不会帮助你处理负载，但可能有助于减轻其中一个问题。</li>
    <li>在XML消息体中，根本不要嵌入二进制信息。这是较好的解决方法，还有几种不同的途径可以实现这一效果。比如，你可以使用带有附件的SOAP或者消息传输优化机制（MTOM）绕过解析开销，尽管这无助于网络延迟问题。</li>
    <li>&#8230;&#8230;还有一个更好的办法，使用SOAP根本不发送大的二进制blob。替代方法，通过受控的文件传输系统，使用一个&#8220;带外数据&#8221;传输&#8230;&#8230;或者&#8220;声明标签（claim Check，参见《EIP模式》或<a href="http://www.enterpriseintegrationpatterns.com/StoreInLibrary.html">这里</a>）&#8221;模式，避免在SOAP和HTTP上发送大的二进制文件。</li>
</ul>
<br />
<br />
<br />
<br />
<span style="color: #2708ff;">任何一种技术都有它使用的环境，在做架构设计的时候一定要避免因为个人的偏好，无意识的舍弃某些选择。 一种简单的方法论是，根据需要达到的目的，列出所有可能的实现方案，最后做出决定。</span><br />
<br />
<br />
<p><strong>不好意思，你的数据正在显示。</strong>根据Kyle所说，另一个典型的Web服务的&#8220;性能问题&#8221; 是，使用Web服务的层面非常、非常低——通常Web服务跟一个SQL语句相关，这是因为：</p>
<blockquote>误解了SOA架构原则。一个优秀SOA架构的关键原则是你的服务应该具有高复用性。</blockquote>
<p>根据Kyle所说，这些情况通常发生在：</p>
<blockquote>
<p>&#8230;&#8230;如果设计是根据现有代码&#8220;自上而下&#8221;衍生出服务，这类服务就会出现；通常，开发者会看着他们现有的架构图并且决定将架构中的每一层（包括表现层）转变成服务集。</p>
<p>相反，在SOA架构的正确位置使用粗粒度的Web服务会更好。再次强调，检查一个架构的标准分层模型，通常在架构中会有一个明确定义的地方已经封装
了系统业务逻辑。可以使用&#8220;远程门面模式（Remote Facade Pattern）&#8221;来包装这些服务，以便用合适的方式来暴露基于模型的服务。</p>
<p><br />
</p>
<p><br />
</p>
</blockquote><span style="color: #2708ff;">同样是可以利用方法论来避免问题，但对于粒度的把握就是一个经验的问题。</span><br />
<br />
<br />
<br />
<br />
<p><strong>模式（Schema）？我们不需要任何发臭的模式！</strong>
Kyle指出，通常开发者试图重用现有代码来生成和解析作为Web服务实现基础的XML。这些实现通常使用XML解析器来编组/解组消息，同时使用
Java
HTTP类来发送和接收XML文档。使用Web服务时，通用的方法是，创建使用模式元素的WSDL文档，使XML不受阻地通过，然后在现有代码中对它们进
行解析。</p>
<blockquote>这个问题的症状是组织没有看到SOA承诺的好处，而且维护他们的解决方案似乎比以前使用Web服务的时候更难（而不是更容易）</blockquote>
<p>简单的解决方案是，每当写Web服务时，不管使用WS-*标准还是使用REST方法，都要确保你创建了代表你文档结构的完整准确的XML模式。</p>
<blockquote>如果你正在构建WS-* Web服务，那么这个XML应该被包含在描述你的Web服务的WSDL之中。即使你在使用REST方法，拥有易于访问的XML模式将鼓励你的服务被重用。</blockquote><br />
<br />
<br />
</blockquote>
<blockquote>
<ul>
    <li><br />
    </li>
</ul>
<br />
<br />
</blockquote>

<img src ="http://www.blogjava.net/jackjhy/aggbug/260022.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackjhy/" target="_blank">季失羽</a> 2009-03-16 14:55 <a href="http://www.blogjava.net/jackjhy/archive/2009/03/16/260022.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何看懂Java混淆后的反编译代码(转)</title><link>http://www.blogjava.net/jackjhy/archive/2009/03/03/257477.html</link><dc:creator>季失羽</dc:creator><author>季失羽</author><pubDate>Tue, 03 Mar 2009 01:59:00 GMT</pubDate><guid>http://www.blogjava.net/jackjhy/archive/2009/03/03/257477.html</guid><wfw:comment>http://www.blogjava.net/jackjhy/comments/257477.html</wfw:comment><comments>http://www.blogjava.net/jackjhy/archive/2009/03/03/257477.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackjhy/comments/commentRss/257477.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackjhy/services/trackbacks/257477.html</trackback:ping><description><![CDATA[<p><strong><font size="4">如何看懂Java混淆后的反编译代码</font></strong></p>
<p>作者：dozb</p>
<p>一般情况下Java应用的开发者为了保护代码不被别人抄袭，在生成class文件的时候都java文件进行了混淆，这种class文件用反编译工具得到的结果很难看懂，并且不能进行编译。本文从研究的角度，浅析如何读懂这种反编译过来的文件。</p>
<p><strong><font color="#0000ff">例子一：赋值</font></strong><br />
反编译过来的代码如下：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Node node;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Node node1 = _$3.getChildNodes().item(0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; node1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; node1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JVM INSTR swap ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; node;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getChildNodes();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; item();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getChildNodes();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; item();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getNodeValue();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String s;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s;<br />
原始语句：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Node node;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Node node1 = currDocument.getChildNodes().item(0);<br />
&nbsp;node = node1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String s = node.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();<br />
注解：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JVM INSTR swap ; //赋值语句<br />
练习：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String s1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String s8 = node.getChildNodes().item(1).getChildNodes().item(0).getNodeValue();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s8;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s8;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JVM INSTR swap ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Integer.parseInt();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i;</p>
<p>&nbsp;&nbsp;&nbsp;<br />
<strong><font color="#0000ff">例子二：不带参数创建对象</font></strong><br />
反编译过来的代码如下：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JVM INSTR new #244 &lt;Class CrossTable&gt;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JVM INSTR dup ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JVM INSTR swap ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CrossTable();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CrossTable crosstable;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; crosstable;</p>
<p>原始语句：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CrossTable crosstable = new CrossTable();<br />
注解：<br />
练习：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JVM INSTR new #246 &lt;Class Database&gt;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JVM INSTR dup ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JVM INSTR swap ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Database();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object obj;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj;</p>
<p><strong><font color="#0000ff">例子三：带参数创建对象<br />
</font></strong>反编译过来的代码如下：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JVM INSTR new #262 &lt;Class StringBuffer&gt;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JVM INSTR dup ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JVM INSTR swap ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String.valueOf(s2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringBuffer();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s.substring(j, i);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; append();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s6;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; append();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; toString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s2;<br />
&nbsp;<br />
原始语句：<br />
&nbsp;s2 = (new StringBuffer(String.valueOf(s2))).append(s.substring(j, i)).append(s6).toString();<br />
注解：<br />
&nbsp;此语句实际上是：s2 += s.substring(j, i) + s6;<br />
练习：</p>
<p><font color="#0000ff"><strong>例子四：for循环</strong></font><br />
反编译过来的代码如下：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int k = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto _L4<br />
_L8:<br />
&nbsp;...<br />
&nbsp;k++;<br />
_L4:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(k &lt; as.length) goto _L8; else goto _L7</p>
<p>原始语句：<br />
&nbsp;for(int k=0;k &lt; as.length;k++)<br />
&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp; ...<br />
&nbsp;}<br />
注解：</p>
<p><strong><font color="#0000ff">例子五：while循环</font></strong><br />
反编译过来的代码如下：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String s1 = "";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto _L1<br />
_L3:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JVM INSTR new #262 &lt;Class StringBuffer&gt;;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JVM INSTR dup ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JVM INSTR swap ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String.valueOf(s1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringBuffer();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _$2(resultset, s, l);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; append();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; toString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s1;<br />
_L1:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(resultset.next()) goto _L3; else goto _L2</p>
<p>原始语句：<br />
&nbsp;String s1 = "";<br />
&nbsp;while(resultset.next())<br />
&nbsp;{<br />
&nbsp;&nbsp;s1 = s1 + resultSetToString(resultset, s, l);</p>
&nbsp;}
<img src ="http://www.blogjava.net/jackjhy/aggbug/257477.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackjhy/" target="_blank">季失羽</a> 2009-03-03 09:59 <a href="http://www.blogjava.net/jackjhy/archive/2009/03/03/257477.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[翻译]走出ClassLoader的迷宫</title><link>http://www.blogjava.net/jackjhy/archive/2008/05/30/204163.html</link><dc:creator>季失羽</dc:creator><author>季失羽</author><pubDate>Fri, 30 May 2008 10:22:00 GMT</pubDate><guid>http://www.blogjava.net/jackjhy/archive/2008/05/30/204163.html</guid><wfw:comment>http://www.blogjava.net/jackjhy/comments/204163.html</wfw:comment><comments>http://www.blogjava.net/jackjhy/archive/2008/05/30/204163.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jackjhy/comments/commentRss/204163.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackjhy/services/trackbacks/204163.html</trackback:ping><description><![CDATA[<p style="text-align: left;">[说明]几个关键字将不翻译</p>
<ol>
    <li>
    <div style="text-align: left;">ClassLoader</div>
    </li>
    <li>
    <div style="text-align: left;">System</div>
    </li>
    <li>
    <div style="text-align: left;">Context</div>
    </li>
    <li>
    <div style="text-align: left;">Thread</div>
    </li>
</ol>
<p style="text-align: center;">走出ClassLoader的迷宫</p>
<p style="text-align: left;"><em style="color: #0000ff;">&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; System、Current和Context ClassLoader？分别在何种情形下使用？</em></p>
<p><br />
</p>
<p style="text-align: left;"><strong>1、问题：在何种情形下使用<span onmouseover="_tipon(this)" onmouseout="_tipoff()"><code>thread.getcontextclassloader()?</code></span></strong></p>
<p style="text-align: left;"><span onmouseover="_tipon(this)" onmouseout="_tipoff()"><code>尽管没经常遇到这个问题，但是想获得准确的答案并不那么容易，特别是在开发应用框架的时候，你需要动态的加载一些类和资源，不可避免的你会被此困扰。一般来说，动态载入资源有三种ClassLoader可以选择，System ClassLoader（也叫App ClassLoader）、当前类的ClassLoader和CurrentThread的Context ClassLoader。那么， 如何选择使用？</code></span></p>
<p style="text-align: left;">首先可以简单排除的是System ClassLoader，这个ClassLoader负责从参数-classpath、-cp、和操作系统CLASSPATH中载入资源。并且，任何ClassLoader的getSystemXXX()方法都是有以上几个路径指定的。我们应该很少需要编写直接使用ClassLoader的程序，否则你的代码将只能在命令行运行，发布你的代码成为ejb、web应用或者java web start应用，我肯定他们会崩溃！</p>
<p style="text-align: left;">接下来，我们只剩下两个选择了：当前ClassLoader和Thread Context ClassLoader</p>
<p style="text-align: left;">Current ClassLoader：当前类所属的ClassLoader，在虚拟机中类之间引用，默认就是使用这个ClassLoader。另外，当你使用<span style="font-family: Courier New;">Class.forName()</span>, <code>Class.getResource()这几个不带ClassLoader参数的方法是，默认同样适用当前类的ClassLoader。你可以通过方法XX.class.GetClassLoader()获取。</code></p>
<p style="text-align: left;">Thread Context ClassLoader，没一个Thread有一个相关联系的Context ClassLoader（由native方法建立的除外），可以通过<span style="font-family: Courier New;">Thread.setContextClassLoader()方法设置。如果你没有主动设置，Thread默认集成Parent Thread的 Context ClassLoader（注意，是parent Thread 不是父类）。如果 你整个应用中都没有对此作任何处理，那么 所有的Thread都会以System ClassLoader作为Context ClassLoader。知道这一点很重要，因为从web服务器，java企业服务器使用一些复杂而且精巧的ClassLoader结构去实现诸如JNDI、线程池和热部署等功能以来，这种简单的情况越发的少见了。</span></p>
<p><span style="font-family: Courier New;">这篇文章中为什么把Thread Context ClassLoader放在首要的位置，别人并没有大张旗鼓的介绍它?很多开发者都对此不甚了解，因为sun没有提供很好的说明文档。</span></p>
<p><span style="font-family: Courier New;">事实上，Context ClassLoader提供一个突破委托代理机制的后门。虚拟机通过父子层次关系组织管理ClassLoader，没有个ClassLoader都有一个Parent ClassLoader（BootStartp不在此范围之内），当要求一个ClassLoader装载一个类是，他首先请求Parent ClassLoader去装载，只有parent ClassLoader装载失败，才会尝试自己装载。</span></p>
<p><span style="font-family: Courier New;">但是，某些时候这种顺序机制会造成困扰，特别是jvm需要动态载入有开发者提供的资源时。就以JNDI为例，JNDI的类是由bootstarp ClassLoader从rt.jar中间载入的，但是JNDI具体的核心驱动是由正式的实现提供的，并且通常会处于-cp参数之下（注：也就是默认的System ClassLoader管理），这就要求bootstartp ClassLoader去载入只有SystemClassLoader可见的类，正常的逻辑就没办法处理。怎么办呢？parent可以通过获得当前调用Thread的方法获得调用线程的Context ClassLoder 来载入类。</span></p>
<p><span style="font-family: Courier New;">顺带补充一句，JAXP从1.4之后也换成了类似JNDI的ClassLoader实现，嘿嘿，刚刚我说什么来着，SUN文档缺乏 ^_^</span></p>
<p><span style="font-family: Courier New;">介绍完这些之后，我们走到的十字路口，任一选择都不是万能的。一些人认为Context ClassLoader将会是新的标准。但是 一旦你的多线程需要通讯某些共享数据，你会发现，你将有一张极其丑陋的ClassLoader分布图，除非所有的线程使用一样的Context ClassLoader。并且委派使用当前ClassLoder对一些方法来说是默认继承来的，比如说Class.forName()。尽管你明确的在任何你能控制的地方使用Context ClassLoader，但是毕竟还有很多代码不归你管（备注：想起一个关于UNIX名字来源的笑话）。</span></p>
<p><span style="font-family: Courier New;">某些应用服务器使用不同的ClassLoder作为Context ClassLoader和当前ClassLoader，并且这些ClassLoader有着相同的ClassPath，但没有父子关系，这使得情况更复杂。请列位看官，花几秒钟时间想一想，为什么这样不好？被载入的类在虚拟机内部有一个全名称，不同的ClassLoader载入的相同名称的类是不一样的，这就隐藏了类型转换错误的隐患。（注：奶奶的 俺就遇到过，JBOSSClassLoader机制蛮挫的）</span></p>
<p><span style="font-family: Courier New;">这种混乱事实上在java类中也有，试着去猜测任何一个包含动态加载的java规范的ClassLoader机制，以下是一个清单：</span></p>
<ul>
    <li><span style="font-family: Courier New;">JNDI uses context classloaders</span></li>
    <li><span style="font-family: Courier New;">Class.getResource() and <code>Class.forName()</code> use the current classloader</span></li>
    <li><span style="font-family: Courier New;">JAXP uses context classloaders (as of J2SE 1.4)</span></li>
    <li><span style="font-family: Courier New;">java.util.ResourceBundle uses the caller's current classloader</span></li>
    <li><span style="font-family: Courier New;">URL protocol handlers specified via <code>java.protocol.handler.pkgs</code> system property are looked up in the bootstrap and system classloaders only</span></li>
    <li><span style="font-family: Courier New;">Java Serialization API uses the caller's current classloader by default</span></li>
</ul>
<p style="text-align: left;">而且关于这些资源的类加载机制文档时很少。</p>
<p style="text-align: left;"><strong>java开发人员应该怎么做？</strong></p>
<p style="text-align: left;">如果你的实现是利用特定的框架，那么恭喜你，实现它远比实现框架要简单得多！例如，在web应用和EJB应用中，你仅仅只要使用 <code>Class.getResource()就足够了。</code></p>
<p style="text-align: left;"><code>其他的情形下，俺有个建议（这个原则是俺工作中发现的，侵权必究,抵制盗版。），</code></p>
<p style="text-align: left;"><span style="font-family: Courier New;">下面这个类</span>可以在整个应用中的任何地方使用，作为一个全局的ClassLoader（所有的示例代码可以从<a href="http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html?page=1#resources">download</a>下载）：</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">abstract</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;ClassLoaderResolver&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #008000;">/**</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #008000;">*&nbsp;This&nbsp;method&nbsp;selects&nbsp;the&nbsp;best&nbsp;classloader&nbsp;instance&nbsp;to&nbsp;be&nbsp;used&nbsp;for<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #008000;">*&nbsp;class/resource&nbsp;loading&nbsp;by&nbsp;whoever&nbsp;calls&nbsp;this&nbsp;method.&nbsp;The&nbsp;decision<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #008000;">*&nbsp;typically&nbsp;involves&nbsp;choosing&nbsp;between&nbsp;the&nbsp;caller's&nbsp;current,&nbsp;thread&nbsp;context,<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #008000;">*&nbsp;system,&nbsp;and&nbsp;other&nbsp;classloaders&nbsp;in&nbsp;the&nbsp;JVM&nbsp;and&nbsp;is&nbsp;made&nbsp;by&nbsp;the<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #008000;">*&nbsp;{</span><span style="color: #808080;">@link</span><span style="color: #008000;">&nbsp;IClassLoadStrategy}&nbsp;instance&nbsp;established&nbsp;by&nbsp;the&nbsp;last&nbsp;call&nbsp;to<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #008000;">*&nbsp;{</span><span style="color: #808080;">@link</span><span style="color: #008000;">&nbsp;#setStrategy}.<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #008000;">*<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #008000;">*&nbsp;</span><span style="color: #808080;">@return</span><span style="color: #008000;">&nbsp;classloader&nbsp;to&nbsp;be&nbsp;used&nbsp;by&nbsp;the&nbsp;caller&nbsp;['null'&nbsp;indicates&nbsp;the<br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #008000;">*&nbsp;primordial&nbsp;loader]<br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">synchronized</span><span style="color: #000000;">&nbsp;ClassLoader&nbsp;getClassLoader()&nbsp;{<br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;Class&nbsp;caller&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;getCallerClass(</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;ClassLoadContext&nbsp;ctx&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;ClassLoadContext(caller);<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;s_strategy.getClassLoader(ctx);<br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">synchronized</span><span style="color: #000000;">&nbsp;IClassLoadStrategy&nbsp;getStrategy()&nbsp;{<br />
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;s_strategy;<br />
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">24</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">synchronized</span><span style="color: #000000;">&nbsp;IClassLoadStrategy&nbsp;setStrategy(<br />
</span><span style="color: #008080;">25</span>&nbsp;<span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;IClassLoadStrategy&nbsp;strategy)&nbsp;{<br />
</span><span style="color: #008080;">26</span>&nbsp;<span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;IClassLoadStrategy&nbsp;old&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;s_strategy;<br />
</span><span style="color: #008080;">27</span>&nbsp;<span style="color: #000000;">s_strategy&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;strategy;<br />
</span><span style="color: #008080;">28</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">29</span>&nbsp;<span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;old;<br />
</span><span style="color: #008080;">30</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">31</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">32</span>&nbsp;<span style="color: #008000;">/**</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">33</span>&nbsp;<span style="color: #008000;">*&nbsp;A&nbsp;helper&nbsp;class&nbsp;to&nbsp;get&nbsp;the&nbsp;call&nbsp;context.&nbsp;It&nbsp;subclasses&nbsp;SecurityManager&nbsp;to<br />
</span><span style="color: #008080;">34</span>&nbsp;<span style="color: #008000;">*&nbsp;make&nbsp;getClassContext()&nbsp;accessible.&nbsp;An&nbsp;instance&nbsp;of&nbsp;CallerResolver&nbsp;only<br />
</span><span style="color: #008080;">35</span>&nbsp;<span style="color: #008000;">*&nbsp;needs&nbsp;to&nbsp;be&nbsp;created,&nbsp;not&nbsp;installed&nbsp;as&nbsp;an&nbsp;actual&nbsp;security&nbsp;manager.<br />
</span><span style="color: #008080;">36</span>&nbsp;<span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">37</span>&nbsp;<span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;CallerResolver&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;SecurityManager&nbsp;{<br />
</span><span style="color: #008080;">38</span>&nbsp;<span style="color: #0000ff;">protected</span><span style="color: #000000;">&nbsp;Class[]&nbsp;getClassContext()&nbsp;{<br />
</span><span style="color: #008080;">39</span>&nbsp;<span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">super</span><span style="color: #000000;">.getClassContext();<br />
</span><span style="color: #008080;">40</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">41</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">42</span>&nbsp;<span style="color: #000000;">}&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;End&nbsp;of&nbsp;nested&nbsp;class</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">43</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">44</span>&nbsp;<span style="color: #008000;">/*</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">45</span>&nbsp;<span style="color: #008000;">*&nbsp;Indexes&nbsp;into&nbsp;the&nbsp;current&nbsp;method&nbsp;call&nbsp;context&nbsp;with&nbsp;a&nbsp;given&nbsp;offset.<br />
</span><span style="color: #008080;">46</span>&nbsp;<span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">47</span>&nbsp;<span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;Class&nbsp;getCallerClass(</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;callerOffset)&nbsp;{<br />
</span><span style="color: #008080;">48</span>&nbsp;<span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;CALLER_RESOLVER.getClassContext()[CALL_CONTEXT_OFFSET<br />
</span><span style="color: #008080;">49</span>&nbsp;<span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;callerOffset];<br />
</span><span style="color: #008080;">50</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">51</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">52</span>&nbsp;<span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;IClassLoadStrategy&nbsp;s_strategy;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;initialized&nbsp;in&nbsp;&lt;clinit&gt;</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">53</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">54</span>&nbsp;<span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;CALL_CONTEXT_OFFSET&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;may&nbsp;need&nbsp;to&nbsp;change&nbsp;if<br />
</span><span style="color: #008080;">55</span>&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;this&nbsp;class&nbsp;is<br />
</span><span style="color: #008080;">56</span>&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;redesigned</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">57</span>&nbsp;<span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;CallerResolver&nbsp;CALLER_RESOLVER;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;set&nbsp;in&nbsp;&lt;clinit&gt;</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">58</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">59</span>&nbsp;<span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;{<br />
</span><span style="color: #008080;">60</span>&nbsp;<span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
</span><span style="color: #008080;">61</span>&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;This&nbsp;can&nbsp;fail&nbsp;if&nbsp;the&nbsp;current&nbsp;SecurityManager&nbsp;does&nbsp;not&nbsp;allow<br />
</span><span style="color: #008080;">62</span>&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;RuntimePermission&nbsp;("createSecurityManager"):</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">63</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">64</span>&nbsp;<span style="color: #000000;">CALLER_RESOLVER&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;CallerResolver();<br />
</span><span style="color: #008080;">65</span>&nbsp;<span style="color: #000000;">}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(SecurityException&nbsp;se)&nbsp;{<br />
</span><span style="color: #008080;">66</span>&nbsp;<span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;RuntimeException(<br />
</span><span style="color: #008080;">67</span>&nbsp;<span style="color: #000000;">"</span><span style="color: #000000;">ClassLoaderResolver:&nbsp;could&nbsp;not&nbsp;create&nbsp;CallerResolver:&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">68</span>&nbsp;<span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;se);<br />
</span><span style="color: #008080;">69</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">70</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">71</span>&nbsp;<span style="color: #000000;">s_strategy&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;DefaultClassLoadStrategy();<br />
</span><span style="color: #008080;">72</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">73</span>&nbsp;<span style="color: #000000;">}&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;End&nbsp;of&nbsp;class.</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">74</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">75</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">76</span>&nbsp;</div>
<p><br />
</p>
<p>通过<span style="font-family: Courier New;">ClassLoaderResolver.getClassLoader()</span>方法获得一个ClassLoader的引用，并且利用正常的ClassLoader的api去加载资源，你也可以使用 <code>ResourceLoader</code> API作为备选方案</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">abstract</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;ResourceLoader&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #008000;">/**</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #008000;">&nbsp;*&nbsp;</span><span style="color: #808080;">@see</span><span style="color: #008000;">&nbsp;java.lang.ClassLoader#loadClass(java.lang.String)<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #008000;">&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;Class&nbsp;loadClass&nbsp;(</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;String&nbsp;name)</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;ClassNotFoundException{<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;ClassLoader&nbsp;loader&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ClassLoaderResolver.getClassLoader&nbsp;(</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;Class.forName&nbsp;(name,&nbsp;</span><span style="color: #0000ff;">false</span><span style="color: #000000;">,&nbsp;loader);<br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #008000;">/**</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #008000;"><br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #008000;">*&nbsp;</span><span style="color: #808080;">@see</span><span style="color: #008000;">&nbsp;java.lang.ClassLoader#getResource(java.lang.String)<br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #008000;"><br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #008000;">*/</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;URL&nbsp;getResource&nbsp;(</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;String&nbsp;name){<br />
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;ClassLoader&nbsp;loader&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ClassLoaderResolver.getClassLoader&nbsp;(</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">25</span>&nbsp;<span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(loader&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;loader.getResource&nbsp;(name);<br />
</span><span style="color: #008080;">26</span>&nbsp;<span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;ClassLoader.getSystemResource&nbsp;(name);<br />
</span><span style="color: #008080;">27</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">28</span>&nbsp;<span style="color: #000000;">&nbsp;more&nbsp;methods&nbsp;<br />
</span><span style="color: #008080;">29</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">30</span>&nbsp;<span style="color: #000000;">}&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;End&nbsp;of&nbsp;class</span></div>
<p>而决定使用何种ClassLoader策略是由接口实现的，这是一种插件机制，方便变更。</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">interface</span><span style="color: #000000;">&nbsp;IClassLoadStrategy{<br />
ClassLoader&nbsp;getClassLoader&nbsp;(ClassLoadContext&nbsp;ctx);<br />
}&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;End&nbsp;of&nbsp;interface</span></div>
<br />
它需要一个ClassLoader Context 对象去决定使用何种ClassLoader策略。<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;ClassLoadContext{<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;Class&nbsp;getCallerClass&nbsp;(){<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;m_caller;<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">ClassLoadContext&nbsp;(</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;Class&nbsp;caller){<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">m_caller&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;caller;<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;Class&nbsp;m_caller;<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">}&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;End&nbsp;of&nbsp;class</span></div>
<br />
<p><span style="font-family: Courier New;">ClassLoadContext.getCallerClass()返回调用者给ClassLoaderResolver 或者 ResourceLoader，因此能获得调用者的ClassLoader。需要注意的是，调用者是不会变的 (注：作者使用的final修饰字)。俺的方法不需要对现有的业务方法做扩展，而且可以作为静态方法是用。而且，你可以根据自己的业务场景实现独特的ClassLoaderContext。</span></p>
<p><span style="font-family: Courier New;">看出来没，这是一种很熟悉的设计模式，XD ，把获得ClassLoader的策略从业务中独立出来，这个策略可以是"总是用ContextClassLoader"或者"总是用当前ClassLoader"。想预先知道那种策略是正确的比较困难，那么这种模式可以让你简单的改变策略。</span></p>
<p><span style="font-family: Courier New;">俺写了一个默认的实现，基本可以对付95%的场景（enjoy yourself）</span></p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;DefaultClassLoadStrategy&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;IClassLoadStrategy{<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;ClassLoader&nbsp;getClassLoader&nbsp;(</span><span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;ClassLoadContext&nbsp;ctx){<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;ClassLoader&nbsp;callerLoader&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ctx.getCallerClass&nbsp;().getClassLoader&nbsp;();<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;ClassLoader&nbsp;contextLoader&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Thread.currentThread&nbsp;().getContextClassLoader&nbsp;();<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">ClassLoader&nbsp;result;<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;If&nbsp;'callerLoader'&nbsp;and&nbsp;'contextLoader'&nbsp;are&nbsp;in&nbsp;a&nbsp;parent-child<br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;relationship,&nbsp;always&nbsp;choose&nbsp;the&nbsp;child:</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(isChild&nbsp;(contextLoader,&nbsp;callerLoader))result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;callerLoader;<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(isChild&nbsp;(callerLoader,&nbsp;contextLoader))result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;contextLoader;<br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #0000ff;">else</span><span style="color: #000000;">{<br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;This&nbsp;else&nbsp;branch&nbsp;could&nbsp;be&nbsp;merged&nbsp;into&nbsp;the&nbsp;previous&nbsp;one,<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;but&nbsp;I&nbsp;show&nbsp;it&nbsp;here&nbsp;to&nbsp;emphasize&nbsp;the&nbsp;ambiguous&nbsp;case:</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;contextLoader;<br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #0000ff;">final</span><span style="color: #000000;">&nbsp;ClassLoader&nbsp;systemLoader&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ClassLoader.getSystemClassLoader&nbsp;();<br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Precaution&nbsp;for&nbsp;when&nbsp;deployed&nbsp;as&nbsp;a&nbsp;bootstrap&nbsp;or&nbsp;extension&nbsp;class:</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(isChild&nbsp;(result,&nbsp;systemLoader))result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;systemLoader;<br />
</span><span style="color: #008080;">24</span>&nbsp;<span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;result;<br />
</span><span style="color: #008080;">25</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">26</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">27</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">28</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">29</span>&nbsp;<span style="color: #000000;"><img src="http://www.blogjava.net/Images/dot.gif" alt="" />&nbsp;more&nbsp;methods&nbsp;<img src="http://www.blogjava.net/Images/dot.gif" alt="" /><br />
</span><span style="color: #008080;">30</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">31</span>&nbsp;<span style="color: #000000;">}&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;End&nbsp;of&nbsp;class<br />
</span><span style="color: #008080;">32</span>&nbsp;</div>
<p><br />
上面的逻辑比较简单，如果当前ClassLoader和Context ClassLoader是父子关系，那就总选儿子，根据委托原则，这个很容易理解。</p>
<p>如果两人平级，选择正确的ClassLoader很重要，运行时不允许含糊。这种情况下，我的代码选择Context ClassLoader（这是俺个人的经验之谈），当然也不要担心不能改变，你能随便根据需要改变。一般而言，Context ClassLoader比较适合框架，而Current ClassLoader在业务逻辑中用的更多。</p>
<p>最后，检查确保选中的ClassLoader不是System ClassLoader的parent，一旦高于System ClassLoader ，请使用System ClassLoader（你的类部署在Ext路径下面，就会出现这种情况）。</p>
<p>请注意，俺故意没关注被载入资源的名称。Java XML API 成为java 核心api的经历告诉我们，根据资源名称过滤是很不cool的idea。而且 我也没有去确认到底哪个ClassLoader被取得了，因为只要清楚原理，这很容易被推理出来。（哈哈，俺是强淫）</p>
<p>尽管讨论java 的ClassLoader不是一个很cool的话题（译者注，当年不cool，但是现在很cool），而且Java EE的ClassLoader策略越发的依赖各种平台的升级。如果这没有一个更好的设计的话，将会变成一个大大的问题。不敢您是否同意俺的观点，俺尊重你说话的权利，所以请给俺分享您的意见经验。</p>
<p>作者介绍：</p>
<p>Vladimir Roubtsov，曾经使用多种语言有超过13年的编程经历（恩 现在应该超过15年了 hoho），95年开始接触java（hoho 俺是99年看的第一本java书）。现在为Trilogy in Austin, Texas开发企业软件。</p>
<br />
<p><br />
</p>
<p><!--more--></p>
<p>翻译完了，MMD 翻译还是很麻烦的。 XD ........</p>
<p class="zoundry_bw_tags">
<!-- Tag links generated by Zoundry Blog Writer. Do not manually edit. http://www.zoundry.com -->
<span class="ztags"><span class="ztagspace">43 Things</span> : <a href="http://www.43things.com/tag/ClassLoader" class="ztag" rel="tag">ClassLoader</a></span>
</p>
<img src ="http://www.blogjava.net/jackjhy/aggbug/204163.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackjhy/" target="_blank">季失羽</a> 2008-05-30 18:22 <a href="http://www.blogjava.net/jackjhy/archive/2008/05/30/204163.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ClassLoader的几个概念、类和对象的解释</title><link>http://www.blogjava.net/jackjhy/archive/2008/05/29/203927.html</link><dc:creator>季失羽</dc:creator><author>季失羽</author><pubDate>Thu, 29 May 2008 12:11:00 GMT</pubDate><guid>http://www.blogjava.net/jackjhy/archive/2008/05/29/203927.html</guid><wfw:comment>http://www.blogjava.net/jackjhy/comments/203927.html</wfw:comment><comments>http://www.blogjava.net/jackjhy/archive/2008/05/29/203927.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/jackjhy/comments/commentRss/203927.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackjhy/services/trackbacks/203927.html</trackback:ping><description><![CDATA[首先，转载一篇文章，个人认为是看到过了讲得最清楚的 XD<br />
&nbsp;
<br />
<br />
<span>当JVM（Java虚拟机）启动时，会形成由三个类加载器组成的初始类加载器层次结构：<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bootstrap classloader<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; extension classloader<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; system classloader<br />
<br />
bootstrap
classloader －
引导（也称为原始）类加载器，它负责加载Java的核心类。在Sun的JVM中，在执行java的命令中使用-Xbootclasspath选项或使用
-D选项指定sun.boot.class.path系统属性值可以指定附加的类。这个加载器的是非常特殊的，它实际上不是
java.lang.ClassLoader的子类，而是由JVM自身实现的。大家可以通过执行以下代码来获得bootstrap
classloader加载了那些核心类库：<br />
</span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;URL[]&nbsp;urls</span><span style="color: #000000;">=</span><span style="color: #000000;">sun.misc.Launcher.getBootstrapClassPath().getURLs();<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;urls.length;&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(urls.toExternalForm());<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<span><br />
在我的计算机上的结果为：<br />
file:/C:/j2sdk1.4.1_01/jre/lib/endorsed/dom.jar<br />
file:/C:/j2sdk1.4.1_01/jre/lib/endorsed/sax.jar<br />
file:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xalan-2.3.1.jar<br />
file:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xercesImpl-2.0.0.jar<br />
file:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xml-apis.jar<br />
file:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xsltc.jar<br />
file:/C:/j2sdk1.4.1_01/jre/lib/rt.jar<br />
file:/C:/j2sdk1.4.1_01/jre/lib/i18n.jar<br />
file:/C:/j2sdk1.4.1_01/jre/lib/sunrsasign.jar<br />
file:/C:/j2sdk1.4.1_01/jre/lib/jsse.jar<br />
file:/C:/j2sdk1.4.1_01/jre/lib/jce.jar<br />
file:/C:/j2sdk1.4.1_01/jre/lib/charsets.jar<br />
file:/C:/j2sdk1.4.1_01/jre/classes<br />
这时大家知道了为什么我们不需要在系统属性CLASSPATH中指定这些类库了吧，因为JVM在启动的时候就自动加载它们了。<br />
<br />
extension
classloader －
扩展类加载器，它负责加载JRE的扩展目录（JAVA_HOME/jre/lib/ext或者由java.ext.dirs系统属性指定的）中JAR的类
包。这为引入除Java核心类以外的新功能提供了一个标准机制。因为默认的扩展目录对所有从同一个JRE中启动的JVM都是通用的，所以放入这个目录的
JAR类包对所有的JVM和system
classloader都是可见的。在这个实例上调用方法getParent()总是返回空值null，因为引导加载器bootstrap
classloader不是一个真正的ClassLoader实例。所以当大家执行以下代码时：<br />
</span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(System.getProperty(</span><span style="color: #000000;">"</span><span style="color: #000000;">java.ext.dirs</span><span style="color: #000000;">"</span><span style="color: #000000;">));<br />
&nbsp;&nbsp;&nbsp;&nbsp;ClassLoader&nbsp;extensionClassloader</span><span style="color: #000000;">=</span><span style="color: #000000;">ClassLoader.getSystemClassLoader().getParent();<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">the&nbsp;parent&nbsp;of&nbsp;extension&nbsp;classloader&nbsp;:&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">+</span><span style="color: #000000;">extensionClassloader.getParent());</span></div>
<br />
<span>
结果为：<br />
C:"j2sdk1.4.1_01"jre"lib"ext<br />
the parent of extension classloader : null<br />
extension
classloader是system classloader的parent，而bootstrap classloader是extension
classloader的parent，但它不是一个实际的classloader，所以为null。<br />
<br />
system
classloader －
系统（也称为应用）类加载器，它负责在JVM被启动时，加载来自在命令java中的-classpath或者java.class.path系统属性或者
CLASSPATH操作系统属性所指定的JAR类包和类路径。总能通过静态方法ClassLoader.getSystemClassLoader()找
到该类加载器。如果没有特别指定，则用户自定义的任何类加载器都将该类加载器作为它的父加载器。执行以下代码即可获得：<br />
&nbsp;&nbsp;&nbsp; System.out.println(System.getProperty("java.class.path"));<br />
输出结果则为用户在系统属性里面设置的CLASSPATH。<br />
classloader
加载类用的是全盘负责委托机制。所谓全盘负责，即是当一个classloader加载一个Class的时候，这个Class所依赖的和引用的所有
Class也由这个classloader负责载入，除非是显式的使用另外一个classloader载入；委托机制则是先让parent（父）类加载器
(而不是super，它与parent
classloader类不是继承关系)寻找，只有在parent找不到的时候才从自己的类路径中去寻找。此外类加载还采用了cache机制，也就是如果
cache中保存了这个Class就直接返回它，如果没有才从文件中读取和转换成Class，并存入cache，这就是为什么我们修改了Class但是必
须重新启动JVM才能生效的原因。<br />
<br />
<br />
每个ClassLoader加载Class的过程是：<br />
1.检测此Class是否载入过（即在cache中是否有此Class），如果有到8,如果没有到2<br />
2.如果parent classloader不存在（没有parent，那parent一定是bootstrap classloader了），到4<br />
3.请求parent classloader载入，如果成功到8，不成功到5<br />
4.请求jvm从bootstrap classloader中载入，如果成功到8<br />
5.寻找Class文件（从与此classloader相关的类路径中寻找）。如果找不到则到7.<br />
6.从文件中载入Class，到8.<br />
7.抛出ClassNotFoundException.<br />
8.返回Class.<br />
<br />
其中5.6步我们可以通过覆盖ClassLoader的findClass方法来实现自己的载入策略。甚至覆盖loadClass方法来实现自己的载入过程。<br />
<br />
类加载器的顺序是：<br />
先
是bootstrap classloader，然后是extension classloader，最后才是system
classloader。大家会发现加载的Class越是重要的越在靠前面。这样做的原因是出于安全性的考虑，试想如果system
classloader&#8220;亲自&#8221;加载了一个具有破坏性的&#8220;java.lang.System&#8221;类的后果吧。这种委托机制保证了用户即使具有一个这样的类，
也把它加入到了类路径中，但是它永远不会被载入，因为这个类总是由bootstrap classloader来加载的。大家可以执行一下以下的代码：<br />
&nbsp;&nbsp;&nbsp; System.out.println(System.class.getClassLoader());<br />
将会看到结果是null，这就表明java.lang.System是由bootstrap classloader加载的，因为bootstrap classloader不是一个真正的ClassLoader实例，而是由JVM实现的，正如前面已经说过的。<br />
<br />
下面就让我们来看看JVM是如何来为我们来建立类加载器的结构的：<br />
sun.misc.Launcher，顾名思义，当你执行java命令的时候，JVM会先使用bootstrap classloader载入并初始化一个Launcher，执行下来代码：<br />
&nbsp;&nbsp; System.out.println("the Launcher's classloader is "+sun.misc.Launcher.getLauncher().getClass().getClassLoader());<br />
结果为：<br />
&nbsp;&nbsp; the Launcher's classloader is null (因为是用bootstrap classloader加载,所以class loader为null)<br />
Launcher
会根据系统和命令设定初始化好class loader结构，JVM就用它来获得extension classloader和system
classloader,并载入所有的需要载入的Class，最后执行java命令指定的带有静态的main方法的Class。extension
classloader实际上是sun.misc.Launcher$ExtClassLoader类的一个实例，system
classloader实际上是sun.misc.Launcher$AppClassLoader类的一个实例。并且都是
java.net.URLClassLoader的子类。<br />
<br />
让我们来看看Launcher初试化的过程的部分代码。<br />
<br />
Launcher的部分代码：<br />
</span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Launcher&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;Launcher()&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExtClassLoader&nbsp;extclassloader;<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">初始化extension&nbsp;classloader</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;extclassloader&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ExtClassLoader.getExtClassLoader();<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">(IOException&nbsp;ioexception)&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;InternalError(</span><span style="color: #000000;">"</span><span style="color: #000000;">Could&nbsp;not&nbsp;create&nbsp;extension&nbsp;class&nbsp;loader</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;">&nbsp;{<br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">初始化system&nbsp;classloader，parent是extension&nbsp;classloader</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loader&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;AppClassLoader.getAppClassLoader(extclassloader);<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">(IOException&nbsp;ioexception1)&nbsp;{<br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throw</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;InternalError(</span><span style="color: #000000;">"</span><span style="color: #000000;">Could&nbsp;not&nbsp;create&nbsp;application&nbsp;class&nbsp;loader</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">将system&nbsp;classloader设置成当前线程的context&nbsp;classloader（将在后面加以介绍）</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.currentThread().setContextClassLoader(loader);<br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<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: #008080;">19</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;ClassLoader&nbsp;getClassLoader()&nbsp;{<br />
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">返回system&nbsp;classloader</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;loader;<br />
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;">}<br />
</span><span style="color: #008080;">25</span>&nbsp;</div>
<br />
<span>
extension classloader的部分代码：<br />
</span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Launcher$ExtClassLoader&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;URLClassLoader&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;Launcher$ExtClassLoader&nbsp;getExtClassLoader()<br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;IOException<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File&nbsp;afile[]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;getExtDirs();<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;(Launcher$ExtClassLoader)AccessController.doPrivileged(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Launcher$</span><span style="color: #000000;">1</span><span style="color: #000000;">(afile));<br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;File[]&nbsp;getExtDirs()&nbsp;{<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">获得系统属性&#8220;java.ext.dirs&#8221;</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;s&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;System.getProperty(</span><span style="color: #000000;">"</span><span style="color: #000000;">java.ext.dirs</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File&nbsp;afile[];<br />
</span><span style="color: #008080;">13</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(s&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">)&nbsp;{<br />
</span><span style="color: #008080;">14</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringTokenizer&nbsp;stringtokenizer&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;StringTokenizer(s,&nbsp;File.pathSeparator);<br />
</span><span style="color: #008080;">15</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;stringtokenizer.countTokens();<br />
</span><span style="color: #008080;">16</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;afile&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;File;<br />
</span><span style="color: #008080;">17</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;j&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;j&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;i;&nbsp;j</span><span style="color: #000000;">++</span><span style="color: #000000;">)<br />
</span><span style="color: #008080;">18</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;afile[j]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;File(stringtokenizer.nextToken());<br />
</span><span style="color: #008080;">19</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">20</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;{<br />
</span><span style="color: #008080;">21</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;afile&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;File[</span><span style="color: #000000;">0</span><span style="color: #000000;">];<br />
</span><span style="color: #008080;">22</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">23</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;afile;<br />
</span><span style="color: #008080;">24</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">25</span>&nbsp;<span style="color: #000000;">}</span></div>
<span><br />
<br />
system classloader的部分代码：<br />
</span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080;">&nbsp;1</span>&nbsp;<span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Launcher$AppClassLoader&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;URLClassLoader<br />
</span><span style="color: #008080;">&nbsp;2</span>&nbsp;<span style="color: #000000;">{<br />
</span><span style="color: #008080;">&nbsp;3</span>&nbsp;<span style="color: #000000;"><br />
</span><span style="color: #008080;">&nbsp;4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;ClassLoader&nbsp;getAppClassLoader(ClassLoader&nbsp;classloader)<br />
</span><span style="color: #008080;">&nbsp;5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">throws</span><span style="color: #000000;">&nbsp;IOException<br />
</span><span style="color: #008080;">&nbsp;6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br />
</span><span style="color: #008080;">&nbsp;7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">获得系统属性&#8220;java.class.path&#8221;</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">&nbsp;8</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;s&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;System.getProperty(</span><span style="color: #000000;">"</span><span style="color: #000000;">java.class.path</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">&nbsp;9</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File&nbsp;afile[]&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;s&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">null</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;Launcher.access$</span><span style="color: #000000;">200</span><span style="color: #000000;">(s)&nbsp;:&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;File[</span><span style="color: #000000;">0</span><span style="color: #000000;">];<br />
</span><span style="color: #008080;">10</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;(Launcher$AppClassLoader)AccessController.doPrivileged(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Launcher$</span><span style="color: #000000;">2</span><span style="color: #000000;">(s,&nbsp;afile,&nbsp;classloader));<br />
</span><span style="color: #008080;">11</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span><span style="color: #008080;">12</span>&nbsp;<span style="color: #000000;">}</span></div>
<span><br />
<br />
看
了源代码大家就清楚了吧，extension
classloader是使用系统属性&#8220;java.ext.dirs&#8221;设置类搜索路径的，并且没有parent。system
classloader是使用系统属性&#8220;java.class.path&#8221;设置类搜索路径的，并且有一个parent
classloader。Launcher初始化extension classloader，system
classloader，并将system classloader设置成为context classloader，但是仅仅返回system
classloader给JVM。<br />
<br />
这里怎么又出来一个context
classloader呢？它有什么用呢？我们在建立一个线程Thread的时候，可以为这个线程通过setContextClassLoader方法来
指定一个合适的classloader作为这个线程的context
classloader，当此线程运行的时候，我们可以通过getContextClassLoader方法来获得此context
classloader，就可以用它来载入我们所需要的Class。默认的是system
classloader。利用这个特性，我们可以&#8220;打破&#8221;classloader委托机制了，父classloader可以获得当前线程的context
classloader，而这个context
classloader可以是它的子classloader或者其他的classloader，那么父classloader就可以从其获得所需的
Class，这就打破了只能向父classloader请求的限制了。这个机制可以满足当我们的classpath是在运行时才确定,并由定制的
classloader加载的时候,由system classloader(即在jvm
classpath中)加载的class可以通过context
classloader获得定制的classloader并加载入特定的class(通常是抽象类和接口,定制的classloader中是其实现),例
如web应用中的servlet就是用这种机制加载的.<br />
<br />
<br />
好了，现在我们了解了classloader的结构和工作原理，那么我们
如何实现在运行时的动态载入和更新呢？只要我们能够动态改变类搜索路径和清除classloader的cache中已经载入的Class就行了，有两个方
案，一是我们继承一个classloader，覆盖loadclass方法，动态的寻找Class文件并使用defineClass方法来；另一个则非常
简单实用，只要重新使用一个新的类搜索路径来new一个classloader就行了，这样即更新了类搜索路径以便来载入新的Class，也重新生成了一
个空白的cache(当然,类搜索路径不一定必须更改)。噢，太好了，我们几乎不用做什么工作，java.netURLClassLoader正是一个符
合我们要求的classloader！我们可以直接使用或者继承它就可以了！<br />
<br />
这是j2se1.4 API的doc中URLClassLoader的两个构造器的描述：<br />
URLClassLoader(URL[] urls) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Constructs a new URLClassLoader for the specified URLs using the default delegation parent ClassLoader. <br />
URLClassLoader(URL[] urls, ClassLoader parent) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Constructs a new URLClassLoader for the given URLs. <br />
其中URL[] urls就是我们要设置的类搜索路径，parent就是这个classloader的parent classloader，默认的是system classloader。<br />
<br />
<br />
好，现在我们能够动态的载入Class了，这样我们就可以利用newInstance方法来获得一个Object。但我们如何将此Object造型呢？可以将此Object造型成它本身的Class吗？<br />
<br />
首先让我们来分析一下java源文件的编译，运行吧！javac命令是调用&#8220;JAVA_HOME/lib/tools.jar&#8221;中的&#8220;com.sun.tools.javac.Main&#8221;的compile方法来编译：<br />
</span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;compile(String&nbsp;as[]);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;compile(String&nbsp;as[],&nbsp;PrintWriter&nbsp;printwriter);<br />
</span></div>
<br />
<span>
返回0表示编译成功，字符串数组as则是我们用javac命令编译时的参数，以空格划分。例如：<br />
javac -classpath c:"foo"bar.jar;. -d c:" c:"Some.java<br />
则
字符串数组as为{"-classpath","c:""foo""bar.jar;.","-d","c:""","c:""Some.java"}，
如果带有PrintWriter参数，则会把编译信息出到这个指定的printWriter中。默认的输出是System.err。<br />
<br />
其中
Main是由JVM使用Launcher初始化的system
classloader载入的，根据全盘负责原则，编译器在解析这个java源文件时所发现的它所依赖和引用的所有Class也将由system
classloader载入，如果system classloader不能载入某个Class时，编译器将抛出一个&#8220;cannot resolve
symbol&#8221;错误。<br />
<br />
所以首先编译就通不过，也就是编译器无法编译一个引用了不在CLASSPATH中的未知Class的java源文件，而由于拼写错误或者没有把所需类库放到CLASSPATH中，大家一定经常看到这个&#8220;cannot resolve symbol&#8221;这个编译错误吧！<br />
<br />
其
次，就是我们把这个Class放到编译路径中，成功的进行了编译，然后在运行的时候不把它放入到CLASSPATH中而利用我们自己的
classloader来动态载入这个Class，这时候也会出现&#8220;java.lang.NoClassDefFoundError&#8221;的违例，为什么呢？<br />
<br />
我
们再来分析一下，首先调用这个造型语句的可执行的Class一定是由JVM使用Launcher初始化的system
classloader载入的，根据全盘负责原则，当我们进行造型的时候，JVM也会使用system
classloader来尝试载入这个Class来对实例进行造型，自然在system
classloader寻找不到这个Class时就会抛出&#8220;java.lang.NoClassDefFoundError&#8221;的违例。<br />
<br />
OK，
现在让我们来总结一下，java文件的编译和Class的载入执行，都是使用Launcher初始化的system
classloader作为类载入器的，我们无法动态的改变system
classloader，更无法让JVM使用我们自己的classloader来替换system
classloader，根据全盘负责原则，就限制了编译和运行时，我们无法直接显式的使用一个system
classloader寻找不到的Class，即我们只能使用Java核心类库，扩展类库和CLASSPATH中的类库中的Class。<br />
<br />
还
不死心！再尝试一下这种情况，我们把这个Class也放入到CLASSPATH中，让system
classloader能够识别和载入。然后我们通过自己的classloader来从指定的class文件中载入这个Class（不能够委托
parent载入，因为这样会被system
classloader从CLASSPATH中将其载入），然后实例化一个Object，并造型成这个Class，这样JVM也识别这个Class（因为
system
classloader能够定位和载入这个Class从CLASSPATH中），载入的也不是CLASSPATH中的这个Class，而是从
CLASSPATH外动态载入的，这样总行了吧！十分不幸的是，这时会出现&#8220;java.lang.ClassCastException&#8221;违例。<br />
<br />
为
什么呢？我们也来分析一下，不错，我们虽然从CLASSPATH外使用我们自己的classloader动态载入了这个Class，但将它的实例造型的时
候是JVM会使用system
classloader来再次载入这个Class，并尝试将使用我们的自己的classloader载入的Class的一个实例造型为system
classloader载入的这个Class（另外的一个）。大家发现什么问题了吗？也就是我们尝试将从一个classloader载入的Class的一
个实例造型为另外一个classloader载入的Class，虽然这两个Class的名字一样，甚至是从同一个class文件中载入。但不幸的是JVM
却认为这个两个Class是不同的，即JVM认为不同的classloader载入的相同的名字的Class（即使是从同一个class文件中载入的）是
不同的！这样做的原因我想大概也是主要出于安全性考虑，这样就保证所有的核心Java类都是system
classloader载入的，我们无法用自己的classloader载入的相同名字的Class的实例来替换它们的实例。<br />
<br />
看到这里，聪明的读者一定想到了该如何动态载入我们的Class，实例化，造型并调用了吧！<br />
<br />
那
就是利用面向对象的基本特性之一的多形性。我们把我们动态载入的Class的实例造型成它的一个system
classloader所能识别的父类就行了！这是为什么呢？我们还是要再来分析一次。当我们用我们自己的classloader来动态载入这我们只要把
这个Class的时候，发现它有一个父类Class，在载入它之前JVM先会载入这个父类Class，这个父类Class是system
classloader所能识别的，根据委托机制，它将由system
classloader载入，然后我们的classloader再载入这个Class，创建一个实例，造型为这个父类Class，注意了，造型成这个父类
Class的时候（也就是上溯）是面向对象的java语言所允许的并且JVM也支持的，JVM就使用system
classloader再次载入这个父类Class，然后将此实例造型为这个父类Class。大家可以从这个过程发现这个父类Class都是由
system classloader载入的，也就是同一个class
loader载入的同一个Class，所以造型的时候不会出现任何异常。而根据多形性，调用这个父类的方法时，真正执行的是这个Class（非父类
Class）的覆盖了父类方法的方法。这些方法中也可以引用system
classloader不能识别的Class，因为根据全盘负责原则，只要载入这个Class的classloader即我们自己定义的
classloader能够定位和载入这些Class就行了。<br />
<br />
这样我们就可以事先定义好一组接口或者基类并放入CLASSPATH中，然
后在执行的时候动态的载入实现或者继承了这些接口或基类的子类。还不明白吗？让我们来想一想Servlet吧，web application
server能够载入任何继承了Servlet的Class并正确的执行它们，不管它实际的Class是什么，就是都把它们实例化成为一个Servlet
Class，然后执行Servlet的init，doPost，doGet和destroy等方法的,而不管这个Servlet是从web-
inf/lib和web-inf/classes下由system
classloader的子classloader(即定制的classloader)动态载入。说了这么多希望大家都明白了。在applet,ejb等
容器中,都是采用了这种机制.<br />
<br />
对于以上各种情况，希望大家实际编写一些example来实验一下。<br />
<br />
最后我再说点别
的，classloader虽然称为类加载器，但并不意味着只能用来加载Class，我们还可以利用它也获得图片，音频文件等资源的URL，当然，这些资
源必须在CLASSPATH中的jar类库中或目录下。我们来看API的doc中关于ClassLoader的两个寻找资源和Class的方法描述吧：<br />
public URL getResource(String name)<br />
用指定的名字来查找资源，一个资源是一些能够被class代码访问的在某种程度上依赖于代码位置的数据（图片，音频，文本等等）。<br />
&nbsp;&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;&nbsp;&nbsp;&nbsp;
这个方法将先请求parent
classloader搜索资源，如果没有parent，则会在内置在虚拟机中的classloader（即bootstrap
classloader）的路径中搜索。如果失败，这个方法将调用findResource(String)来寻找资源。<br />
public static URL getSystemResource(String name)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从用来载入类的搜索路径中查找一个指定名字的资源。这个方法使用system class loader来定位资源。即相当于ClassLoader.getSystemClassLoader().getResource(name)。<br />
<br />
例如：<br />
&nbsp;&nbsp;&nbsp; System.out.println(ClassLoader.getSystemResource("java/lang/String.class"));<br />
的结果为：<br />
&nbsp;&nbsp;&nbsp; jar:file:/C:/j2sdk1.4.1_01/jre/lib/rt.jar!/java/lang/String.class<br />
表明String.class文件在rt.jar的java/lang目录中。<br />
因此我们可以将图片等资源随同Class一同打包到jar类库中（当然，也可单独打包这些资源）并添加它们到class loader的搜索路径中，我们就可以无需关心这些资源的具体位置，让class loader来帮我们寻找了！<br />
<span style="color: #0817ff;"><br />
以上是转自bea论坛的一篇文章，作者不清楚，估计是bea内部的大牛。是值得俺们顶礼膜拜的神一般的存在 XD</span><br />
<br />
<br />
最后 附上自己的几点理解<br />
<br />
bootstrap classloader&nbsp; -------&nbsp; 对应jvm中某c++写的dll类<br />
Extenson ClassLoader ---------对应内部类ExtClassLoader<br />
System ClassLoader&nbsp; ---------对应内部类AppClassLoader<br />
Custom ClassLoader&nbsp; ----------对应任何URLClassLoader的子类（你也可以继承SecureClassLoader或者更加nb一点 直接继承ClassLoader，这样的话你也是神一般的存在了 XD）<br />
<br />
<br />
以上四种classloder按照从上到下的顺序，依次为下一个的parent<br />
<br />
这个第一概念<br />
<br />
第二个概念是几个有关的classloader的类<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 抽象类 ClassLoader<br />
&nbsp;&nbsp;&nbsp;&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; SecureClassLoader<br />
&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; URLClassloader<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; <br />
&nbsp;sun的ExtClassLoader&nbsp;&nbsp; sun的AppClassLoader <br />
以上的类之间是继承关系，与第一个概念说的parent是两回事情，需要小心。<br />
<br />
第三个概念是Thread的ContextClassLoader<br />
其实从Context的名称就可以看出来，这只是一个用以存储任何classloader引用的临时存储空间，与classloader的层次没有任何关系。<br />
<br />
<br />
第四 就是如何实现自己的classloader了，本来是要翻译另外一篇文章Find a way out of the ClassLoader maze<br />
不过今天时间都花在《小夫妻天天恶战》这篇神文上了 XD 强烈推荐任何和俺一样期望彪悍人生的朋友都去看看<br />
<br />
翻译明天补上，浪费时间是可耻的 XD<br />
<br />
匿鸟，晚上还有朋友推荐的 《lie with me》（与我同眠）要看。XD<br />
<br />
<br />
</span>
<img src ="http://www.blogjava.net/jackjhy/aggbug/203927.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackjhy/" target="_blank">季失羽</a> 2008-05-29 20:11 <a href="http://www.blogjava.net/jackjhy/archive/2008/05/29/203927.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于extends 和 constructor的默认实现与覆盖策略</title><link>http://www.blogjava.net/jackjhy/archive/2008/05/28/203416.html</link><dc:creator>季失羽</dc:creator><author>季失羽</author><pubDate>Wed, 28 May 2008 02:44:00 GMT</pubDate><guid>http://www.blogjava.net/jackjhy/archive/2008/05/28/203416.html</guid><wfw:comment>http://www.blogjava.net/jackjhy/comments/203416.html</wfw:comment><comments>http://www.blogjava.net/jackjhy/archive/2008/05/28/203416.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.blogjava.net/jackjhy/comments/commentRss/203416.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jackjhy/services/trackbacks/203416.html</trackback:ping><description><![CDATA[<p>今天在TSS上又看到有人讨论java多继承的问题，是想起这个话题的原因。^_^</p>
<p><br />
</p>
java中任何类都默认继承 Java.lang.Object，除非被另一个继承覆盖(override)，hoho 俺一直这么称呼override的，感觉更加贴切一些。<br />
请看以下代码:<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;org.myth.test;<br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;SuperSon{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;SuperSon(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">this&nbsp;is&nbsp;super&nbsp;son</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}<br />
</span></div>
<br />
对于编译器来说，这段代码会被首先补全为：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;org.myth.test;<br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;SuperSon&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;Object{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;SuperSon(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">this&nbsp;is&nbsp;super&nbsp;son</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}<br />
</span></div>
<br />
对待任何一个类，编译器会去检查extends关键字，如果没有，编译器会默认添加extens Object<br />
<br />
extends Object就是一段默认隐藏的代码，同样在Constructor中，也有一段默认隐藏的代码。<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;org.myth.test;<br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;SuperSon&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;Object{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;SuperSon(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">super</span><span style="color: #000000;">();</span><span style="color: #008000;">//</span><span style="color: #008000;">这就是一段默认隐藏代码</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">this&nbsp;is&nbsp;super&nbsp;son</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp; //</span><span style="color: #008000;">整个构造方法也是一段默认隐藏代码</span><span style="color: #008000;"><br />
</span><span style="color: #000000;"><br />
}<br />
</span></div>
<br />
如同编译类时编译器回去检查extends关键字一样，编译器会首先检查是否存在constructor，如果没有,默认增加ClassName()构造方法。<br />
在构造方法内部，编译器会检查第一行代码是否为super构造方法，如果不是，默认添加super()<br />
<br />
这个就是为什么 new一个对象的时候，首先调用的是父类的构造方法。<br />
<br />
一个错误代码示例：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;org.myth.test;<br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;SuperMan&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;SuperMan(String&nbsp;s){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">this&nbsp;is&nbsp;super&nbsp;man</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}<br />
<br />
<br />
<br />
</span><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;org.myth.test;<br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;SuperSon&nbsp;</span><span style="color: #0000ff;">extends</span><span style="color: #000000;">&nbsp;SuperMan{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;SuperSon(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">this&nbsp;is&nbsp;super&nbsp;son</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}<br />
</span></div>
<br />
<br />
嘿嘿 第一篇文章<br />
<img src ="http://www.blogjava.net/jackjhy/aggbug/203416.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackjhy/" target="_blank">季失羽</a> 2008-05-28 10:44 <a href="http://www.blogjava.net/jackjhy/archive/2008/05/28/203416.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Test Blog</title><link>http://www.blogjava.net/jackjhy/archive/2008/05/26/202995.html</link><dc:creator>季失羽</dc:creator><author>季失羽</author><pubDate>Mon, 26 May 2008 09:35:00 GMT</pubDate><guid>http://www.blogjava.net/jackjhy/archive/2008/05/26/202995.html</guid><description><![CDATA[2008年5月26日<br />
初次使用blogjava<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/jackjhy/aggbug/202995.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jackjhy/" target="_blank">季失羽</a> 2008-05-26 17:35 <a href="http://www.blogjava.net/jackjhy/archive/2008/05/26/202995.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>