??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲精品美女久久久久99小说,亚洲男人的天堂www,亚洲精品乱码久久久久久按摩http://www.tkk7.com/jackjhy/archive/2009/03/03/257477.html季失?/dc:creator>季失?/author>Tue, 03 Mar 2009 01:59:00 GMThttp://www.tkk7.com/jackjhy/archive/2009/03/03/257477.htmlhttp://www.tkk7.com/jackjhy/comments/257477.htmlhttp://www.tkk7.com/jackjhy/archive/2009/03/03/257477.html#Feedback0http://www.tkk7.com/jackjhy/comments/commentRss/257477.htmlhttp://www.tkk7.com/jackjhy/services/trackbacks/257477.html如何看懂Javah后的反编译代?/font>

作者:dozb

一般情况下Java应用的开发者ؓ了保护代码不被别人抄袭,在生成class文g的时候都java文gq行了؜淆,q种class文g用反~译工具得到的结果很隄懂,q且不能q行~译。本文从研究的角度,析如何Lq种反编译过来的文g?/p>

例子一Q赋?/font>
反编译过来的代码如下Q?br />         Node node;
        Node node1 = _$3.getChildNodes().item(0);
        node1;
        node1;
        JVM INSTR swap ;
        node;
        getChildNodes();
        0;
        item();
        getChildNodes();
        0;
        item();
        getNodeValue();
        String s;
        s;
原始语句Q?br />         Node node;
        Node node1 = currDocument.getChildNodes().item(0);
 node = node1;
        String s = node.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
注解Q?br />         JVM INSTR swap ; //赋D?br /> l习Q?br />         String s1;
        String s8 = node.getChildNodes().item(1).getChildNodes().item(0).getNodeValue();
        s8;
        s8;
        JVM INSTR swap ;
        s1;
        10;
        Integer.parseInt();
        int i;
        i;

   
例子二:不带参数创徏对象
反编译过来的代码如下Q?br />         JVM INSTR new #244 <Class CrossTable>;
        JVM INSTR dup ;
        JVM INSTR swap ;
        CrossTable();
        CrossTable crosstable;
        crosstable;

原始语句Q?br />         CrossTable crosstable = new CrossTable();
注解Q?br /> l习Q?br />         JVM INSTR new #246 <Class Database>;
        JVM INSTR dup ;
        JVM INSTR swap ;
        Database();
        Object obj;
        obj;

例子三:带参数创建对?br /> 反编译过来的代码如下Q?br />         JVM INSTR new #262 <Class StringBuffer>;
        JVM INSTR dup ;
        JVM INSTR swap ;
        String.valueOf(s2);
        StringBuffer();
        s.substring(j, i);
        append();
        s6;
        append();
        toString();
        s2;
 
原始语句Q?br />  s2 = (new StringBuffer(String.valueOf(s2))).append(s.substring(j, i)).append(s6).toString();
注解Q?br />  此语句实际上是:s2 += s.substring(j, i) + s6;
l习Q?/p>

例子四:for循环
反编译过来的代码如下Q?br />         int k = 0;
          goto _L4
_L8:
 ...
 k++;
_L4:
        if(k < as.length) goto _L8; else goto _L7

原始语句Q?br />  for(int k=0;k < as.length;k++)
 {
     ...
 }
注解Q?/p>

例子五:while循环
反编译过来的代码如下Q?br />         String s1 = "";
          goto _L1
_L3:
        JVM INSTR new #262 <Class StringBuffer>;
        JVM INSTR dup ;
        JVM INSTR swap ;
        String.valueOf(s1);
        StringBuffer();
        _$2(resultset, s, l);
        append();
        toString();
        s1;
_L1:
        if(resultset.next()) goto _L3; else goto _L2

