六月婷婷综合激情-六月婷婷综合-六月婷婷在线观看-六月婷婷在线-亚洲黄色在线网站-亚洲黄色在线观看网站

明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

玩轉(zhuǎn)Java的CLASSPATH

[摘要]摘要: =================================== 從表面上看,Java的classpath(類(lèi)路徑)很簡(jiǎn)單,但一直以來(lái)它都是一個(gè)產(chǎn)生問(wèn)題和混亂的根源。本文介紹classpath的基本知識(shí)、可能產(chǎn)生的問(wèn)題,并提供了一個(gè)簡(jiǎn)單的classpath管理工具。 ...
摘要:
===================================
從表面上看,Java的classpath(類(lèi)路徑)很簡(jiǎn)單,但一直以來(lái)它都是一個(gè)產(chǎn)生問(wèn)題和混亂的根源。本文介紹classpath的基本知識(shí)、可能產(chǎn)生的問(wèn)題,并提供了一個(gè)簡(jiǎn)單的classpath管理工具。
===================================
正文:
===================================

和Java類(lèi)路徑(classpath)打交道的過(guò)程中,開(kāi)發(fā)者偶爾會(huì)遇到麻煩。這是因?yàn),?lèi)裝載器實(shí)際裝入的是哪一個(gè)類(lèi)有時(shí)并不顯而易見(jiàn),當(dāng)應(yīng)用程序的classpath包含大量的類(lèi)和目錄時(shí),情況尤其嚴(yán)重。本文將提供一個(gè)工具,它能夠顯示出被裝入類(lèi)文件的絕對(duì)路徑名。


一、Classpath基礎(chǔ)


Java虛擬機(jī)(JVM)借助類(lèi)裝載器裝入應(yīng)用程序使用的類(lèi),具體裝入哪些類(lèi)根據(jù)當(dāng)時(shí)的需要決定。CLASSPATH環(huán)境變量告訴類(lèi)裝載器到哪里去尋找第三方提供的類(lèi)和用戶定義的類(lèi)。另外,你也可以使用JVM命令行參數(shù)-classpath分別為應(yīng)用程序指定類(lèi)路徑,在-classpath中指定的類(lèi)路徑覆蓋CLASSPATH環(huán)境變量中指定的值。


類(lèi)路徑中的內(nèi)容可以是:文件的目錄(包含不在包里面的類(lèi)),包的根目錄(包含已打包的類(lèi)),包含類(lèi)的檔案文件(比如.zip文件或者.jar文件)。在Unix家族的系統(tǒng)上,類(lèi)路徑的各個(gè)項(xiàng)目由冒號(hào)分隔,在MS Windows系統(tǒng)上,它們由分號(hào)分隔。


類(lèi)裝載器以委托層次的形式組織,每一個(gè)類(lèi)裝載器有一個(gè)父類(lèi)裝載器。當(dāng)一個(gè)類(lèi)裝載器被要求裝載某個(gè)類(lèi)時(shí),它在嘗試自己尋找類(lèi)之前會(huì)把請(qǐng)求先委托給它的父類(lèi)裝載器。系統(tǒng)類(lèi)裝載器,即由安裝在系統(tǒng)上的JDK或JRE提供的默認(rèn)類(lèi)裝載器,通過(guò)CLASSPATH環(huán)境變量或者-classpath這個(gè)JVM命令行參數(shù)裝入第三方提供的類(lèi)或者用戶定義的類(lèi)。系統(tǒng)類(lèi)裝載器委托擴(kuò)展類(lèi)裝載器裝入使用Java Extension機(jī)制的類(lèi)。擴(kuò)展類(lèi)裝載器委托自舉類(lèi)裝載器(bootstrap class loader)裝入核心JDK類(lèi)。


你可以自己開(kāi)發(fā)特殊的類(lèi)裝載器,定制JVM如何動(dòng)態(tài)地裝入類(lèi)。例如,大多數(shù)Servlet引擎使用定制的類(lèi)裝載器,動(dòng)態(tài)地裝入那些在classpath指定的目錄內(nèi)發(fā)生變化的類(lèi)。


必須特別注意的是(也是令人吃驚的是),類(lèi)裝載器裝入類(lèi)的次序就是類(lèi)在classpath中出現(xiàn)的次序。類(lèi)裝載器從classpath的第一項(xiàng)開(kāi)始,依次檢查每一個(gè)設(shè)定的目錄和壓縮文件,嘗試找出待裝入的類(lèi)文件。當(dāng)類(lèi)裝載器第一次找到具有指定名字的類(lèi)時(shí),它就把該類(lèi)裝入,classpath中所有余下的項(xiàng)目都被忽略。


看起來(lái)很簡(jiǎn)單,對(duì)吧?

二、可能出現(xiàn)的問(wèn)題


