日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Mastering the Java CLASSPATH

發布時間:2025/4/16 java 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Mastering the Java CLASSPATH 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
拋棄IDE進行java命令行開發才發現問題多多,找了篇不錯的解釋classpath的文章,防止找不到,轉載之。
原文:http://www.k99k.com/texts/master-java-classpath.html
1、class搜索路徑的重要性

理解class搜索路徑對所有Java開發人員來說都很重要,但是,IDE的廣泛使用掩蓋了這項技術,使大家普遍對它缺乏了解,甚至包括好多老鳥。這個問題在開發用于發布的應用程序(原文為distributed applications,但好像譯為“分布式應用”有點晦澀)時尤其嚴重,因為應用程序運行時的系統環境可能和開發時的大不相同。

本文詳細描述了某些Java類被其他代碼引用時,Java編譯器和JVM如何使用類搜索路徑(class search path )定位這些類。這兒用一個非常簡單的例子——同一個包中的兩個類——來具體說明。我們將通過不同的方式來編譯這兩個類,根據classpath的設置不 同,編譯可能成功也可能失敗。

為了最清楚的說明這個問題,我們將只使用命令行工具進行編譯。交互式開發工具有它們自己操作classpath的方法,這些方法因產品而異。

至于是由Java編譯器在編譯時定位需要的類,還是由JVM在運行時來做,這兩種方法沒有本質的區別。但編譯器可以從源代碼中編譯需要的類,而JVM不行。下面的例子中我們用編譯器來做,但在運行時的實現也完全類似。


2、例子

本例有兩個很小的類:com.web_tomorrow.CPTest1 和 com.web_tomorrow.CPTest2,如下所示:
package com.web_tomorrow;
public class CPTest1
{
?? public static void main(String[] args)
?? {
??? System.out.println ("Run CPTest1.main()");
?? }
}

package com.web_tomorrow;
public class CPTest2
{
? public static void main(String[] args)
? {
??? System.out.println ("Run CPTest2.main()");
??? CPTest1 cpt1 = new CPTest1();
? }
}

Java代碼組織的一個最基本規則就是`package name = directory name'(“包名 = 目錄名”)。我們將為這兩個類建立對應的目錄結構,它們在包com.web_tomorrow中,所以我們創建目錄
com/web_tomorrow來存放源代碼:
[root]
? com
??? web_tomorrow
????? CPTest1.java
????? CPTest2.java

在本文中我用符號`[root]'來表示存放上述結構的任意目錄,也就是說,根目錄的位置由你決定。當然這會隨安裝這些文件的方式不同而不一樣。

3基本原理

讓我們來嘗試用命令行工具javac來編譯CPTest1.java。為了完全禁止類搜索路徑(以防已有的設置影響本例),我們在javac上加上選項`-classpath ""'。

作為第一次試驗,我們先換到CPTest1.java所在的目錄下,并且嘗試用javac和文件名進行編譯。
cd [root]/com/web_tomorrow
javac -classpath "" CPTest1.java

操作成功,因為編譯器能發現CPTest1.java (它就在當前的工作目錄下),并且CPTest1沒有引用任何其他類。輸出文件CPTest1.class在CPTest1.java的相同目錄下,因為 你沒有給編譯器任何信息讓它作其它處理。到現在為止,一直都很好。現在讓我們用同樣的方式來試一下CPTest2。仍然在web_tomorrow目錄 下,執行命令:
javac -classpath "" CPTest2.java

雖然目錄還是剛才的目錄,CPTest1和CPTest2也在相同的包里,這一次卻失敗了。錯誤信息可能是這樣的:
CPTest2.java:7: cannot resolve symbol
symbol? : class CPTest1?
location: class com.web_tomorrow.CPTest2
? CPTest1 cpt1 = new CPTest1();
? ^

這一次和上一次成功的情況之間的區別之一就是CPTest2中有對CPTest1的引用:
? CPTest1 cpt1 = new CPTest1();

這次發生了什么呢?當編譯器遇到對CP1Test的引用時,它會認為CP1Test類與當前編譯的CP2Test類在同一個包里。這個假定是正確的,于是編譯器來尋

找com.web_tomorrow.CP1Test,但它沒有地方可以找,因為我們已經把類搜索路徑明確的指定成了“”(也就是空)。

你可能認為,只要告訴編譯器在當前目錄下尋找就可以解決這個問題。在Unix和Windows系統中,“當前目錄”的標準符號都是一個點號(.),也就是這樣的命

令:
javac -classpath "." CPTest2.java

Fail Againt!跟剛才的例子完全一樣,現在的問題是雖然CPTest1.java在當前目錄下,但它實現的類不是CPTest1,而是 com.web_tomorrow.CPTest1,編譯器將在當前目錄下尋找目錄com/web_tomorrow。也就是說,它在目錄[root] /com/web_tomorrow/com/web_tomorrow中尋找一個Java源文件或類文件,它們事實上根本不存在,于是出錯。

為了讓編譯器工作正常,我們不能讓類搜索路徑指向包含CPTest1的目錄,而是按照Java標準中`package name = directory name'的規則,給類搜索路徑指定編譯器能找到CPTest1的根目錄。這樣才能工作,雖然不太好看:
javac -classpath "../.." CPTest2.java