原始语句Q?br />  String s1 = "";
 while(resultset.next())
 {
  s1 = s1 + resultSetToString(resultset, s, l);

 }

]]>
[译]走出ClassLoader的迷?/title><link>http://www.tkk7.com/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.tkk7.com/jackjhy/archive/2008/05/30/204163.html</guid><wfw:comment>http://www.tkk7.com/jackjhy/comments/204163.html</wfw:comment><comments>http://www.tkk7.com/jackjhy/archive/2008/05/30/204163.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jackjhy/comments/commentRss/204163.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/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;">                                                               System、Current和Context ClassLoaderQ分别在何种情Ş下用?</em></p> <p><br /> </p> <p style="text-align: left;"><strong>1、问题:在何U情形下使用<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>管没经帔R到这个问题,但是惌得准的{案q不那么ҎQ特别是在开发应用框架的时候,你需要动态的加蝲一些类和资源,不可避免的你会被此困扰。一般来_动态蝲入资源有三种ClassLoader可以选择QSystem ClassLoaderQ也叫App ClassLoaderQ、当前类的ClassLoader和CurrentThread的Context ClassLoader。那么, 如何选择使用Q?/code></span></p> <p style="text-align: left;">首先可以单排除的是System ClassLoaderQ这个ClassLoader负责从参?classpath?cp、和操作pȝCLASSPATH中蝲入资源。ƈ且,MClassLoader的getSystemXXX()Ҏ都是有以上几个\径指定的。我们应该很需要编写直接用ClassLoader的程序,否则你的代码只能在命o行运行,发布你的代码成ؓejb、web应用或者java web start应用Q我肯定他们会崩溃!</p> <p style="text-align: left;">接下来,我们只剩下两个选择了:当前ClassLoader和Thread Context ClassLoader</p> <p style="text-align: left;">Current ClassLoaderQ当前类所属的ClassLoaderQ在虚拟ZcM间引用,默认是使用q个ClassLoader。另外,当你使用<span style="font-family: Courier New;">Class.forName()</span>, <code>Class.getResource()q几个不带ClassLoader参数的方法是Q默认同样适用当前cȝClassLoader。你可以通过ҎXX.class.GetClassLoader()获取?/code></p> <p style="text-align: left;">Thread Context ClassLoaderQ没一个Thread有一个相兌pȝContext ClassLoaderQ由nativeҎ建立的除外)Q可以通过<span style="font-family: Courier New;">Thread.setContextClassLoader()Ҏ讄。如果你没有d讄QThread默认集成Parent Thread?Context ClassLoaderQ注意,是parent Thread 不是父类Q。如?你整个应用中都没有对此作M处理Q那?所有的Thread都会以System ClassLoader作ؓContext ClassLoader。知道这一点很重要Q因Zweb服务器,java企业服务器用一些复杂而且_y的ClassLoaderl构d现诸如JNDI、线E池和热部v{功能以来,q种单的情况发的少见了?/span></p> <p><span style="font-family: Courier New;">q篇文章中ؓ什么把Thread Context ClassLoader攑֜首要的位|,别hq没有大张旗鼓的介绍?很多开发者都Ҏ不甚了解Q因为sun没有提供很好的说明文档?/span></p> <p><span style="font-family: Courier New;">事实上,Context ClassLoader提供一个突破委托代理机制的后门。虚拟机通过父子层次关系l织理ClassLoaderQ没有个ClassLoader都有一个Parent ClassLoaderQBootStartp不在此范围之内)Q当要求一个ClassLoader装蝲一个类是,他首先请求Parent ClassLoader去装载,只有parent ClassLoader装蝲p|Q才会尝试自p载?/span></p> <p><span style="font-family: Courier New;">但是Q某些时候这U顺序机制会造成困扰Q特别是jvm需要动态蝲入有开发者提供的资源时。就以JNDIZQJNDI的类是由bootstarp ClassLoader从rt.jar中间载入的,但是JNDI具体的核心驱动是由正式的实现提供的,q且通常会处?cp参数之下Q注Q也是默认的System ClassLoader理Q,q就要求bootstartp ClassLoader去蝲入只有SystemClassLoader可见的类Q正常的逻辑没办法处理。怎么办呢Qparent可以通过获得当前调用Thread的方法获得调用线E的Context ClassLoder 来蝲入类?/span></p> <p><span style="font-family: Courier New;">带补充一句,JAXP?.4之后也换成了cMJNDI的ClassLoader实现Q嘿嘿,刚刚我说什么来着QSUN文档~Z ^_^</span></p> <p><span style="font-family: Courier New;">介绍完这些之后,我们走到的十字\口,M选择都不是万能的。一些h认ؓContext ClassLoader会是新的标准。但?一旦你的多U程需要通讯某些׃n数据Q你会发玎ͼ你将有一张极其丑陋的ClassLoader分布图,除非所有的U程使用一LContext ClassLoader。ƈ且委z用当前ClassLoder对一些方法来说是默认l承来的Q比如说Class.forName()。尽你明确的在M你能控制的地方用Context ClassLoaderQ但是毕竟还有很多代码不归你(备注Q想起一个关于UNIX名字来源的笑话)?/span></p> <p><span style="font-family: Courier New;">某些应用服务器用不同的ClassLoder作ؓContext ClassLoader和当前ClassLoaderQƈ且这些ClassLoader有着相同的ClassPathQ但没有父子关系Q这使得情况更复杂。请列位看官Q花几秒钟时间想一惻IZ么这样不好?被蝲入的cd虚拟机内部有一个全名称Q不同的ClassLoader载入的相同名U的cL不一LQ这隐藏了cd转换错误的隐患。(注:奶奶?俺就遇到q,JBOSSClassLoader机制蛮挫的)</span></p> <p><span style="font-family: Courier New;">q种混ؕ事实上在javacM也有Q试着ȝQ何一个包含动态加载的java规范的ClassLoader机制Q以下是一个清单:</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;">而且关于q些资源的类加蝲机制文档时很?/p> <p style="text-align: left;"><strong>java开发h员应该怎么做?</strong></p> <p style="text-align: left;">如果你的实现是利用特定的框架Q那么恭喜你Q实现它q比实现框架要简单得多!例如Q在web应用和EJB应用中,你仅仅只要?<code>Class.getResource()p够了?/code></p> <p style="text-align: left;"><code>其他的情形下Q俺有个Q这个原则是俺工作中发现的,侉|必究,抵制盗版。)Q?/code></p> <p style="text-align: left;"><span style="font-family: Courier New;">下面q个c?/span>可以在整个应用中的Q何地方用,作ؓ一个全局的ClassLoaderQ所有的CZ代码可以?a >download</a>下蝲Q:</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;"> 1</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">abstract</span><span style="color: #000000;"> </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> ClassLoaderResolver {<br /> </span><span style="color: #008080;"> 2</span> <span style="color: #008000;">/**</span><span style="color: #008000;"><br /> </span><span style="color: #008080;"> 3</span> <span style="color: #008000;">* This method selects the best classloader instance to be used for<br /> </span><span style="color: #008080;"> 4</span> <span style="color: #008000;">* class/resource loading by whoever calls this method. The decision<br /> </span><span style="color: #008080;"> 5</span> <span style="color: #008000;">* typically involves choosing between the caller's current, thread context,<br /> </span><span style="color: #008080;"> 6</span> <span style="color: #008000;">* system, and other classloaders in the JVM and is made by the<br /> </span><span style="color: #008080;"> 7</span> <span style="color: #008000;">* {</span><span style="color: #808080;">@link</span><span style="color: #008000;"> IClassLoadStrategy} instance established by the last call to<br /> </span><span style="color: #008080;"> 8</span> <span style="color: #008000;">* {</span><span style="color: #808080;">@link</span><span style="color: #008000;"> #setStrategy}.<br /> </span><span style="color: #008080;"> 9</span> <span style="color: #008000;">*<br /> </span><span style="color: #008080;">10</span> <span style="color: #008000;">* </span><span style="color: #808080;">@return</span><span style="color: #008000;"> classloader to be used by the caller ['null' indicates the<br /> </span><span style="color: #008080;">11</span> <span style="color: #008000;">* primordial loader]<br /> </span><span style="color: #008080;">12</span> <span style="color: #008000;">*/</span><span style="color: #000000;"><br /> </span><span style="color: #008080;">13</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> </span><span style="color: #0000ff;">synchronized</span><span style="color: #000000;"> ClassLoader getClassLoader() {<br /> </span><span style="color: #008080;">14</span> <span style="color: #0000ff;">final</span><span style="color: #000000;"> Class caller </span><span style="color: #000000;">=</span><span style="color: #000000;"> getCallerClass(</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br /> </span><span style="color: #008080;">15</span> <span style="color: #0000ff;">final</span><span style="color: #000000;"> ClassLoadContext ctx </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> ClassLoadContext(caller);<br /> </span><span style="color: #008080;">16</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">17</span> <span style="color: #0000ff;">return</span><span style="color: #000000;"> s_strategy.getClassLoader(ctx);<br /> </span><span style="color: #008080;">18</span> <span style="color: #000000;">}<br /> </span><span style="color: #008080;">19</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">20</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> </span><span style="color: #0000ff;">synchronized</span><span style="color: #000000;"> IClassLoadStrategy getStrategy() {<br /> </span><span style="color: #008080;">21</span> <span style="color: #0000ff;">return</span><span style="color: #000000;"> s_strategy;<br /> </span><span style="color: #008080;">22</span> <span style="color: #000000;">}<br /> </span><span style="color: #008080;">23</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">24</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> </span><span style="color: #0000ff;">synchronized</span><span style="color: #000000;"> IClassLoadStrategy setStrategy(<br /> </span><span style="color: #008080;">25</span> <span style="color: #0000ff;">final</span><span style="color: #000000;"> IClassLoadStrategy strategy) {<br /> </span><span style="color: #008080;">26</span> <span style="color: #0000ff;">final</span><span style="color: #000000;"> IClassLoadStrategy old </span><span style="color: #000000;">=</span><span style="color: #000000;"> s_strategy;<br /> </span><span style="color: #008080;">27</span> <span style="color: #000000;">s_strategy </span><span style="color: #000000;">=</span><span style="color: #000000;"> strategy;<br /> </span><span style="color: #008080;">28</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">29</span> <span style="color: #0000ff;">return</span><span style="color: #000000;"> old;<br /> </span><span style="color: #008080;">30</span> <span style="color: #000000;">}<br /> </span><span style="color: #008080;">31</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">32</span> <span style="color: #008000;">/**</span><span style="color: #008000;"><br /> </span><span style="color: #008080;">33</span> <span style="color: #008000;">* A helper class to get the call context. It subclasses SecurityManager to<br /> </span><span style="color: #008080;">34</span> <span style="color: #008000;">* make getClassContext() accessible. An instance of CallerResolver only<br /> </span><span style="color: #008080;">35</span> <span style="color: #008000;">* needs to be created, not installed as an actual security manager.<br /> </span><span style="color: #008080;">36</span> <span style="color: #008000;">*/</span><span style="color: #000000;"><br /> </span><span style="color: #008080;">37</span> <span style="color: #0000ff;">private</span><span style="color: #000000;"> </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> </span><span style="color: #0000ff;">final</span><span style="color: #000000;"> </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> CallerResolver </span><span style="color: #0000ff;">extends</span><span style="color: #000000;"> SecurityManager {<br /> </span><span style="color: #008080;">38</span> <span style="color: #0000ff;">protected</span><span style="color: #000000;"> Class[] getClassContext() {<br /> </span><span style="color: #008080;">39</span> <span style="color: #0000ff;">return</span><span style="color: #000000;"> </span><span style="color: #0000ff;">super</span><span style="color: #000000;">.getClassContext();<br /> </span><span style="color: #008080;">40</span> <span style="color: #000000;">}<br /> </span><span style="color: #008080;">41</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">42</span> <span style="color: #000000;">} </span><span style="color: #008000;">//</span><span style="color: #008000;"> End of nested class</span><span style="color: #008000;"><br /> </span><span style="color: #008080;">43</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">44</span> <span style="color: #008000;">/*</span><span style="color: #008000;"><br /> </span><span style="color: #008080;">45</span> <span style="color: #008000;">* Indexes into the current method call context with a given offset.<br /> </span><span style="color: #008080;">46</span> <span style="color: #008000;">*/</span><span style="color: #000000;"><br /> </span><span style="color: #008080;">47</span> <span style="color: #0000ff;">private</span><span style="color: #000000;"> </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> Class getCallerClass(</span><span style="color: #0000ff;">final</span><span style="color: #000000;"> </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> callerOffset) {<br /> </span><span style="color: #008080;">48</span> <span style="color: #0000ff;">return</span><span style="color: #000000;"> CALLER_RESOLVER.getClassContext()[CALL_CONTEXT_OFFSET<br /> </span><span style="color: #008080;">49</span> <span style="color: #000000;">+</span><span style="color: #000000;"> callerOffset];<br /> </span><span style="color: #008080;">50</span> <span style="color: #000000;">}<br /> </span><span style="color: #008080;">51</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">52</span> <span style="color: #0000ff;">private</span><span style="color: #000000;"> </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> IClassLoadStrategy s_strategy; </span><span style="color: #008000;">//</span><span style="color: #008000;"> initialized in <clinit></span><span style="color: #008000;"><br /> </span><span style="color: #008080;">53</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">54</span> <span style="color: #0000ff;">private</span><span style="color: #000000;"> </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> </span><span style="color: #0000ff;">final</span><span style="color: #000000;"> </span><span style="color: #0000ff;">int</span><span style="color: #000000;"> CALL_CONTEXT_OFFSET </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #000000;">3</span><span style="color: #000000;">; </span><span style="color: #008000;">//</span><span style="color: #008000;"> may need to change if<br /> </span><span style="color: #008080;">55</span> <span style="color: #008000;">//</span><span style="color: #008000;"> this class is<br /> </span><span style="color: #008080;">56</span> <span style="color: #008000;">//</span><span style="color: #008000;"> redesigned</span><span style="color: #008000;"><br /> </span><span style="color: #008080;">57</span> <span style="color: #0000ff;">private</span><span style="color: #000000;"> </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> </span><span style="color: #0000ff;">final</span><span style="color: #000000;"> CallerResolver CALLER_RESOLVER; </span><span style="color: #008000;">//</span><span style="color: #008000;"> set in <clinit></span><span style="color: #008000;"><br /> </span><span style="color: #008080;">58</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">59</span> <span style="color: #0000ff;">static</span><span style="color: #000000;"> {<br /> </span><span style="color: #008080;">60</span> <span style="color: #0000ff;">try</span><span style="color: #000000;"> {<br /> </span><span style="color: #008080;">61</span> <span style="color: #008000;">//</span><span style="color: #008000;"> This can fail if the current SecurityManager does not allow<br /> </span><span style="color: #008080;">62</span> <span style="color: #008000;">//</span><span style="color: #008000;"> RuntimePermission ("createSecurityManager"):</span><span style="color: #008000;"><br /> </span><span style="color: #008080;">63</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">64</span> <span style="color: #000000;">CALLER_RESOLVER </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> CallerResolver();<br /> </span><span style="color: #008080;">65</span> <span style="color: #000000;">} </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (SecurityException se) {<br /> </span><span style="color: #008080;">66</span> <span style="color: #0000ff;">throw</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> RuntimeException(<br /> </span><span style="color: #008080;">67</span> <span style="color: #000000;">"</span><span style="color: #000000;">ClassLoaderResolver: could not create CallerResolver: </span><span style="color: #000000;">"</span><span style="color: #000000;"><br /> </span><span style="color: #008080;">68</span> <span style="color: #000000;">+</span><span style="color: #000000;"> se);<br /> </span><span style="color: #008080;">69</span> <span style="color: #000000;">}<br /> </span><span style="color: #008080;">70</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">71</span> <span style="color: #000000;">s_strategy </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">new</span><span style="color: #000000;"> DefaultClassLoadStrategy();<br /> </span><span style="color: #008080;">72</span> <span style="color: #000000;">}<br /> </span><span style="color: #008080;">73</span> <span style="color: #000000;">} </span><span style="color: #008000;">//</span><span style="color: #008000;"> End of class.</span><span style="color: #008000;"><br /> </span><span style="color: #008080;">74</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">75</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">76</span> </div> <p><br /> </p> <p>通过<span style="font-family: Courier New;">ClassLoaderResolver.getClassLoader()</span>Ҏ获得一个ClassLoader的引用,q且利用正常的ClassLoader的apid载资源,你也可以使用 <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;"> 1</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">abstract</span><span style="color: #000000;"> </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> ResourceLoader {<br /> </span><span style="color: #008080;"> 2</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;"> 3</span> <span style="color: #008000;">/**</span><span style="color: #008000;"><br /> </span><span style="color: #008080;"> 4</span> <span style="color: #008000;"> * </span><span style="color: #808080;">@see</span><span style="color: #008000;"> java.lang.ClassLoader#loadClass(java.lang.String)<br /> </span><span style="color: #008080;"> 5</span> <span style="color: #008000;"> </span><span style="color: #008000;">*/</span><span style="color: #000000;"><br /> </span><span style="color: #008080;"> 6</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> Class loadClass (</span><span style="color: #0000ff;">final</span><span style="color: #000000;"> String name)</span><span style="color: #0000ff;">throws</span><span style="color: #000000;"> ClassNotFoundException{<br /> </span><span style="color: #008080;"> 7</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;"> 8</span> <span style="color: #0000ff;">final</span><span style="color: #000000;"> ClassLoader loader </span><span style="color: #000000;">=</span><span style="color: #000000;"> ClassLoaderResolver.getClassLoader (</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br /> </span><span style="color: #008080;"> 9</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">10</span> <span style="color: #0000ff;">return</span><span style="color: #000000;"> Class.forName (name, </span><span style="color: #0000ff;">false</span><span style="color: #000000;">, loader);<br /> </span><span style="color: #008080;">11</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">12</span> <span style="color: #000000;">}<br /> </span><span style="color: #008080;">13</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">14</span> <span style="color: #008000;">/**</span><span style="color: #008000;"><br /> </span><span style="color: #008080;">15</span> <span style="color: #008000;"><br /> </span><span style="color: #008080;">16</span> <span style="color: #008000;">* </span><span style="color: #808080;">@see</span><span style="color: #008000;"> java.lang.ClassLoader#getResource(java.lang.String)<br /> </span><span style="color: #008080;">17</span> <span style="color: #008000;"><br /> </span><span style="color: #008080;">18</span> <span style="color: #008000;">*/</span><span style="color: #000000;">    <br /> </span><span style="color: #008080;">19</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">20</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">21</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">static</span><span style="color: #000000;"> URL getResource (</span><span style="color: #0000ff;">final</span><span style="color: #000000;"> String name){<br /> </span><span style="color: #008080;">22</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">23</span> <span style="color: #0000ff;">final</span><span style="color: #000000;"> ClassLoader loader </span><span style="color: #000000;">=</span><span style="color: #000000;"> ClassLoaderResolver.getClassLoader (</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br /> </span><span style="color: #008080;">24</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">25</span> <span style="color: #0000ff;">if</span><span style="color: #000000;"> (loader </span><span style="color: #000000;">!=</span><span style="color: #000000;"> </span><span style="color: #0000ff;">null</span><span style="color: #000000;">)</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> loader.getResource (name);<br /> </span><span style="color: #008080;">26</span> <span style="color: #0000ff;">else</span><span style="color: #000000;"> </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> ClassLoader.getSystemResource (name);<br /> </span><span style="color: #008080;">27</span> <span style="color: #000000;">}<br /> </span><span style="color: #008080;">28</span> <span style="color: #000000;"> more methods <br /> </span><span style="color: #008080;">29</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">30</span> <span style="color: #000000;">} </span><span style="color: #008000;">//</span><span style="color: #008000;"> End of class</span></div> <p>而决定用何UClassLoader{略是由接口实现的,q是一U插件机Ӟ方便变更?/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;"> </span><span style="color: #0000ff;">interface</span><span style="color: #000000;"> IClassLoadStrategy{<br /> ClassLoader getClassLoader (ClassLoadContext ctx);<br /> } </span><span style="color: #008000;">//</span><span style="color: #008000;"> End of interface</span></div> <br /> 它需要一个ClassLoader Context 对象d定用何UClassLoader{略?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;"> 1</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> ClassLoadContext{<br /> </span><span style="color: #008080;"> 2</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;"> 3</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">final</span><span style="color: #000000;"> Class getCallerClass (){<br /> </span><span style="color: #008080;"> 4</span> <span style="color: #0000ff;">return</span><span style="color: #000000;"> m_caller;<br /> </span><span style="color: #008080;"> 5</span> <span style="color: #000000;">}<br /> </span><span style="color: #008080;"> 6</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;"> 7</span> <span style="color: #000000;">ClassLoadContext (</span><span style="color: #0000ff;">final</span><span style="color: #000000;"> Class caller){<br /> </span><span style="color: #008080;"> 8</span> <span style="color: #000000;">m_caller </span><span style="color: #000000;">=</span><span style="color: #000000;"> caller;<br /> </span><span style="color: #008080;"> 9</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">10</span> <span style="color: #000000;">}<br /> </span><span style="color: #008080;">11</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">12</span> <span style="color: #0000ff;">private</span><span style="color: #000000;"> </span><span style="color: #0000ff;">final</span><span style="color: #000000;"> Class m_caller;<br /> </span><span style="color: #008080;">13</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">14</span> <span style="color: #000000;">} </span><span style="color: #008000;">//</span><span style="color: #008000;"> End of class</span></div> <br /> <p><span style="font-family: Courier New;">ClassLoadContext.getCallerClass()q回调用者给ClassLoaderResolver 或?ResourceLoaderQ因此能获得调用者的ClassLoader。需要注意的是,调用者是不会变的 (注:作者用的final修饰?。俺的方法不需要对现有的业务方法做扩展Q而且可以作ؓ静态方法是用。而且Q你可以Ҏ自己的业务场景实现独特的ClassLoaderContext?/span></p> <p><span style="font-family: Courier New;">看出来没Q这是一U很熟悉的设计模式,XD Q把获得ClassLoader的策略从业务中独立出来,q个{略可以?L用ContextClassLoader"或?L用当前ClassLoader"。想预先知道那种{略是正的比较困难Q那么这U模式可以让你简单的改变{略?/span></p> <p><span style="font-family: Courier New;">俺写了一个默认的实现Q基本可以对?5%的场景(enjoy yourselfQ?/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;"> 1</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> DefaultClassLoadStrategy </span><span style="color: #0000ff;">implements</span><span style="color: #000000;"> IClassLoadStrategy{<br /> </span><span style="color: #008080;"> 2</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;"> 3</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> ClassLoader getClassLoader (</span><span style="color: #0000ff;">final</span><span style="color: #000000;"> ClassLoadContext ctx){<br /> </span><span style="color: #008080;"> 4</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;"> 5</span> <span style="color: #0000ff;">final</span><span style="color: #000000;"> ClassLoader callerLoader </span><span style="color: #000000;">=</span><span style="color: #000000;"> ctx.getCallerClass ().getClassLoader ();<br /> </span><span style="color: #008080;"> 6</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;"> 7</span> <span style="color: #0000ff;">final</span><span style="color: #000000;"> ClassLoader contextLoader </span><span style="color: #000000;">=</span><span style="color: #000000;"> Thread.currentThread ().getContextClassLoader ();<br /> </span><span style="color: #008080;"> 8</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;"> 9</span> <span style="color: #000000;">ClassLoader result;<br /> </span><span style="color: #008080;">10</span> <span style="color: #008000;">//</span><span style="color: #008000;"> If 'callerLoader' and 'contextLoader' are in a parent-child<br /> </span><span style="color: #008080;">11</span> <span style="color: #008000;">//</span><span style="color: #008000;"> relationship, always choose the child:</span><span style="color: #008000;"><br /> </span><span style="color: #008080;">12</span> <span style="color: #0000ff;">if</span><span style="color: #000000;"> (isChild (contextLoader, callerLoader))result </span><span style="color: #000000;">=</span><span style="color: #000000;"> callerLoader;<br /> </span><span style="color: #008080;">13</span> <span style="color: #0000ff;">else</span><span style="color: #000000;"> </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (isChild (callerLoader, contextLoader))result </span><span style="color: #000000;">=</span><span style="color: #000000;"> contextLoader;<br /> </span><span style="color: #008080;">14</span> <span style="color: #0000ff;">else</span><span style="color: #000000;">{<br /> </span><span style="color: #008080;">15</span> <span style="color: #008000;">//</span><span style="color: #008000;"> This else branch could be merged into the previous one,<br /> </span><span style="color: #008080;">16</span> <span style="color: #008000;">//</span><span style="color: #008000;"> but I show it here to emphasize the ambiguous case:</span><span style="color: #008000;"><br /> </span><span style="color: #008080;">17</span> <span style="color: #000000;">result </span><span style="color: #000000;">=</span><span style="color: #000000;"> contextLoader;<br /> </span><span style="color: #008080;">18</span> <span style="color: #000000;">}<br /> </span><span style="color: #008080;">19</span> <span style="color: #0000ff;">final</span><span style="color: #000000;"> ClassLoader systemLoader </span><span style="color: #000000;">=</span><span style="color: #000000;"> ClassLoader.getSystemClassLoader ();<br /> </span><span style="color: #008080;">20</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">21</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">22</span> <span style="color: #008000;">//</span><span style="color: #008000;"> Precaution for when deployed as a bootstrap or extension class:</span><span style="color: #008000;"><br /> </span><span style="color: #008080;">23</span> <span style="color: #0000ff;">if</span><span style="color: #000000;"> (isChild (result, systemLoader))result </span><span style="color: #000000;">=</span><span style="color: #000000;"> systemLoader;<br /> </span><span style="color: #008080;">24</span> <span style="color: #0000ff;">return</span><span style="color: #000000;"> result;<br /> </span><span style="color: #008080;">25</span> <span style="color: #000000;">}<br /> </span><span style="color: #008080;">26</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">27</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">28</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">29</span> <span style="color: #000000;"><img src="http://www.tkk7.com/Images/dot.gif" alt="" /> more methods <img src="http://www.tkk7.com/Images/dot.gif" alt="" /><br /> </span><span style="color: #008080;">30</span> <span style="color: #000000;"><br /> </span><span style="color: #008080;">31</span> <span style="color: #000000;">} </span><span style="color: #008000;">//</span><span style="color: #008000;"> End of class<br /> </span><span style="color: #008080;">32</span> </div> <p><br /> 上面的逻辑比较单,如果当前ClassLoader和Context ClassLoader是父子关p,那就总选儿子,Ҏ委托原则Q这个很Ҏ理解?/p> <p>如果两hqQ选择正确的ClassLoader很重要,q行时不允许含糊。这U情况下Q我的代码选择Context ClassLoaderQ这是俺个h的经验之谈)Q当然也不要担心不能改变Q你能随便根据需要改变。一般而言QContext ClassLoader比较适合框架Q而Current ClassLoader在业务逻辑中用的更多?/p> <p>最后,查确保选中的ClassLoader不是System ClassLoader的parentQ一旦高于System ClassLoader Q请使用System ClassLoaderQ你的类部v在Ext路径下面Q就会出现这U情况)?/p> <p>h意,俺故意没x被蝲入资源的名称。Java XML API 成ؓjava 核心api的经历告诉我们,Ҏ资源名称qo是很不cool的idea。而且 我也没有ȝ认到底哪个ClassLoader被取得了Q因为只要清楚原理,q很Ҏ被推理出来。(哈哈Q俺是强淫)</p> <p>管讨论java 的ClassLoader不是一个很cool的话题(译者注Q当q不coolQ但是现在很coolQ,而且Java EE的ClassLoader{略发的依赖各U^台的升。如果这没有一个更好的设计的话Q将会变成一个大大的问题。不敢您是否同意俺的观点Q俺重你说话的权利Q所以请l俺分n您的意见l验?/p> <p>作者介l:</p> <p>Vladimir RoubtsovQ曾l用多U语a有超q?3q的~程l历Q恩 现在应该过15q了 hohoQ,95q开始接触javaQhoho 俺是99q看的第一本java书)。现在ؓTrilogy in Austin, Texas开发企业Y件?/p> <br /> <p><br /> </p> <p><!--more--></p> <p>译完了QMMD 译q是很麻烦的?XD ........</p> <p class="zoundry_bw_tags"> <!-- Tag links generated by Zoundry Blog Writer. Do not manually edit. http://www.zoundry.com --> <span id="nrlphjr" class="ztags"><span id="rbjfzbz" class="ztagspace">43 Things</span> : <a class="ztag" rel="tag">ClassLoader</a></span> </p> <img src ="http://www.tkk7.com/jackjhy/aggbug/204163.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jackjhy/" target="_blank">季失?/a> 2008-05-30 18:22 <a href="http://www.tkk7.com/jackjhy/archive/2008/05/30/204163.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ClassLoader的几个概c类和对象的解释http://www.tkk7.com/jackjhy/archive/2008/05/29/203927.html季失?/dc:creator>季失?/author>Thu, 29 May 2008 12:11:00 GMThttp://www.tkk7.com/jackjhy/archive/2008/05/29/203927.htmlhttp://www.tkk7.com/jackjhy/comments/203927.htmlhttp://www.tkk7.com/jackjhy/archive/2008/05/29/203927.html#Feedback1http://www.tkk7.com/jackjhy/comments/commentRss/203927.htmlhttp://www.tkk7.com/jackjhy/services/trackbacks/203927.html  