不管他們是否愿意承認(rèn),初學(xué)者和富有經(jīng)驗(yàn)的Java開(kāi)發(fā)者都一樣,他們都曾經(jīng)在某些時(shí)候(通常是在那些最糟糕的情形下)被冗長(zhǎng)、復(fù)雜的classpath欺騙。應(yīng)用程序所依賴(lài)的第三方類(lèi)和用戶定義類(lèi)的數(shù)量逐漸增長(zhǎng),classpath也逐漸成了一個(gè)堆積所有可能的目錄和檔案文件名的地方。此時(shí),類(lèi)裝載器首先裝載的究竟是哪一個(gè)類(lèi)也就不再顯而易見(jiàn)。如果classpath中包含重復(fù)的類(lèi)入口,這個(gè)問(wèn)題尤其突出。前面已經(jīng)提到,類(lèi)裝載器總是裝載第一個(gè)它在classpath中找到的具有合適名字的類(lèi),從實(shí)際效果看,它“隱藏”了其他具有合適名字但在classpath中優(yōu)先級(jí)較低的類(lèi)。


如果不小心,你很容易掉進(jìn)這個(gè)classpath的陷阱。當(dāng)你結(jié)束了一天漫長(zhǎng)的工作,最后為了讓?xiě)?yīng)用程序使用最好、最新的類(lèi),你把一個(gè)目錄加入到了classpath,但與此同時(shí),你卻忘記了:在classpath的另一個(gè)具有更高優(yōu)先級(jí)的目錄下,存放著該類(lèi)的另一個(gè)版本!


三、一個(gè)簡(jiǎn)單的classpath工具


優(yōu)先級(jí)問(wèn)題是扁平路徑聲明方法與生俱來(lái)固有的問(wèn)題,但它不是只有Java的classpath才有的問(wèn)題。要解決這個(gè)問(wèn)題,你只需站到富有傳奇色彩的軟件巨構(gòu)的肩膀上:Unix操作系統(tǒng)有一個(gè)which命令,在命令參數(shù)中指定一個(gè)名字,which就會(huì)顯示出當(dāng)這個(gè)名字作為命令執(zhí)行時(shí)執(zhí)行文件的路徑名。實(shí)際上,which命令是分析PATH變量,然后找出命令第一次出現(xiàn)的位置。對(duì)于Java的類(lèi)路徑管理來(lái)說(shuō),這應(yīng)該也是一個(gè)好工具。在它的啟發(fā)之下,我著手設(shè)計(jì)了一個(gè)Java工具JWhich。這個(gè)工具要求指定一個(gè)Java類(lèi)的名字,然后根據(jù)classpath的指引,找出類(lèi)裝載器即將裝載的類(lèi)所在位置的絕對(duì)路徑。


下面是一個(gè)JWhich的使用實(shí)例。它顯示出當(dāng)Java類(lèi)裝載器裝載com.clarkware.ejb.ShoppingCartBean類(lèi)時(shí),該類(lèi)第一次出現(xiàn)位置的絕對(duì)路徑名,查找結(jié)果顯示該類(lèi)在某個(gè)目錄下:


> java JWhich com.clarkware.ejb.ShoppingCartBean

Class 'com.clarkware.ejb.ShoppingCartBean' found in
'/home/mclark/classes/com/clarkware/ejb/ShoppingCartBean.class'




下面是第二個(gè)JWhich的使用實(shí)例。它顯示出當(dāng)Java類(lèi)裝載器裝載javax.servlet.http.HttpServlet類(lèi)時(shí),該類(lèi)第一次出現(xiàn)位置的絕對(duì)路徑名,查找結(jié)果顯示該類(lèi)在某個(gè)檔案文件中:


> java JWhich javax.servlet.http.HttpServlet

Class 'javax.servlet.http.HttpServlet' found in
'file:/home/mclark/lib/servlet.jar!/javax/servlet/http/HttpServlet.class'

四、JWhich的工作過(guò)程

要精確地測(cè)定classpath中哪一個(gè)類(lèi)先被裝載,你必須深入到類(lèi)裝載器的思考方法。事實(shí)上,具體實(shí)現(xiàn)的時(shí)候并沒(méi)有聽(tīng)起來(lái)這么復(fù)雜——你只需直接詢(xún)問(wèn)類(lèi)裝載器就可以了!


1: public class JWhich {
2:
3: /**
4: * 根據(jù)當(dāng)前的classpath設(shè)置,
5: * 顯示出包含指定類(lèi)的類(lèi)文件所在
6: * 位置的絕對(duì)路徑
7: *
8: * @param className <類(lèi)的名字>
9: */
10: public static void which(String className) {
11:
12: if (!className.startsWith("/")) {
13: className = "/" + className;
14: }
15: className = className.replace('.', '/');
16: className = className + ".class";
17:
18: java.net.URL classUrl =
19: new JWhich().getClass().getResource(className);
20:
21: if (classUrl != null) {
22: System.out.println("\nClass '" + className +
23: "' found in \n'" + classUrl.getFile() + "'");
24: } else {
25: System.out.println("\nClass '" + className +
26: "' not found in \n'" +
27: System.getProperty("java.class.path") + "'");
28: }
29: }
30:
31: public static void main(String args[]) {
32: if (args.length > 0) {
33: JWhich.which(args[0]);
34: } else {
35: System.err.println("Usage: java JWhich <classname>");
36: }
37: }
38: }