在考慮如何變得不難看之前,看一下這個例子(仍在同一目錄下)
javac -classpath "" CPTest1.java CPTest2.java

盡管classpath為空,這次卻能工作。這是因為Java編譯器會在命令行中明確列出的所有源代碼中查找引用。如果要編譯同一目錄下的多個類,有一種很簡單的方式:
javac -classpath "" *.java

'*.java'擴展為當前目錄下所有.java文件的列表。這就說明為什么一次編譯多個文件會成功,而同樣的文件一個一個的編譯卻失敗。

編譯CPTest2有一個更方便的方法:
cd [root]
javac -classpath "." com/web_tomorrow/CPTest2.java

這次我們為CPtest2.java指定了完整的路徑,而在-classpath選項中使用了'.'。另外,我們沒有告訴編譯器在當前目錄下尋找文 件,而是讓它從當前目錄開始搜索。因為我們要找的類是com.web_tomorrow.CPTest1,編譯器將在./com /web_tomorrow(也就是說當前目錄下的com/web_tomorrow子目錄)下尋找。這才是CPTest1.java正確的位置。

事實上,盡管我在命令行只指定了CPTest2,但事實上CPTest1同時也會被編譯。編譯器在正確的位置找到這個.java文件,但它不能判定這個.java文件是否包含正確的類,所以它編譯這個文件。但請注意如果是:
cd [root]
javac -classpath "." com/web_tomorrow/CPTest1.java

就不會導致CPTest2.java被編譯,因為編譯器編譯CPTest1時不需要知道CPTest2的任何事情。

類文件與.java文件分開的情況
到目前為止所有成功的例子都把輸出的.class文件放到.java文件同樣的位置,這是一種比較簡單的模式,應用非常廣泛。但很多開發者喜歡把源文件和生成的文件分開,因此它必須告訴編譯器為.class文件維護不同的目錄。下面我們來看看這對類搜索路徑有何影響。

