sharajava

          2006年7月27日 #

          類的動(dòng)態(tài)加載

          : 調(diào)用 Class.forName() ClassLoader.loadClass() 的區(qū)別在什么地方 ?

          : 這兩方法都是通過一個(gè)給定的類名去定位和加載這個(gè)類名對(duì)應(yīng)的 java.long.Class 類對(duì)象 . 盡管如此 , 它們的在行為方式上還是有區(qū)別的 .

          ????????? 用哪個(gè) java.lang.ClassLoader 進(jìn)行加載

          ????????? 返回的 Class 對(duì)象是否被初始化

          Class.forName(String) 方法(只有一個(gè)參數(shù)), 使用調(diào)用者的類加載器來加載, 也就是用加載了調(diào)用forName方法的代碼的那個(gè)類加載器. 相應(yīng)的, ClassLoader.loadClass()方法是一個(gè)實(shí)例方法(非靜態(tài)方法), 調(diào)用時(shí)需要自己指定類加載器, 那么這個(gè)類加載器就可能是也可能不是加載調(diào)用代碼的類加載器. 如果用特定的類加載器來加載類在你的設(shè)計(jì)中占有比較重要的地位, 你就應(yīng)該調(diào)用ClassLoader.loadClass(String)方法或Class.forName(String, boolean, ClassLoader)方法.

          ??? 另外, Class.forName()方法對(duì)加載的類對(duì)象進(jìn)行初始化. 可見的效果就是類中靜態(tài)初始化段及字節(jié)碼中對(duì)所有靜態(tài)成員的初始工作的執(zhí)行(這個(gè)過程在類的所有父類中遞歸地調(diào)用). 這點(diǎn)就與ClassLoader.loadClass()不同. ClassLoader.loadClass()加載的類對(duì)象是在第一次被調(diào)用時(shí)才進(jìn)行初始化的.

          ??? 你可以利用上述的差異. 比如,要加載一個(gè)靜態(tài)初始化開銷很大的類, 你就可以選擇提前加載該類(以確保它在classpath), 但不進(jìn)行初始化, 直到第一次使用該類的域或方法時(shí)才進(jìn)行初始化.

          ??? 最常用的是Class.forName(String, boolean, ClassLoader). 設(shè)置第二個(gè)參數(shù)為false即推遲初始化, 第三個(gè)參數(shù)指定要用來進(jìn)行加載的類加載器. 我建議為了最大的靈活性使用這個(gè)方法.

          類初始化錯(cuò)誤是難處理的

          ??? 成功地加載了類, 并不意味著就不會(huì)有其它問題. 靜態(tài)初始化代碼可以拋出異常, 異常被包裝到java.long.ExceptionInInitializerError的實(shí)例中. 異常拋出后, 這個(gè)類將不可用. 這樣, 如果你需要在代碼中處理這些錯(cuò)誤, 你就應(yīng)該調(diào)用進(jìn)行初始化的Class.forName()方法.

          ??? 但進(jìn)一步說, 如果你要處理ExceptionInInitializerError并試圖從錯(cuò)誤中恢復(fù), 很可能不如你想象的那樣正常工作. 請(qǐng)看下面的示例代碼:


          public ? class ?Main
          {
          ????
          public ? static ? void ?main?(String?[]?args)? throws ?Exception
          ????{
          ????????
          for ?( int ?repeat?=?0;?repeat?<?3;?++?repeat)
          ????????{
          ????????????
          try
          ????????????{
          ????????????????
          //?"Real"?name?for?X?is?outer?class?name+$+nested?class?name:
          ????????????????Class.forName?("Main$X");
          ????????????}
          ????????????
          catch ?(Throwable?t)
          ????????????{
          ????????????????System.out.println?("load?attempt?#"?+?repeat?+?":");
          ????????????????t.printStackTrace?(System.out);
          ????????????}
          ????????}
          ????}

          ????
          private ? static ? class ?X
          ????{
          ????????
          static
          ????????{
          ????????????
          if ?(++?s_count?==?1)
          ????????????????
          throw ? new ?RuntimeException?("failing?static?initializer");
          ????????}
          ????????
          ????}?
          //?End?of?nested?class

          ????
          private ? static ? int ?s_count;

          }?
          //?End?of?class

          ??? 上面的代碼3次嘗試加載一個(gè)內(nèi)部類X, 即便是X的靜態(tài)初始化只在每一次加載時(shí)失敗, 3次加載都拋出了異常.

          >java Main
          load attempt #0:
          java.lang.ExceptionInInitializerError
          ????????at java.lang.Class.forName0(Native Method)
          ????????at java.lang.Class.forName(Class.java:140)
          ????????at Main.main(Main.java:17)
          Caused by: java.lang.RuntimeException: failing static initializer...
          ????????at Main$X.<clinit>(Main.java:40)
          ????????... 3 more
          load attempt #1:
          java.lang.NoClassDefFoundError
          ????????at java.lang.Class.forName0(Native Method)
          ????????at java.lang.Class.forName(Class.java:140)
          ????????at Main.main(Main.java:17)
          load attempt #2:
          java.lang.NoClassDefFoundError
          ????????at java.lang.Class.forName0(Native Method)
          ????????at java.lang.Class.forName(Class.java:140)
          ????????at Main.main(Main.java:17)

          ??? 有點(diǎn)令人吃驚的時(shí), 在第2, 3次進(jìn)行類加載時(shí), 拋出的異常竟然是java.lang.NoClassDefFoundError. 這里發(fā)生的事情是, 第一次加載后(在進(jìn)行初始化之前), JVM發(fā)現(xiàn)X已經(jīng)被加載, 而這個(gè)X的類實(shí)例在加載它的類加載器被垃圾回收之前是不會(huì)被卸載的. 所以這之后的對(duì)Class.forName()的調(diào)用時(shí), JVM不會(huì)再嘗試進(jìn)行初始化的工作, 但是, 更令人不解的是, 拋出一個(gè)NoClassDefFoundError.

          ??? 卸載這樣的類的方法是丟棄原來加載該類的類加載器實(shí)例并重新創(chuàng)建一個(gè). 當(dāng)然, 這只能是在你使用了Class.forName(String, boolean, ClassLoader)這個(gè)3參數(shù)的方法的時(shí)候才能辦到.

          隱藏的 Class.forName() 方法

          ??? 你一定用過JavaX.class的語法去獲取一個(gè)在編譯器就知道名字的類對(duì)象實(shí)例. 在字節(jié)碼的層次上, 這一點(diǎn)是如何實(shí)現(xiàn)的就不被人熟知了. 不同的編譯器有不同的實(shí)例細(xì)節(jié), 但共同點(diǎn)是, 所有編譯器所相應(yīng)產(chǎn)生的代碼都是調(diào)用的Class.forName(String)這一個(gè)參數(shù)的方法. 比如J2SE 1.4.1javac就把Class cls = X.class; 翻譯成如下等價(jià)的形式:

          ?
          ????????
          //?This?is?how?"Class?cls?=?X.class"?is?transformed:
          ???????? if ?( class $Main$X?==? null )
          ????????{
          ????????????
          class $Main$X?=? class $?("Main$X");
          ????????}
          ????????Class?cls?=?
          class $Main$X;

          ????

          ????
          static ?Class? class $?(String?s)
          ????{
          ????????
          try
          ????????{
          ????????????
          return ?Class.forName?(s);
          ????????}
          ????????
          catch ?(ClassNotFoundException?e)
          ????????{
          ????????????
          throw ? new ?NoClassDefFoundError?(e.getMessage());
          ????????}
          ????}

          ????
          static ?Class? class $Main$X;? //?A?synthetic?field?created?by?the?compiler

          Sun javac 開個(gè)玩笑

          從上面的例子你可以看到, 編譯器調(diào)用Class.forName()方法加載類對(duì)象, 并將其緩存到一個(gè)包內(nèi)可見的靜態(tài)變量中. 這種令人費(fèi)解的實(shí)現(xiàn)方式的可能是因?yàn)樵谠缙诎姹镜?span lang="EN-US">Java, 這種X.class的語法還未被支持, so the feature was added on top of the Java 1.0 byte-code instruction set.(???)

          利用這一點(diǎn), 你可以在編譯器的開銷上做一些有趣的事情. J2SE 1.3.1編譯下面的代碼片段:

          public ? class ?Main
          {
          ????
          public ? static ? void ?main?(String?[]?args)? throws ?Exception
          ????{
          ????????System.out.println?("String?class:?"?+?String.
          class );
          ????????
          class $java$lang$String?=? int . class ;
          ????????System.out.println?("String?class:?"?+?String.
          class );
          ????}
          ????
          ????
          static ?Class? class $java$lang$String;

          }?
          //?End?of?class

          運(yùn)行它, 你會(huì)得到下面這個(gè)很荒謬的輸出結(jié)果:

          >java Main

          String class: class java.lang.String

          String class: int

          J2SE 1.4.1, 上面的代碼將不能被編譯通過, 但你仍然可以用反射的方式戲弄它:

          public ? static ? void ?main?(String?[]?args)? throws ?Exception
          ????{
          ????????System.out.println?("String?class:?"?+?String.
          class );
          ????????Main.
          class .getDeclaredField?("class$java$lang$String").set?( null ,? int . class );
          ????????System.out.println?("String?class:?"?+?String.
          class );
          ????}

          ?

          ??? 綜上所述, 下次你再調(diào)用Class.forName()方法時(shí), 你應(yīng)該知道它的局限性可選的替代方案了.

          ?

          ?

          posted @ 2006-07-27 09:06 sharajava 閱讀(2160) | 評(píng)論 (0)編輯 收藏

          2006年7月25日 #

          JBoss MBean服務(wù)加載過程

          http://www.aygfsteel.com/images/blogjava_net/sharajava/13416/o_start-jboss-mbean-service.JPG?

          ?

          1.????? 前綴1.1的方法, 代表加載和解析XML服務(wù)描述文件的過程.

          2.????? 前綴1.2的方法, 代表對(duì)XML服務(wù)描述文件中類路徑條目的處理. 這個(gè)過程創(chuàng)建獨(dú)立的部署, 使得jar和類目錄對(duì)于相應(yīng)的統(tǒng)一類加載器(UnifiedClassLoader)可用. 這個(gè)UnifiedClassLoader是注冊(cè)到統(tǒng)一的類加載器倉(cāng)庫(kù)中的.

          3.????? 前綴1.3的方法, 代表處理服務(wù)描述文件中定義的本地目錄條目的過程. 這個(gè)過程把在路徑屬性中指定的SAR相關(guān)條目復(fù)制一份到server/<config>/db目錄下.

          4.????? 方法1.4, 代表對(duì)已經(jīng)部署的服務(wù)中嵌套的可部單元的部署過程. 子部署項(xiàng)目被創(chuàng)建并被加入到服務(wù)部署信息的子部署項(xiàng)列表中.

          5.????? 方法2.1, SAR部署單元相應(yīng)的UnifiedClassLoader(本身也是MBean)被注冊(cè)到MBean Server, 這樣它就可以被用來加載SAR中的MBean.

          6.????? 方法2.2, 創(chuàng)建XML服務(wù)描述文件中定義的每個(gè)MBean并用描述文件中給定的值初始化其屬性. 這些工作通過調(diào)用ServiceControllerinstall(Element, ObjectName)方法來完成的.

          7.????? 方法2.4.1, 對(duì)于前面步驟中創(chuàng)建好的每個(gè)MBean實(shí)例, 獲取其JMX對(duì)象名并由ServiceController處理服務(wù)生命周期中的create步驟. ServiceController處理MBean服務(wù)的依賴關(guān)系, 只有當(dāng)所有依賴都滿足時(shí), create方法才會(huì)被調(diào)用.

          8.????? 前綴3.1的方法, 代表MBean實(shí)例的起動(dòng)過程. 對(duì)于創(chuàng)建好的每個(gè)MBean實(shí)例, 獲取其JMX對(duì)象名并由ServiceController處理服務(wù)生命周期中的start步驟. ServiceController處理MBean服務(wù)的依賴關(guān)系, 只有當(dāng)所有依賴都滿足時(shí), start方法才會(huì)被調(diào)用.

          posted @ 2006-07-25 11:18 sharajava 閱讀(1928) | 評(píng)論 (0)編輯 收藏

          走出ClassLoader迷局

          : 我什么時(shí)候應(yīng)該使用 Thread.getContextClassLoader()?

          : 這個(gè)問題經(jīng)常出現(xiàn)在編寫框架代碼 , 需要?jiǎng)討B(tài)加載很多類和資源的時(shí)候 . 通常當(dāng)你需要?jiǎng)討B(tài)加載資源的時(shí)候 , 你至少有三個(gè) ClassLoader 可以選擇 :

          2??????? 系統(tǒng)類加載器或叫作應(yīng)用類加載器 (system classloader or application classloader)

          2??????? 當(dāng)前類加載器

          2??????? 當(dāng)前線程類加載器

          上面的問題指的是最后一種類加載器 . 哪種類加載器是正確的選擇呢 ?

          第一種選擇可以很容易地排除 : 系統(tǒng)類加載器 (system classloader). 這個(gè)類加載器處理 -classpath 下的類加載工作 , 可以通過 ClassLoader.getSystemClassLoader() 方法調(diào)用 . ClassLoader 下所有的 getSystemXXX() 的靜態(tài)方法都是通過這個(gè)方法定義的 . 在你的代碼中 , 你應(yīng)該盡量少地調(diào)用這個(gè)方法 , 以其它的類加載器作為代理 . 否則你的代碼將只能工作在簡(jiǎn)單的命令行應(yīng)用中 , 這個(gè)時(shí)候系統(tǒng)類加載器 (system classloader) JVM 最后創(chuàng)建的類加載器 . 一但你把代碼移到 EJB, Web 應(yīng)用或 Java Web Start 應(yīng)用中 , 一定會(huì)出問題 .

          ????? 所以我們來看第二種選擇 : 當(dāng)前上下文環(huán)境下的類加載器 . 根據(jù)定義 , 當(dāng)前類加載器就是你當(dāng)前方法所屬的類的加載器 . 在運(yùn)行時(shí)類之間動(dòng)態(tài)聯(lián)編 , 及調(diào)用 Class.forName,() Class.getResource() 等類似方法時(shí) , 這個(gè)類加載器會(huì)被隱含地使用 . It is also used by syntactic constructs like X.class class literals.

          ??? 線程上下文類型加載器是在Java 2平臺(tái)上被引入的. 每一個(gè)線程都有一個(gè)類加載器與之對(duì)應(yīng)(除非這個(gè)線程是被本地代碼創(chuàng)建的). 這個(gè)類加載器是通過Thread.setContextClassLoaser()方法設(shè)置的. 如果你不在線程構(gòu)造后調(diào)用這個(gè)方法, 這個(gè)線程將從它的父線程中繼承相應(yīng)的上下文類加載器. 如果在整個(gè)應(yīng)用中你不做任何特殊設(shè)置, 所有的線程將都以系統(tǒng)類加載器(system classloader)作為自己的線程上下文類加載器. 自從WebJ2EE應(yīng)用服務(wù)器使用成熟的類加載器機(jī)制來實(shí)現(xiàn)諸如JNDI, 線程池, 組件熱部署等功能以來, 這種在整個(gè)應(yīng)用中不做任何線程類加載器設(shè)置的情況就很少了.

          ??? 為什么線程上下文類加載器存在于如此重要的位置呢? 這個(gè)概念在J2SE中的引入并不引人注目. 很多開發(fā)人員對(duì)這一概念迷惑的原因是Sun公司在這方面缺乏適當(dāng)?shù)闹敢臀臋n.

          ??? 事實(shí)上, 上下文類加載器提供了類加載機(jī)制的后門, 這一點(diǎn)也在J2SE中被引入了. 通常, JVM中的所有類加載器被組織成了有繼承層次的結(jié)構(gòu), 每一個(gè)類加載器(除了引導(dǎo)JVM的原始類加載器)都有一個(gè)父加載器. 每當(dāng)被請(qǐng)示加載類時(shí), 類加載器都會(huì)首先請(qǐng)求其父類加載器, 只有當(dāng)父類加載器不能加載時(shí), 才會(huì)自己進(jìn)行類加載.

          ?? 有時(shí)候這種類加載的順序安排不能正常工作, 通常當(dāng)必須動(dòng)態(tài)加載應(yīng)用程序開發(fā)人員提供的資源的時(shí)候. JNDI為例: 它的內(nèi)容(J2SE1.3開始)就在rt.jar中的引導(dǎo)類中實(shí)現(xiàn)了, 但是這些JNDI核心類需要?jiǎng)討B(tài)加載由獨(dú)立廠商實(shí)現(xiàn)并部署在應(yīng)用程序的classpath下的JNDI提供者. 這種情況就要求一個(gè)父classloader(本例, 就是引導(dǎo)類加載器)去加載對(duì)于它其中一個(gè)子classloader(本例, 系統(tǒng)類加載器)可見的類. 這時(shí)通常的類加載代理機(jī)制不能實(shí)現(xiàn)這個(gè)要求. 解決的辦法(workaround)就是, JNDI核心類使用當(dāng)前線程上下文的類加載器, 這樣, 就基本的類加載代理機(jī)制的相反方向建立了一條有效的途徑.

          ??? 另外, 上面一段可能讓你想起一些其它的事情: XML解析Java API(JAXP). 是的, 當(dāng)JAXP只是J2SE的擴(kuò)展進(jìn), 它很自然地用當(dāng)前類加載器來引導(dǎo)解析器的實(shí)現(xiàn). 而當(dāng)JAXP被加入到J2SE1.4的核心類庫(kù)中時(shí), 它的類加載也就改成了用當(dāng)前線程類加載器, JNDI的情況完全類似(也使很多程序員很迷惑). 明白為什么我說來自Sun的指導(dǎo)很缺乏了吧?

          ?? 在以上的介紹之后, 我們來看關(guān)鍵問題: 這兩種選擇(當(dāng)前類加載器和當(dāng)前線程類加載器)都不是在所有環(huán)境下都適用. 有些人認(rèn)為當(dāng)前線程類加載器應(yīng)該成為新的標(biāo)準(zhǔn)策略. 但是, 如果這樣, 當(dāng)多個(gè)線程通過共享數(shù)據(jù)進(jìn)行交互的時(shí), 將會(huì)呈現(xiàn)出一幅極其復(fù)雜的類加載的畫面, 除非它們?nèi)渴褂昧送粋€(gè)上下文的類加載器. 進(jìn)一步說, 在某些遺留下來的解決方案中, 委派到當(dāng)前類加載器的方法已經(jīng)是標(biāo)準(zhǔn). 比如對(duì)Class.forName(String)的直接調(diào)用(這也是我為什么推薦盡量避免對(duì)這個(gè)方法進(jìn)行調(diào)用的原因). 即使你努力去只調(diào)用上下文相關(guān)的類加載器, 仍然會(huì)有一些代碼會(huì)不由你控制. 這種不受控制的類加載委派機(jī)制是混入是很危險(xiǎn)的.

          ??? 更嚴(yán)重的問題, 某些應(yīng)用服務(wù)器把環(huán)境上下文及當(dāng)前類加載器設(shè)置到不同的類加載器實(shí)例上, 而這些類加載器有相同的類路徑但卻沒有委派機(jī)制中的父子關(guān)系. 想想這為什么十分可怕. 要知道類加載器定義并加載的類實(shí)例會(huì)帶有一個(gè)JVM內(nèi)部的ID號(hào). 如果當(dāng)前類加載器加載一個(gè)類X的實(shí)例, 這個(gè)實(shí)例調(diào)用JNDI查找類Y的實(shí)例, 些時(shí)的上下文的類加載器也可以定義了加載類Y實(shí)例. 這個(gè)類Y的定義就與當(dāng)前類加載器看到的類Y的定義不同. 如果進(jìn)行強(qiáng)制類型轉(zhuǎn)換, 則產(chǎn)生異常.

          ?? 這種混亂的情況還將在Java中存在一段時(shí)間. 對(duì)于那些需要?jiǎng)討B(tài)加載資源的J2SEAPI, 我們來猜想它們的類加策略. 例如:

          ????????? JNDI 使用線程上下文類加載器

          ????????? Class.getResource() Class.forName()使用當(dāng)前類加載器

          ????????? JAXP(J2SE 1.4 及之后)使用線程上下文類加載器

          ????????? java.util.ResourceBundle 使用調(diào)用者的當(dāng)前類加載器

          ????????? URL protocol handlers specified via java.protocol.handler.pkgs system property are looked up in the bootstrap and system classloaders only

          ????????? Java 序列化API默認(rèn)使用調(diào)用者當(dāng)前的類加載器

          這些類及資源的加載策略問題, 肯定是J2SE領(lǐng)域中文檔最及說明最缺乏的部分了.

          posted @ 2006-07-25 11:04 sharajava 閱讀(2519) | 評(píng)論 (1)編輯 收藏

          2006年7月21日 #

          JBoss啟動(dòng)過程(譯)

          1.????? org.jboss.Main.main(String[]) 為入口.

          2.????? main 函數(shù)創(chuàng)建一個(gè)名叫”jboss”的線程組, 然后創(chuàng)建一個(gè)屬于該組的線程, 在線程中執(zhí)行boot方法.

          3.????? boot 方法首先處理main函數(shù)中的參數(shù)(及一些其它的系統(tǒng)環(huán)境設(shè)置), 接著就用系統(tǒng)的屬性創(chuàng)建了org.jboss.system.server.ServerLoader實(shí)例[new ServerLoader(props)].

          4.????? ServerLoader 注冊(cè)Jboss相關(guān)的類路徑, 包括XML解析器, jboss-jmx.jar, concurrent.jar及其它的一些額外的類路徑.

          5.????? ServerLoader 通過load(ClassLoader)方法創(chuàng)建Jboss Server實(shí)例. 參數(shù)ClassLoaderClassLoader parentCL = Thread.currentThread(). getContextClassLoader( )得到的當(dāng)前線程的類加載器. 創(chuàng)建的Server實(shí)例是org.jboss.system.server.Server接口的實(shí)現(xiàn). load(ClassLoader)方法的細(xì)節(jié):

          ???????? jar包及在ServerLoader中注冊(cè)的類路徑創(chuàng)建一個(gè)URLClassLoader的實(shí)例, 把傳入的ClassLoader作為該URLClassLoaderparent.

          ???????? Server 接口的實(shí)現(xiàn)類由系統(tǒng)屬性 jboss.server.type決定, 默認(rèn)是????? org.jboss.system.server.ServerImpl.

          ???????? URLClassLoader 通過無參構(gòu)造函數(shù)加載Server接口實(shí)現(xiàn)的實(shí)例. 在加載前把當(dāng)前線程的類加載器置為該URLClassLoader, 在加載完成后再置回之前傳入的ClassLoader.

          6.????? Server 實(shí)例用系統(tǒng)屬性進(jìn)行初始化[server.init(props)].

          7.????? 服務(wù)起動(dòng)[server.start()]. 起動(dòng)過程的默認(rèn)實(shí)現(xiàn)如下:

          ???????? 把當(dāng)前線程類型加載器置為加載該Server接口實(shí)現(xiàn)實(shí)例的ClassLoader.

          ???????? jboss域內(nèi), 通過MBeanServerFactorycreateMBeanServer(String)方法創(chuàng)建MbeanServer實(shí)例.

          ???????? MBean Server上注冊(cè)ServerImplServerConfigImpl兩個(gè)MBean.

          ???????? 初始化統(tǒng)一的類加載倉(cāng)庫(kù)(unified class loader repository), 用來裝載服務(wù)器配置目錄及其它可選目錄下的jar文件. 對(duì)于每一個(gè)jar文件和類目錄都會(huì)創(chuàng)建一個(gè)相應(yīng)的org.jboss.jmx.loading.UnifiedClassLoader實(shí)例, 并且注冊(cè)到統(tǒng)一的倉(cāng)庫(kù)中. 其中一個(gè)UnifiedClassLoader實(shí)例會(huì)被設(shè)置為當(dāng)前線程上下文的ClassLoader. [?: This effectively makes allUnifiedClassLoaders available through the thread context class loader.]

          ???????? 接下來創(chuàng)建org.jboss.system.ServiceControllerMBean實(shí)例. ServiceController管理JBoss MBean服務(wù)的生命周期.

          ???????? org.jboss.deployment.MainDeployer 實(shí)例被創(chuàng)建并起動(dòng). MainDeployer管理部署的依賴和部署的定向.

          ???????? org.jboss.deployment. JARDeployer 實(shí)例被創(chuàng)建并起動(dòng). JARDeployer處理jar包的部署.

          ???????? org.jboss.deployment. SARDeployer 實(shí)例被創(chuàng)建并起動(dòng). SARDeployer處理JBoss MBean服務(wù)的部署.

          ???????? MainDeployer 對(duì)當(dāng)前服務(wù)器文件環(huán)境里conf/jboss-service.xml定義的服務(wù)進(jìn)行部署.

          啟動(dòng)過程結(jié)束. 把當(dāng)前線程上下文類加載器置回為起動(dòng)前的ClassLoader.

          posted @ 2006-07-21 08:27 sharajava 閱讀(1616) | 評(píng)論 (0)編輯 收藏

          僅列出標(biāo)題  
          主站蜘蛛池模板: 连城县| 林甸县| 定结县| 广南县| 汶上县| 磐安县| 兴隆县| 色达县| 闻喜县| 多伦县| 怀安县| 云龙县| 萝北县| 赤峰市| 昔阳县| 房产| 鄱阳县| 会理县| 辰溪县| 沙坪坝区| 新竹市| 富蕴县| 密云县| 醴陵市| 建湖县| 嫩江县| 都兰县| 乐陵市| 长丰县| 广元市| 南和县| 武陟县| 西畴县| 额尔古纳市| 平安县| 望都县| 静海县| 太谷县| 巴彦淖尔市| 新兴县| 织金县|