首先,你必須稍微調(diào)整一下類(lèi)的名字以便類(lèi)裝載器能夠接受(12-16行)。在類(lèi)的名字前面加上一個(gè)“/”表示要求類(lèi)裝載器對(duì)classpath中的類(lèi)名字進(jìn)行逐字精確匹配,而不是嘗試隱含地加上調(diào)用類(lèi)的包名字前綴。把所有“.”轉(zhuǎn)換為“/”的目的是,按照類(lèi)裝載器的要求,把類(lèi)名字格式化成一個(gè)合法的URL資源名。

接下來(lái),程序向類(lèi)裝載器查詢(xún)資源,這個(gè)資源的名字必須和經(jīng)過(guò)適當(dāng)格式化的類(lèi)名字匹配(18-19行)。每一個(gè)Class對(duì)象維護(hù)著一個(gè)對(duì)裝載它的ClassLoader對(duì)象的引用,所以這里是向裝載JWhich類(lèi)的類(lèi)裝載器查詢(xún)。Class.getResource()方法實(shí)際上委托裝入該類(lèi)的類(lèi)裝載器,返回一個(gè)用于讀取類(lèi)文件資源的URL;或者,當(dāng)指定的類(lèi)名字不能在當(dāng)前的classpath中找到時(shí),Class.getResource()方法返回null。

最后,如果當(dāng)前的classpath中能夠找到指定的類(lèi),則程序顯示包含該類(lèi)的類(lèi)文件所在位置的絕對(duì)路徑名(21-24行)。作為一種調(diào)試輔助手段,如果當(dāng)前classpath中不能找到指定的類(lèi),則程序獲取java.class.path系統(tǒng)屬性并顯示當(dāng)前的classpath(24-28行)。

很容易想象,在使用Servlet引擎classpath的Java Servlet中,或者在使用EJB服務(wù)器classpath的EJB組件中,上面這段簡(jiǎn)單的代碼是如何運(yùn)作。例如,如果JWhich類(lèi)是由Servlet引擎的定制類(lèi)裝載器裝入,那么程序?qū)⒂肧ervlet引擎的類(lèi)裝載器去尋找指定的類(lèi)。如果Servlet引擎的類(lèi)裝載器不能找到類(lèi)文件,它將委托它的父類(lèi)裝載器。一般地,當(dāng)JWhich被某個(gè)類(lèi)裝載器裝入時(shí),它能夠找出當(dāng)前類(lèi)裝載器以及所有其父類(lèi)裝載器所裝入的所有類(lèi)。

【結(jié)束語(yǔ)】如果需要是所有發(fā)明之母,那么幫助我們管理Java類(lèi)路徑的工具可以說(shuō)遲到了很長(zhǎng)時(shí)間。Java新聞組和郵件列表中充塞著許多有關(guān)classpath的問(wèn)題,現(xiàn)在JWhich為我們提供了一個(gè)簡(jiǎn)單卻強(qiáng)大的工具,幫助我們?cè)谌魏苇h(huán)境中徹底玩轉(zhuǎn)Java類(lèi)路徑。



相關(guān)文章

主站蜘蛛池模板: 色爱区综合小说 | 伊人五月婷婷 | 欧美一级高清片 | 伊人网在线免费视频 | 伊人首页| 亚洲国产成人久久综合野外 | 亚洲成在人 | 中国日韩欧美中文日韩欧美色 | 日韩亚洲欧美日本精品va | 伊人影视在线观看日韩区 | 天天干天天干天天干天天干天天干 | 日韩成人免费视频播放 | 人人爱人人做 | 欧美天天性 | 中文字幕乱码视频中文字幕14 | 亚洲欧美手机在线观看 | 亚洲伊人久久大香线蕉结合 | 色网站在线观看 | 无遮挡毛片a级武则天 | 青草视频入口 在线观看 | 中文字幕欧美视频 | 日本伊人久久 | 天天爱天天舔 | 亚洲视频在线免费观看 | 天堂网www中文在线资源 | 性喷潮久久久久久久久 | 色狠狠成人综合网 | 日韩欧美中文字幕一区二区三区 | 最近新韩国hd视频 | 亚洲综合免费视频 | 日韩av东京社区男人的天堂 | 热久久亚洲 | 天天逼网| 手机在线毛片免费播放 | 青青草原国产 | 午夜5060网| 婷婷午夜| 天天射天天搞 | 综合婷婷丁香 | 亚洲精品乱码久久久久久中文字幕 | 日本高清免费中文在线看 |