前言
學習java的第一步就要搭建java的學習環境,首先是要安裝JDK,JDK安裝好之後,還需要在電腦上配置"JAVA_HOME”、"path”、"classpath"這三個環境變量才能夠把java的開發環境搭建好。在沒安裝過jdk的環境下,path環境變量是系統變量,本來存在的,而JAVA_HOME和classpath是不存在的。
一、配置JAVA_HOME變量
操作步驟(win7系統):計算機→右鍵“屬性”→高級系統設置→高級→環境變量,如下圖所示:
新建】”,彈出一個新建系統變量對話框,首先在變量名寫上JAVA_HOME,顧名思義,JAVA_HOME的含義就是JDK的安裝路徑,,然後在變量值寫JDK的安裝路徑,如這裏設置的變量值是"D:\Program Files (x86)\Java\jdk1.7.0",設置好變量值之後,點擊【確定】按鈕,JAVA_HOME環境變量就設置完成,如下圖所示:系統變量中多了一個"JAVA_HOME"變量
二、配置path環境變量
操作步驟(win7系統):計算機→右鍵“屬性”→高級系統設置→高級→環境變量
找到系統變量中的Path變量,點擊【編輯】按鈕,彈出編輯系統變量的對話框,可以看到,Path變量中設置有很多的目錄,每個目錄之間使用;(分號)隔開,將%JAVA_HOME%\bin;添加到Path變量的變量值中,點擊【確定】按鈕,Path環境變量的就設置完成了,如下圖所示:
三、配置ClassPath變量
設置Classpath的目的,在於告訴Java執行環境,在哪些目錄下可以找到您所要執行的Java程序(.class文件),關於這個ClassPath變量,其實可以不用配置了,在網上經常看到Classpath=.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\toos.jar,但學習java這麼久發現,不配置ClassPath也不影響java項目的開發和運行的。
四、JAVA_HOME變量、Path變量、ClassPath變量的説明
4.1. 設置JAVA_HOME變量的目的
一、為了方便引用,比如,JDK安裝在D:\Program Files (x86)\Java\jdk1.7.0目錄裏,則設置JAVA_HOME為該目錄路徑, 那麼以後要使用這個路徑的時候, 只需輸入%JAVA_HOME%即可, 避免每次引用都輸入很長的路徑串;
二、歸一原則, 當JDK路徑被迫改變的時候, 僅需更改JAVA_HOME的變量值即可。
三、第三方軟件會引用約定好的JAVA_HOME變量, 典型的就是tomcat服務器,如果不配置JAVA_HOME變量,那麼tomcat服務器根本運行不起來
4.2. Path變量(重點説明)
操作系統用path的路徑來找可執行程序(.exe程序),在windows下當我們敲任何一個命令時,實際上就是在執行一個可執行文件,如輸入notepad命令就可以打開一個記事本
實際上是執行了c:\Windows下的notepad.exe這個可執行文件,和用鼠標雙擊notepad.exe後能夠打開一個記事本的效果是一樣的
當在命令窗口敲一個命令時,系統就會去自動尋找這個命令對應的可執行文件(.exe),如果這個文件不存在,就當然無法執行這個命令了。這個可執行文件的根目錄必須設置在path環境變量中。
4.3.在命令窗口顯示path設置的環境變量
直接輸入“echo %path%”命令就可以顯示設置的path環境變量的所有根目錄了,只要是根目錄裏面存在相應的.exe文件,敲入命令時就能執行這個相應的.exe文件。
因為notepad.exe所在的Windows目錄已經添加到了Path環境變量中了,這就解釋了為什麼輸入命令notepad就可以打開一個記事本,所以前面配置java開發環境時,將%JAVA_HOME%\bin添加到Path變量中的目的就是希望可以在命令行窗口下使用javac和java這兩個命令來執行javac.exe和java.exe這兩個可執行程序。
4.4.Classpath變量説明
使用javac命令編譯.java文件時,如果需要其他的類,也是通過classpath去找的,
使用java命令執行.class文件時,執行的.class文件是通過classpath去找的。
classpath表示的是要查找的類所在的路徑。
五、用户變量和系統變量的區別
從上面的圖中可以看到,環境變量中有兩種變量,一種是用户變量,另一種是系統變量,那麼這兩種變量有什麼區別呢?用户變量,顧名思義,是針對某一個特定的用户的,只對特定的用户有效,而系統變量,則對任何用户都有效。下面以配置Maven的開發環境來進行具體説明用户變量和系統變量的區別
添加MAVEN_HOME用户變量
點擊用户變量的【新建】按鈕,彈出新建用户變量對話框,輸入要新建的變量名和變量值,點擊【確定】按鈕,新的用户變量就創建好了,如下圖所示:
添加Path用户變量
這裏是在當前登錄系統的gacl用户的用户變量裏面添加了2個新的用户變量:MAVEN_HOME用户變量和Path用户變量,MAVEN_HOME變量和Path變量只對gacl用户有效,使用別的用户登錄是無效的。
現在可以看到了,環境變量中存在了2個Path變量,一個是用户變量Path,一個是系統變量Path,
那麼當需要使用Path變量的值時,到底使用哪一個Path呢,怎麼區分這兩個Path呢?當需要使用Path環境變量時,操作,系統的做法是把用户自己創建的Path用户變量的值和path系統變量的值疊加在一起來使用,或者可以理解成操作系統會把Path用户變量的值加入到Path系統變量中,然後使用的時候使用的是系統變量的Path。
沒有添加用户變量Path前,Path變量的值就是系統變量Path裏面設置的值,如下圖所示:
添加用户變量Path後,Path變量的值=系統變量Path裏面設置的值+用户變量Path中設置的值,如下圖所示:
在Windows下,環境變量不區分大小寫,所以path變量名不區分大小寫。
Java整個編譯以及運行的過程相當繁瑣,本文通過一個簡單的程序來簡單的説明整個流程。
如下圖,Java程序從源文件創建到程序運行要經過兩大步驟:1、源文件由編譯器編譯成字節碼(ByteCode) 2、字節碼由java虛擬機解釋運行。因為java程序既要編譯同時也要經過JVM的解釋運行,所以説Java被稱為半解釋語言( "semi-interpreted" language)。
圖1 java程序編譯運行過程
下面通過以下這個java程序,來説明java程序從編譯到最後運行的整個流程。代碼如下:
1. //MainApp.java
2. public class MainApp {
3. public static void main(String[] args) {
4. new Animal("Puppy");
5. animal.printName();
6. }
7. }
8. //Animal.java
9. public class Animal {
10. public String name;
11. public Animal(String name) {
12. this.name = name;
13. }
14. public void printName() {
15. "Animal ["+name+"]");
16. }
17. }
第一步(編譯): 創建完源文件之後,程序會先被編譯為.class文件。Java編譯一個類時,如果這個類所依賴的類還沒有被編譯,編譯器就會先編譯這個被依賴的類,然後引用,否則直接引用,這個有點象make。如果java編譯器在指定目錄下找不到該類所其依賴的類的.class文件或者.java源文件的話,編譯器話報“cant find symbol”的錯誤。
編譯後的字節碼文件格式主要分為兩部分:常量池和方法字節碼。常量池記錄的是代碼出現過的所有token(類名,成員變量名等等)以及符號引用(方法引用,成員變量引用等等);方法字節碼放的是類中各個方法的字節碼。下面是MainApp.class通過反彙編的結果,我們可以清楚看到.class文件的結構:
第二步(運行):java類運行的過程大概可分為兩個過程:1、類的加載 2、類的執行。需要説明的是:JVM主要在程序第一次主動使用類的時候,才會去加載該類。也就是説,JVM並不是在一開始就把一個程序就所有的類都加載到內存中,而是到不得不用的時候才把它加載進來,而且只加載一次。
下面是程序運行的詳細步驟:
- 在編譯好java程序得到MainApp.class文件後,在命令行上敲java AppMain。系統就會啓動一個jvm進程,jvm進程從classpath路徑中找到一個名為AppMain.class的二進制文件,將MainApp的類信息加載到運行時數據區的方法區內,這個過程叫做MainApp類的加載。
- 然後JVM找到AppMain的主函數入口,開始執行main函數。
- main函數的第一條命令是Animal animal = new Animal("Puppy");就是讓JVM創建一個Animal對象,但是這時候方法區中沒有Animal類的信息,所以JVM馬上加載Animal類,把Animal類的類型信息放到方法區中。
- 加載完Animal類之後,Java虛擬機做的第一件事情就是在堆區中為一個新的Animal實例分配內存, 然後調用構造函數初始化Animal實例,這個Animal實例持有着指向方法區的Animal類的類型信息(其中包含有方法表,java動態綁定的底層實現)的引用。
- 當使用animal.printName()的時候,JVM根據animal引用找到Animal對象,然後根據Animal對象持有的引用定位到方法區中Animal類的類型信息的方法表,獲得printName()函數的字節碼的地址。
- 開始運行printName()函數。
特別説明:java類中所有public和protected的實例方法都採用動態綁定機制,所有私有方法、靜態方法、構造器及初始化方法<clinit>都是採用靜態綁定機制。而使用動態綁定機制的時候會用到方法表,靜態綁定時並不會用到。本文只是講述java程序運行的大概過程,所以並沒有細加區分。本文的所述的流程非常粗糙,想深入瞭解的讀者請查閲其他資料。存在謬誤的地方,請多指正。