在Java中宝泵,我們經(jīng)常聽到classpath
這個東西粗恢。網(wǎng)上有很多關(guān)于“如何設(shè)置classpath”的文章梆造,但大部分設(shè)置都不靠譜洛心。
到底什么是classpath
固耘?
classpath
是JVM用到的一個環(huán)境變量,它用來指示JVM如何搜索class
词身。
因為Java是編譯型語言厅目,源碼文件是.java
,而編譯后的.class
文件才是真正可以被JVM執(zhí)行的字節(jié)碼法严。因此损敷,JVM需要知道,如果要加載一個abc.xyz.Hello
的類深啤,應(yīng)該去哪搜索對應(yīng)的Hello.class
文件拗馒。
所以,classpath
就是一組目錄的集合溯街,它設(shè)置的搜索路徑與操作系統(tǒng)相關(guān)诱桂。例如,在Windows系統(tǒng)上呈昔,用;
分隔挥等,帶空格的目錄用""
括起來,可能長這樣:
C:\work\project1\bin;C:\shared;"D:\My Documents\project1\bin"
在Linux系統(tǒng)上堤尾,用:
分隔肝劲,可能長這樣:
/usr/shared:/usr/local/bin:/home/liaoxuefeng/bin
現(xiàn)在我們假設(shè)classpath
是.;C:\work\project1\bin;C:\shared
,當(dāng)JVM在加載abc.xyz.Hello
這個類時,會依次查找:
- <當(dāng)前目錄>\abc\xyz\Hello.class
- C:\work\project1\bin\abc\xyz\Hello.class
- C:\shared\abc\xyz\Hello.class
注意到.
代表當(dāng)前目錄涡相。如果JVM在某個路徑下找到了對應(yīng)的class
文件哲泊,就不再往后繼續(xù)搜索。如果所有路徑下都沒有找到催蝗,就報錯切威。
classpath
的設(shè)定方法有兩種:
在系統(tǒng)環(huán)境變量中設(shè)置classpath
環(huán)境變量,不推薦丙号;
在啟動JVM時設(shè)置classpath
變量先朦,推薦。
我們強烈不推薦在系統(tǒng)環(huán)境變量中設(shè)置classpath
犬缨,那樣會污染整個系統(tǒng)環(huán)境喳魏。在啟動JVM時設(shè)置classpath
才是推薦的做法。實際上就是給java
命令傳入-classpath
或-cp
參數(shù):
java -classpath .;C:\work\project1\bin;C:\shared abc.xyz.Hello
或者使用-cp
的簡寫:
java -cp .;C:\work\project1\bin;C:\shared abc.xyz.Hello
沒有設(shè)置系統(tǒng)環(huán)境變量怀薛,也沒有傳入-cp
參數(shù)刺彩,那么JVM默認(rèn)的classpath
為.
,即當(dāng)前目錄:
java abc.xyz.Hello
上述命令告訴JVM只在當(dāng)前目錄搜索Hello.class
枝恋。
在IDE中運行Java程序创倔,IDE自動傳入的-cp
參數(shù)是當(dāng)前工程的bin
目錄和引入的jar包。
通常焚碌,我們在自己編寫的class
中畦攘,會引用Java核心庫的class
,例如十电,String
知押、ArrayList
等。這些class
應(yīng)該上哪去找鹃骂?
有很多“如何設(shè)置classpath”的文章會告訴你把JVM自帶的rt.jar
放入classpath
台盯,但事實上,根本不需要告訴JVM如何去Java核心庫查找class
畏线,JVM怎么可能笨到連自己的核心庫在哪都不知道爷恳?
不要把任何Java核心庫添加到classpath中!JVM根本不依賴classpath加載核心庫象踊!
更好的做法是温亲,不要設(shè)置classpath
!默認(rèn)的當(dāng)前目錄.
對于絕大多數(shù)情況都夠用了杯矩。
jar包
如果有很多.class
文件栈虚,散落在各層目錄中,肯定不便于管理史隆。如果能把目錄打一個包魂务,變成一個文件,就方便多了。
jar包就是用來干這個事的粘姜,它可以把package
組織的目錄層級鬓照,以及各個目錄下的所有文件(包括.class
文件和其他文件)都打成一個jar文件,這樣一來孤紧,無論是備份豺裆,還是發(fā)給客戶,就簡單多了号显。
jar包實際上就是一個zip格式的壓縮文件臭猜,而jar包相當(dāng)于目錄。如果我們要執(zhí)行一個jar包的class
押蚤,就可以把jar包放到classpath
中:
java -cp ./hello.jar abc.xyz.Hello
這樣JVM會自動在hello.jar
文件里去搜索某個類蔑歌。
那么問題來了:如何創(chuàng)建jar包?
因為jar包就是zip包揽碘,所以次屠,直接在資源管理器中,找到正確的目錄雳刺,點擊右鍵帅矗,在彈出的快捷菜單中選擇“發(fā)送到”,“壓縮(zipped)文件夾”煞烫,就制作了一個zip文件。然后累颂,把后綴從.zip
改為.jar
滞详,一個jar包就創(chuàng)建成功。
假設(shè)編譯輸出的目錄結(jié)構(gòu)是這樣:
package_sample
└─ bin
├─ hong
│ └─ Person.class
│ ming
│ └─ Person.class
└─ mr
└─ jun
└─ Arrays.class
這里需要特別注意的是紊馏,jar包里的第一層目錄料饥,不能是bin
,而應(yīng)該是hong
朱监、ming
岸啡、mr
。如果在Windows的資源管理器中看赫编,應(yīng)該長這樣:
如果長這樣:
說明打包打得有問題巡蘸,JVM仍然無法從jar包中查找正確的class
,原因是hong.Person
必須按hong/Person.class
存放擂送,而不是bin/hong/Person.class
悦荒。
jar包還可以包含一個特殊的/META-INF/MANIFEST.MF
文件,MANIFEST.MF
是純文本嘹吨,可以指定Main-Class
和其它信息搬味。JVM會自動讀取這個MANIFEST.MF
文件,如果存在Main-Class
,我們就不必在命令行指定啟動的類名碰纬,而是用更方便的命令:
java -jar hello.jar
jar包還可以包含其它jar包萍聊,這個時候,就需要在MANIFEST.MF
文件里配置classpath
了悦析。
在大型項目中寿桨,不可能手動編寫MANIFEST.MF
文件,再手動創(chuàng)建zip包她按。Java社區(qū)提供了大量的開源構(gòu)建工具牛隅,例如Maven,可以非常方便地創(chuàng)建jar包酌泰。
小結(jié)
JVM通過環(huán)境變量classpath
決定搜索class
的路徑和順序媒佣;
不推薦設(shè)置系統(tǒng)環(huán)境變量classpath
,始終建議通過-cp
命令傳入陵刹;
jar包相當(dāng)于目錄默伍,可以包含很多.class
文件,方便下載和使用衰琐;
MANIFEST.MF
文件可以提供jar包的信息也糊,如Main-Class
,這樣可以直接運行jar包羡宙。
本文轉(zhuǎn)載自:https://www.liaoxuefeng.com/wiki/1252599548343744/1260466914339296