当JVMQJava虚拟机)启动Ӟ会Ş成由三个cd载器l成的初始类加蝲器层ơ结构:

        bootstrap classloader
                 |
        extension classloader
                 |
        system classloader

bootstrap classloader Q? 引导Q也UCؓ原始Q类加蝲器,它负责加载Java的核心类。在Sun的JVM中,在执行java的命令中使用-Xbootclasspath选项或? -D选项指定sun.boot.class.pathpȝ属性值可以指定附加的cR这个加载器的是非常Ҏ的,它实际上不是 java.lang.ClassLoader的子c,而是由JVM自n实现的。大家可以通过执行以下代码来获得bootstrap classloader加蝲了那些核心类库:
    URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();
    
for (int i = 0; i < urls.length; i++) {
      System.out.println(urls.toExternalForm());
    }

在我的计机上的l果为:
file:/C:/j2sdk1.4.1_01/jre/lib/endorsed/dom.jar
file:/C:/j2sdk1.4.1_01/jre/lib/endorsed/sax.jar
file:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xalan-2.3.1.jar
file:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xercesImpl-2.0.0.jar
file:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xml-apis.jar
file:/C:/j2sdk1.4.1_01/jre/lib/endorsed/xsltc.jar
file:/C:/j2sdk1.4.1_01/jre/lib/rt.jar
file:/C:/j2sdk1.4.1_01/jre/lib/i18n.jar
file:/C:/j2sdk1.4.1_01/jre/lib/sunrsasign.jar
file:/C:/j2sdk1.4.1_01/jre/lib/jsse.jar
file:/C:/j2sdk1.4.1_01/jre/lib/jce.jar
file:/C:/j2sdk1.4.1_01/jre/lib/charsets.jar
file:/C:/j2sdk1.4.1_01/jre/classes
q时大家知道了ؓ什么我们不需要在pȝ属性CLASSPATH中指定这些类库了吧,因ؓJVM在启动的时候就自动加蝲它们了?br />
extension classloader Q? 扩展cd载器Q它负责加蝲JRE的扩展目录(JAVA_HOME/jre/lib/ext或者由java.ext.dirspȝ属性指定的Q中JAR的类 包。这为引入除Java核心cM外的新功能提供了一个标准机制。因为默认的扩展目录Ҏ有从同一个JRE中启动的JVM都是通用的,所以放入这个目录的 JARcdҎ有的JVM和system classloader都是可见的。在q个实例上调用方法getParent()Lq回I值nullQ因为引导加载器bootstrap classloader不是一个真正的ClassLoader实例。所以当大家执行以下代码Ӟ

    System.out.println(System.getProperty(
"java.ext.dirs"));
    ClassLoader extensionClassloader
=ClassLoader.getSystemClassLoader().getParent();
    System.out.println(
"the parent of extension classloader : "+extensionClassloader.getParent());

l果为:
C:"j2sdk1.4.1_01"jre"lib"ext
the parent of extension classloader : null
extension classloader是system classloader的parentQ而bootstrap classloader是extension classloader的parentQ但它不是一个实际的classloaderQ所以ؓnull?br />
system classloader Q? pȝQ也UCؓ应用Q类加蝲器,它负责在JVM被启动时Q加载来自在命ojava中的-classpath或者java.class.pathpȝ属性或? CLASSPATH操作pȝ属性所指定的JARcd和类路径。总能通过静态方法ClassLoader.getSystemClassLoader()? 到该cd载器。如果没有特别指定,则用戯定义的Q何类加蝲器都该cd载器作ؓ它的父加载器。执行以下代码即可获得:
    System.out.println(System.getProperty("java.class.path"));
输出l果则ؓ用户在系l属性里面设|的CLASSPATH?br /> classloader 加蝲cȝ的是全盘负责委托机制。所谓全盘负责,x当一个classloader加蝲一个Class的时候,q个Class所依赖的和引用的所? Class也由q个classloader负责载入Q除非是昑ּ的用另外一个classloader载入Q委托机制则是先让parentQ父Q类加蝲? (而不是superQ它与parent classloadercM是承关p?LQ只有在parent找不到的时候才从自qc\径中d找。此外类加蝲q采用了cache机制Q也是如果 cache中保存了q个Classq接返回它Q如果没有才从文件中d和{换成ClassQƈ存入cacheQ这是Z么我们修改了Class但是? 重新启动JVM才能生效的原因?br />

每个ClassLoader加蝲Class的过E是Q?br /> 1.此Class是否载入q(卛_cache中是否有此ClassQ,如果有到8,如果没有?
2.如果parent classloader不存在(没有parentQ那parent一定是bootstrap classloader了)Q到4
3.hparent classloader载入Q如果成功到8Q不成功?
4.hjvm从bootstrap classloader中蝲入,如果成功?
5.LClass文gQ从与此classloader相关的类路径中寻找)。如果找不到则到7.
6.从文件中载入ClassQ到8.
7.抛出ClassNotFoundException.
8.q回Class.

其中5.6步我们可以通过覆盖ClassLoader的findClassҎ来实现自q载入{略。甚臌盖loadClassҎ来实现自q载入q程?br />
cd载器的顺序是Q?br /> ? 是bootstrap classloaderQ然后是extension classloaderQ最后才是system classloader。大家会发现加蝲的Class是重要的越在靠前面。这样做的原因是Z安全性的考虑Q试惛_果system classloader“亲自”加蝲了一个具有破坏性的“java.lang.System”cȝ后果吧。这U委托机制保证了用户即h一个这Lc, 也把它加入到了类路径中,但是它永q不会被载入Q因个类L由bootstrap classloader来加载的。大家可以执行一下以下的代码Q?br />     System.out.println(System.class.getClassLoader());
会看到l果是nullQ这p明java.lang.System是由bootstrap classloader加蝲的,因ؓbootstrap classloader不是一个真正的ClassLoader实例Q而是由JVM实现的,正如前面已经说过的?br />
下面p我们来看看JVM是如何来为我们来建立cd载器的结构的Q?br /> sun.misc.LauncherQ顾名思义Q当你执行java命o的时候,JVM会先使用bootstrap classloader载入q初始化一个LauncherQ执行下来代码:
   System.out.println("the Launcher's classloader is "+sun.misc.Launcher.getLauncher().getClass().getClassLoader());
l果为:
   the Launcher's classloader is null (因ؓ是用bootstrap classloader加蝲,所以class loader为null)
Launcher 会根据系l和命o讑֮初始化好class loaderl构QJVMq它来获得extension classloader和system classloader,q蝲入所有的需要蝲入的ClassQ最后执行java命o指定的带有静态的mainҎ的Class。extension classloader实际上是sun.misc.Launcher$ExtClassLoadercȝ一个实例,system classloader实际上是sun.misc.Launcher$AppClassLoadercȝ一个实例。ƈ且都? java.net.URLClassLoader的子cR?br />
让我们来看看Launcher初试化的q程的部分代码?br />
Launcher的部分代码:
 1 public class Launcher  {
 2     public Launcher() {
 3         ExtClassLoader extclassloader;
 4         try {
 5             //初始化extension classloader
 6             extclassloader = ExtClassLoader.getExtClassLoader();
 7         } catch(IOException ioexception) {
 8             throw new InternalError("Could not create extension class loader");
 9         }
10         try {
11             //初始化system classloaderQparent是extension classloader
12             loader = AppClassLoader.getAppClassLoader(extclassloader);
13         } catch(IOException ioexception1) {
14             throw new InternalError("Could not create application class loader");
15         }
16         //system classloader讄成当前线E的context classloaderQ将在后面加以介l)
17         Thread.currentThread().setContextClassLoader(loader);
18         
19     }
20     public ClassLoader getClassLoader() {
21         //q回system classloader
22         return loader;
23     }
24 }
25 

extension classloader的部分代码:
 1 static class Launcher$ExtClassLoader extends URLClassLoader {
 2 
 3     public static Launcher$ExtClassLoader getExtClassLoader()
 4         throws IOException
 5     {
 6         File afile[] = getExtDirs();
 7         return (Launcher$ExtClassLoader)AccessController.doPrivileged(new Launcher$1(afile));
 8     }
 9    private static File[] getExtDirs() {
10         //获得pȝ属?#8220;java.ext.dirs”
11         String s = System.getProperty("java.ext.dirs");
12         File afile[];
13         if(s != null) {
14             StringTokenizer stringtokenizer = new StringTokenizer(s, File.pathSeparator);
15             int i = stringtokenizer.countTokens();
16             afile = new File;
17             for(int j = 0; j < i; j++)
18                 afile[j] = new File(stringtokenizer.nextToken());
19 
20         } else {
21             afile = new File[0];
22         }
23         return afile;
24     }
25 }


system classloader的部分代码:
 1 static class Launcher$AppClassLoader extends URLClassLoader
 2 {
 3 
 4     public static ClassLoader getAppClassLoader(ClassLoader classloader)
 5         throws IOException
 6     {
 7         //获得pȝ属?#8220;java.class.path”
 8         String s = System.getProperty("java.class.path");
 9         File afile[] = s != null ? Launcher.access$200(s) : new File[0];
10         return (Launcher$AppClassLoader)AccessController.doPrivileged(new Launcher$2(s, afile, classloader));
11     }
12 }


? 了源代码大家清楚了吧,extension classloader是用系l属?#8220;java.ext.dirs”讄cL索\径的Qƈ且没有parent。system classloader是用系l属?#8220;java.class.path”讄cL索\径的Qƈ且有一个parent classloader。Launcher初始化extension classloaderQsystem classloaderQƈsystem classloader讄成ؓcontext classloaderQ但是仅仅返回system classloaderlJVM?br />
q里怎么又出来一个context classloader呢?它有什么用呢?我们在徏立一个线EThread的时候,可以个线E通过setContextClassLoaderҎ? 指定一个合适的classloader作ؓq个U程的context classloaderQ当此线E运行的时候,我们可以通过getContextClassLoaderҎ来获得此context classloaderQ就可以用它来蝲入我们所需要的Class。默认的是system classloader。利用这个特性,我们可以“打破”classloader委托机制了,父classloader可以获得当前U程的context classloaderQ而这个context classloader可以是它的子classloader或者其他的classloaderQ那么父classloader可以从其获得所需? ClassQ这打破了只能向父classloaderh的限制了。这个机制可以满_我们的classpath是在q行时才定,q由定制? classloader加蝲的时?由system classloader(卛_jvm classpath?加蝲的class可以通过context classloader获得定制的classloaderq加载入特定的class(通常是抽象类和接?定制的classloader中是其实?,? 如web应用中的servlet是用这U机制加载的.


好了Q现在我们了解了classloader的结构和工作原理Q那么我? 如何实现在运行时的动态蝲入和更新呢?只要我们能够动态改变类搜烦路径和清除classloader的cache中已l蝲入的Classp了,有两个方 案,一是我们承一个classloaderQ覆盖loadclassҎQ动态的LClass文gq用defineClassҎ来;另一个则非常 单实用,只要重新使用一个新的类搜烦路径来new一个classloaderp了,q样xCcL索\径以便来载入新的ClassQ也重新生成了一 个空白的cache(当然,cL索\径不一定必L?。噢Q太好了Q我们几乎不用做什么工作,java.netURLClassLoader正是一个符 合我们要求的classloaderQ我们可以直接用或者承它可以了Q?br />
q是j2se1.4 API的doc中URLClassLoader的两个构造器的描qͼ
URLClassLoader(URL[] urls)
          Constructs a new URLClassLoader for the specified URLs using the default delegation parent ClassLoader.
URLClassLoader(URL[] urls, ClassLoader parent)
          Constructs a new URLClassLoader for the given URLs.
其中URL[] urls是我们要设|的cL索\径,parent是q个classloader的parent classloaderQ默认的是system classloader?br />

好,现在我们能够动态的载入Class了,q样我们可以利用newInstanceҎ来获得一个Object。但我们如何此Object造型呢?可以此Object造型成它本n的Class吗?

首先让我们来分析一下java源文件的~译Q运行吧Qjavac命o是调?#8220;JAVA_HOME/lib/tools.jar”中的“com.sun.tools.javac.Main”的compileҎ来编译:

    
public static int compile(String as[]);

    
public static int compile(String as[], PrintWriter printwriter);

q回0表示~译成功Q字W串数组as则是我们用javac命o~译时的参数Q以I格划分。例如:
javac -classpath c:"foo"bar.jar;. -d c:" c:"Some.java
? 字符串数las为{"-classpath","c:""foo""bar.jar;.","-d","c:""","c:""Some.java"}Q? 如果带有PrintWriter参数Q则会把~译信息出到q个指定的printWriter中。默认的输出是System.err?br />
其中 Main是由JVM使用Launcher初始化的system classloader载入的,Ҏ全盘负责原则Q编译器在解析这个java源文件时所发现的它所依赖和引用的所有Class也将由system classloader载入Q如果system classloader不能载入某个ClassӞ~译器将抛出一?#8220;cannot resolve symbol”错误?br />
所以首先编译就通不q,也就是编译器无法~译一个引用了不在CLASSPATH中的未知Class的java源文Ӟ而由于拼写错误或者没有把所需cd攑ֈCLASSPATH中,大家一定经常看到这?#8220;cannot resolve symbol”q个~译错误吧!

? ơ,是我们把这个Class攑ֈ~译路径中,成功的进行了~译Q然后在q行的时候不把它攑օ到CLASSPATH中而利用我们自q classloader来动态蝲入这个ClassQ这时候也会出?#8220;java.lang.NoClassDefFoundError”的违例,Z么呢Q?br />
? 们再来分析一下,首先调用q个造型语句的可执行的Class一定是由JVM使用Launcher初始化的system classloader载入的,Ҏ全盘负责原则Q当我们q行造型的时候,JVM也会使用system classloader来尝试蝲入这个Class来对实例q行造型Q自然在system classloaderL不到q个Class时就会抛?#8220;java.lang.NoClassDefFoundError”的违例?br />
OKQ? 现在让我们来ȝ一下,java文g的编译和Class的蝲入执行,都是使用Launcher初始化的system classloader作ؓc蝲入器的,我们无法动态的改变system classloaderQ更无法让JVM使用我们自己的classloader来替换system classloaderQ根据全盘负责原则,限制了~译和运行时Q我们无法直接显式的使用一个system classloaderL不到的ClassQ即我们只能使用Java核心cdQ扩展类库和CLASSPATH中的cd中的Class?br />
q? 不死心!再尝试一下这U情况,我们把这个Class也放入到CLASSPATH中,让system classloader能够识别和蝲入。然后我们通过自己的classloader来从指定的class文g中蝲入这个ClassQ不能够委托 parent载入Q因样会被system classloader从CLASSPATH中将其蝲入)Q然后实例化一个ObjectQƈ造型成这个ClassQ这样JVM也识别这个ClassQ因? system classloader能够定位和蝲入这个Class从CLASSPATH中)Q蝲入的也不是CLASSPATH中的q个ClassQ而是? CLASSPATH外动态蝲入的Q这h行了吧Q十分不q的是,q时会出?#8220;java.lang.ClassCastException”q例?br />
? 什么呢Q我们也来分析一下,不错Q我们虽然从CLASSPATH外用我们自qclassloader动态蝲入了q个ClassQ但它的实例造型的时 候是JVM会用system classloader来再ơ蝲入这个ClassQƈ试用我们的自己的classloader载入的Class的一个实例造型为system classloader载入的这个ClassQ另外的一个)。大家发C么问题了吗?也就是我们尝试将从一个classloader载入的Class的一 个实例造型为另外一个classloader载入的ClassQ虽然这两个Class的名字一P甚至是从同一个class文g中蝲入。但不幸的是JVM 却认个两个Class是不同的Q即JVM认ؓ不同的classloader载入的相同的名字的ClassQ即使是从同一个class文g中蝲入的Q是 不同的!q样做的原因我想大概也是主要Z安全性考虑Q这样就保证所有的核心Javac都是system classloader载入的,我们无法用自qclassloader载入的相同名字的Class的实例来替换它们的实例?br />
看到q里Q聪明的读者一定想C该如何动态蝲入我们的ClassQ实例化Q造型q调用了吧!

? 是利用面向对象的基本特性之一的多形性。我们把我们动态蝲入的Class的实例造型成它的一个system classloader所能识别的父类p了!q是Z么呢Q我们还是要再来分析一ơ。当我们用我们自qclassloader来动态蝲入这我们只要? q个Class的时候,发现它有一个父cClassQ在载入它之前JVM先会载入q个父类ClassQ这个父cClass是system classloader所能识别的Q根据委托机Ӟ它将由system classloader载入Q然后我们的classloader再蝲入这个ClassQ创Z个实例,造型个父cClassQ注意了Q造型成这个父c? Class的时候(也就是上溯)是面向对象的java语言所允许的ƈ且JVM也支持的QJVM׃用system classloader再次载入q个父类ClassQ然后将此实例造型个父cClass。大家可以从q个q程发现q个父类Class都是? system classloader载入的,也就是同一个class loader载入的同一个ClassQ所以造型的时候不会出CQ何异常。而根据多形性,调用q个父类的方法时Q真正执行的是这个ClassQ非父类 ClassQ的覆盖了父cL法的Ҏ。这些方法中也可以引用system classloader不能识别的ClassQ因为根据全盘负责原则,只要载入q个Class的classloaderx们自己定义的 classloader能够定位和蝲入这些Classp了?br />
q样我们可以事先定义好一l接口或者基cdƈ攑օCLASSPATH中,? 后在执行的时候动态的载入实现或者承了q些接口或基cȝ子类。还不明白吗Q让我们来想一想Servlet吧,web application server能够载入Ml承了Servlet的Classq正的执行它们Q不它实际的Class是什么,是都把它们实例化成Z个Servlet ClassQ然后执行Servlet的initQdoPostQdoGet和destroy{方法的,而不这个Servlet是从web- inf/lib和web-inf/classes下由system classloader的子classloader(卛_制的classloader)动态蝲入。说了这么多希望大家都明白了。在applet,ejb{? 容器?都是采用了这U机?

对于以上各种情况Q希望大家实际编写一些example来实验一下?br />
最后我再说点别 的,classloader虽然UCؓcd载器Q但q不意味着只能用来加蝲ClassQ我们还可以利用它也获得囄Q音频文件等资源的URLQ当Ӟq些? 源必dCLASSPATH中的jarcd中或目录下。我们来看API的doc中关于ClassLoader的两个寻找资源和Class的方法描q吧Q?br /> public URL getResource(String name)
用指定的名字来查找资源,一个资源是一些能够被class代码讉K的在某种E度上依赖于代码位置的数据(囄Q音频,文本{等Q?br />                 一个资源的名字是以'/'号分隔确定资源的路径名的?br />                 q个Ҏ先hparent classloader搜烦资源Q如果没有parentQ则会在内置在虚拟机中的classloaderQ即bootstrap classloaderQ的路径中搜索。如果失败,q个Ҏ调用findResource(String)来寻找资源?br /> public static URL getSystemResource(String name)
                从用来蝲入类的搜索\径中查找一个指定名字的资源。这个方法用system class loader来定位资源。即相当于ClassLoader.getSystemClassLoader().getResource(name)?br />
例如Q?br />     System.out.println(ClassLoader.getSystemResource("java/lang/String.class"));
的结果ؓQ?br />     jar:file:/C:/j2sdk1.4.1_01/jre/lib/rt.jar!/java/lang/String.class
表明String.class文g在rt.jar的java/lang目录中?br /> 因此我们可以图片等资源随同Class一同打包到jarcd中(当然Q也可单独打包这些资源)q添加它们到class loader的搜索\径中Q我们就可以无需兛_q些资源的具体位|,让class loader来帮我们L了!

以上是{自bea论坛的一文章,作者不清楚Q估计是bea内部的大牛。是值得Z礼膜拜的神一般的存在 XD



最?附上自己的几点理?br />
bootstrap classloader  -------  对应jvm中某c++写的dllc?br /> Extenson ClassLoader ---------对应内部cExtClassLoader
System ClassLoader  ---------对应内部cAppClassLoader
Custom ClassLoader  ----------对应MURLClassLoader的子c(你也可以l承SecureClassLoader或者更加nb一?直接l承ClassLoaderQ这L话你也是一般的存在?XDQ?br />

以上四种classloder按照从上C的顺序,依次Z一个的parent

q个W一概念

W二个概忉|几个有关的classloader的类

           抽象c?ClassLoader
                  |
            SecureClassLoader
                   |
            URLClassloader
             |           |                
 sun的ExtClassLoader   sun的AppClassLoader
以上的类之间是承关p,与第一个概念说的parent是两回事情,需要小心?br />
W三个概忉|Thread的ContextClassLoader
其实从Context的名U就可以看出来,q只是一个用以存储Q何classloader引用的时存储空_与classloader的层ơ没有Q何关pR?br />

W四 是如何实现自己的classloader了,本来是要译另外一文章Find a way out of the ClassLoader maze
不过今天旉都花在《小夫妻天天恶战》这神文上?XD 强烈推荐M和俺一h望彪悍h生的朋友都去看看

译明天补上Q浪Ҏ间是可ȝ XD

匉KQ晚上还有朋友推荐的 《lie with me》(与我同眠Q要看。XD




]]>
关于extends ?constructor的默认实C覆盖{略http://www.tkk7.com/jackjhy/archive/2008/05/28/203416.html季失?/dc:creator>季失?/author>Wed, 28 May 2008 02:44:00 GMThttp://www.tkk7.com/jackjhy/archive/2008/05/28/203416.htmlhttp://www.tkk7.com/jackjhy/comments/203416.htmlhttp://www.tkk7.com/jackjhy/archive/2008/05/28/203416.html#Feedback10http://www.tkk7.com/jackjhy/comments/commentRss/203416.htmlhttp://www.tkk7.com/jackjhy/services/trackbacks/203416.html今天在TSS上又看到有h讨论java多承的问题Q是惌vq个话题的原因。^_^


java中Q何类都默认?Java.lang.ObjectQ除非被另一个承覆?override)Qhoho Z直这么称呼override的,感觉更加贴切一些?br /> L以下代码:

package org.myth.test;

public class SuperSon{
    
    SuperSon(){
        System.out.println(
"this is super son");
    }

}

对于~译器来_q段代码会被首先补全为:

package org.myth.test;

public class SuperSon extends Object{
    
    SuperSon(){
        System.out.println(
"this is super son");
    }

}

对待M一个类Q编译器会去查extends关键字,如果没有Q编译器会默认添加extens Object

extends Object是一D默认隐藏的代码Q同样在Constructor中,也有一D默认隐藏的代码?br />
package org.myth.test;

public class SuperSon extends Object{
    
    SuperSon(){
        
super();//q就是一D默认隐藏代?/span>
        System.out.println("this is super son");
    }

    //
整个构造方法也是一D默认隐藏代?/span>

}

如同~译cL~译器回L查extends关键字一P~译器会首先查是否存在constructorQ如果没?默认增加ClassName()构造方法?br /> 在构造方法内部,~译器会查第一行代码是否ؓsuper构造方法,如果不是Q默认添加super()

q个是Z?new一个对象的时候,首先调用的是父类的构造方法?br />
一个错误代码示例:
package org.myth.test;

public class SuperMan {
    
    SuperMan(String s){
        System.out.println(
"this is super man");
    }

}



package org.myth.test;

public class SuperSon extends SuperMan{
    
    SuperSon(){
        System.out.println(
"this is super son");
    }

}


嘿嘿 W一文?br />

]]>
Test Bloghttp://www.tkk7.com/jackjhy/archive/2008/05/26/202995.html季失?/dc:creator>季失?/author>Mon, 26 May 2008 09:35:00 GMThttp://www.tkk7.com/jackjhy/archive/2008/05/26/202995.html 初次使用blogjava





]]>
վ֩ģ壺 һһͰһƵ| ŷŷɫ| ߹ۿ| aëƬվ| ѹۿ| ӰԺMV߹ۿƵ| 91Ѳˬ˿| Ƶ߹ۿһ| ĻƷþ| һɫݳѾƷվ| ޳aƬ߿| Ƶ97| ƷѲ| ޾Ʒ޿һ| һƵѹۿ| ޹Ʒþһ| ޾Ʒͷ| AëƬav| ޹Ʒxo߹ۿ| ëƬƵa| Ʒרţţ| Ʒ1024Ƶ| mate20pro鶹| ˬִ̼߳Ƶ | 鵺̳ƷƵվ | ׾Ʒһ| ۺϹһ| ҹ׾糡| ޾Ʒ߹ۿ| ޾ƷƷԲۿ| ˳7777| ޹91Ʒר| Ƶ߹ۿ| 77777_ҹþö| վvƬ㽶| Ůվ߹ۿƵѵ| ޴ɫ߹ۿ| ?VþþƷ| պAVһ| ޹Ʒľþþ| 91ѽ|