首先我們刪除剛才幾個例子產生的所有.class文件。我們還要有一個新的目錄來存放生成的.class文件。命令行方式下的操作過程如下:
cd [root]
rm com/web_tomorrow/*.class
mkdir classes

如果你用Windows系統,別忘了把'/'替換成'\',現在的目錄結構如下:
[root]
? com
??? web_tomorrow
????? CPTest1.java
????? CPTest2.java
? classes

現在編譯CPTest1.java,指定類文件的目標目錄(通過-d選項)
cd [root]
javac -d classes -classpath "" com/web_tomorrow/CPTest1.java

成功,但你會注意到,.class文件根本不是直接放在classes目錄中,而是有了一個新的目錄結構:
[root]
? com
??? web_tomorrow
????? CPTest1.java
????? CPTest2.java
? classes
??? com
????? web_tomorrow
??????? CPTest1.class

編譯器建立了一個符合包結構的目錄結構,這很有用,我們馬上就會看到。當開始編譯CPTest2.java時我們有兩個選擇,第一種是像上面一樣,讓編譯器同時也

編譯一次CPTest1;另一種是用-classpath選項指定剛才編譯好的.class文件,這種方法更好一點,因為我們不必再來編譯一遍CPTest1:
cd [root]
javac -d classes -classpath classes com/web_tomorrow/CPTest2.java

完成之后,我們的目錄結構如下:
[root]
? com
??? web_tomorrow
????? CPTest1.java
????? CPTest2.java
? classes
??? com
????? web_tomorrow
??????? CPTest1.class
??????? CPTest2.class

當然我們也可以在同一條命令中編譯兩個.java文件,結果完全相同。


4、classpath中的JAR打包文件

Java編譯器和運行環境不僅可以在獨立文件中搜索類,還可以在JAR打包文件中進行查找。一個JAR打包文件可以維護它自己的目錄結構,Java 按照跟普通目錄結構完全相同的方式,`directory name = package name',進行搜索。由于JAR本身就是一個目錄,所以在類搜索路徑中包含JAR打包文件時,路徑必須引用JAR本身,而不是它所在的目錄。如果我在目 錄/myclasses下有一個JAR myclasses.jar,我需要指定:
javac -classpath /myclasses/myclasses.jar ...
而不僅僅是目錄myclasses。

5、多個類搜索目錄

在上面的例子中,每次我們都只讓javac在一個目錄下搜索。實際工作中,你的類搜索路徑會包含很多目錄和JAR文件。Javac的-classpath選項允許指定多個位置,但請注意,它的具體語法在Unix系統和Windows系統中稍有區別。
在Unix系統中是:
javac -classpath dir1:dir2:dir3 ...
而Windows系統則是:
javac -classpath dir1;dir2;dir3 ...

這是因為Windows使用冒號(:)作為文件名的一部分,因此不能作為文件名分隔符。當然目錄分隔符也不一樣:Unix的正斜杠(/)和Windows的反斜杠(\)。

6、系統classpath

除了在javac命令指定類搜索路徑外,我們還可以使用'系統'類路徑。如果命令中沒有指定特定的路徑,Java編譯器和JVM都使用系統路徑。在Unix和Windows系統中,系統路徑都通過環境變量設置。例如在使用bash shell的Linux系統中:
CLASSPATH=/myclasses/myclasses.jar;export CLASSPATH
在Windows中:
set CLASSPATH=c:\myclasses\myclasses.jar

這是暫時改變系統變量CLASSPATH的好方法,但如果你想這些變化一直保留下來,你就需要針對你的系統做一些修改。例如在Linux系統中,我會將這個命令放到我目錄下的文件.bashrc中。而在Windows 2000/NT中可以通過‘控制面板’來修改。

如果你有很多隨時用到的JAR,設置系統變量CLASSPATH就顯得尤為重要。比如說,如果我在用Sun的J2EE參考實現開發EJB應用,所有 EJB相關的類都發布在一個叫做“j2ee.jar”的JAR打包文件中,我希望這個JAR一直都在類搜索路徑中。另外,還有很多人希望無論當前目錄是什 么,搜索路徑始終包含當前目錄。所以在我的.bashrc文件中就有這樣一行:
CLASSPATH=/usr/j2ee/j2ee.jar:.;export CLASSPATH
其中`.'是指'當前目錄'

很容易看到命令行中的-classpath選項覆蓋默認的系統類路徑;它不是擴展而是覆蓋。因此如果我們既要包含默認的系統路徑,又要增加一些時怎 么處理呢?我們可以簡單的通過-classpath選項同時列出默認值和我們要額外增加的部分。而一個更好的辦法是引用系統變量CLASSPATH。當 然,這個語法對Windows系統和Unix系統是不同的。在Unix上:
javac -classpath $CLASSPATH:dir1:dir2 ...
其中$CLASSPATH擴展為系統變量CLASSPATH。在Windows上:
javac -classpath %CLASSPATH%;dir1:dir2 ...

轉載于:https://www.cnblogs.com/bnuvincent/archive/2009/08/11/1543435.html

總結

以上是生活随笔為你收集整理的Mastering the Java CLASSPATH的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。