java基礎知識入門
一、java簡介及原理圖
Java的前世今生
Java之父詹姆斯·高斯林:
1967年, 12歲用報廢的電話機和電視做了一臺電子遊戲機;
1983年, 獲得卡內基梅隆大學電腦科學博士學位;
1983年, 畢業後設計了IBM第一代工作站;
1990年, 領導開發Sun用於數字家電的程式語言Oak(橡樹);
1994年, Oak被更名為Java, 在矽谷釋出並引發熱潮;
2000年, Java成為世界上最流行的程式語言
JDK(Java Development Kit)
JDK是Java開發工具包,是Sun Microsystems針對Java開發員的產品。
JDK中包含JRE,在JDK的安裝目錄下有一個名為jre的目錄,裡面有兩個資料夾bin和lib,在這裡可以認為bin裡的就是jvm,lib中則是jvm工作所需要的類庫,而jvm和 lib和起來就稱為jre。
JDK是整個JAVA的核心,包括了Java執行環境JRE(Java Runtime Envirnment)、一堆Java工具(javac/java/jdb等)和Java基礎的類庫(即Java API 包括rt.jar)。
①SE(J2SE),standard edition,標準版,是我們通常用的一個版本,從JDK 5.0開始,改名為Java SE。
②EE(J2EE),enterprise edition,企業版,使用這種JDK開發J2EE應用程式,從JDK 5.0開始,改名為Java EE。
③ME(J2ME),micro edition,主要用於移動裝置、嵌入式裝置上的java應用程式,從JDK 5.0開始,改名為Java ME。
金字塔結構 JDK=JRE+JVM+其它 執行Java程式一般都要求使用者的電腦安裝JRE環境(Java Runtime Environment);沒有jre,java程式無法執行;而沒有java程式,jre就沒有用武之地。
Java原理圖如下
二、資料型別
注意:java的關鍵字和識別符號是不可更改的
boolean 只有兩個值:true、false,可以使用 1 bit 來儲存,但是具體大小沒有明確規定。JVM 會在編譯時期將 boolean 型別的資料轉換為 int,使用 1 來表示 true,0 表示 false。JVM 支援 boolean 陣列,但是是通過讀寫 byte 陣列來實現的。
- Primitive Data Types
- The Java® Virtual Machine Specification
三、Java的心臟-JVM
JVM就是一臺虛擬的機器, Java程式編譯成位元組碼就能在所有JVM上執行. JVM可以說是整個Java生態系統的心臟, 它提供了兩大核心優勢:
強的跨平臺性: 除Windows和OS X之外, 還支援全部的Linux發行版和Solaris等較小 眾的作業系統
超強的執行效率: JVM在編譯和執行時會對程式做大量優化, 提高程式執行效率
由於JVM顯著的技術優勢, 除Java外, 還有一系列現代程式語言是基於 JVM技術的, 這極大地擴充套件了Java程式設計師未來的發展空間
Java虛擬機器的體系結構
·每個JVM都有兩種機制:
①類裝載子系統:裝載具有適合名稱的類或介面
②執行引擎:負責執行包含在已裝載的類或介面中的指令
·每個JVM都包含:
方法區、Java堆、Java棧、本地方法棧、指令計數器及其他隱含暫存器
對於JVM的學習,在我看來這麼幾個部分最重要:
Java程式碼編譯和執行的整個過程
JVM記憶體管理及垃圾回收機制
下面分別對這幾部分進行說明:
2、Java程式碼編譯和執行的整個過程
也正如前面所說,Java程式碼的編譯和執行的整個過程大概是:開發人員編寫Java程式碼(.java檔案),然後將之編譯成位元組碼(.class檔案),再然後位元組碼被裝入記憶體,一旦位元組碼進入虛擬機器,它就會被直譯器解釋執行,或者是被即時程式碼發生器有選擇的轉換成機器碼執行。
(1)Java程式碼編譯是由Java原始碼編譯器來完成,也就是Java程式碼到JVM位元組碼(.class檔案)的過程。 流程圖如下所示:
(2)Java位元組碼的執行是由JVM執行引擎來完成,流程圖如下所示:
Java程式碼編譯和執行的整個過程包含了以下三個重要的機制:
·Java原始碼編譯機制
·類載入機制
·類執行機制
(1)Java原始碼編譯機制
Java 原始碼編譯由以下三個過程組成:
①分析和輸入到符號表
②註解處理
③語義分析和生成class檔案
流程圖如下所示:
最後生成的class檔案由以下部分組成:
①結構資訊:包括class檔案格式版本號及各部分的數量與大小的資訊
②元資料:對應於Java原始碼中宣告與常量的資訊。包含類/繼承的超類/實現的介面的宣告資訊、域與方法宣告資訊和常量池
③方法資訊:對應Java原始碼中語句和表示式對應的資訊。包含位元組碼、異常處理器表、求值棧與區域性變數區大小、求值棧的型別記錄、除錯符號資訊
(2)類載入機制
JVM的類載入是通過ClassLoader及其子類來完成的,類的層次關係和載入順序可以由下圖來描述:
①Bootstrap ClassLoader
負責載入$JAVA_HOME中jre/lib/rt.jar裡所有的class,由C++實現,不是ClassLoader子類
②Extension ClassLoader
負責載入java平臺中擴充套件功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目錄下的jar包
③App ClassLoader
負責記載classpath中指定的jar包及目錄中class
④Custom ClassLoader
屬於應用程式根據自身需要自定義的ClassLoader,如tomcat、jboss都會根據j2ee規範自行實現ClassLoader
載入過程中會先檢查類是否被已載入,檢查順序是自底向上,從Custom ClassLoader到BootStrap ClassLoader逐層檢查,只要某個classloader已載入就視為已載入此類,保證此類只所有ClassLoader載入一次。而載入的順序是自頂向下,也就是由上層來逐層嘗試載入此類。
(3)類執行機制
JVM是基於堆疊的虛擬機器。JVM為每個新建立的執行緒都分配一個堆疊.也就是說,對於一個Java程式來說,它的執行就是通過對堆疊的操作來完成的。堆疊以幀為單位儲存執行緒的狀態。JVM對堆疊只進行兩種操作:以幀為單位的壓棧和出棧操作。
JVM執行class位元組碼,執行緒建立後,都會產生程式計數器(PC)和棧(Stack),程式計數器存放下一條要執行的指令在方法內的偏移量,棧中存放一個個棧幀,每個棧幀對應著每個方法的每次呼叫,而棧幀又是有區域性變數區和運算元棧兩部分組成,區域性變數區用於存放方法中的區域性變數和引數,運算元棧中用於存放方法執行過程中產生的中間結果。棧的結構如下圖所示:
四、JRE和JDK
JRE(Java Runtime Enviroment)是Java的執行環境。面向Java程式的使用者,而不是開發者。如果你僅下載並安裝了JRE,那麼你的系統只能執行Java程式。JRE是執行Java程式所必須環境的集合,包含JVM標準實現及 Java核心類庫。它包括Java虛擬機器、Java平臺核心類和支援檔案。它不包含開發工具(編譯器、偵錯程式等)。
JDK(Java Development Kit)又稱J2SDK(Java2 Software Development Kit),是Java開發工具包,它提供了Java的開發環境(提供了編譯器javac等工具,用於將java檔案編譯為class檔案)和執行環境(提 供了JVM和Runtime輔助包,用於解析class檔案使其得到執行)。如果你下載並安裝了JDK,那麼你不僅可以開發Java程式,也同時擁有了運 行Java程式的平臺。JDK是整個Java的核心,包括了Java執行環境(JRE),一堆Java工具tools.jar和Java標準類庫 (rt.jar)。
2. 區別
JRE主要包含:java類庫的class檔案(都在lib目錄下打包成了jar)和虛擬機器(jvm.dll);JDK主要包含:java類庫的 class檔案(都在lib目錄下打包成了jar)並自帶一個JRE。那麼為什麼JDK要自帶一個JRE呢?而且jdk/jre/bin下的client 和server兩個資料夾下都包含jvm.dll(說明JDK自帶的JRE有兩個虛擬機器)。
記得在環境變數path中設定jdk/bin路徑麼?老師會告訴大家不設定的話javac和java是用不了的。確實jdk/bin目錄下包含了所有的命令。可是有沒有人想過我們用的java命令並不是jdk/bin目錄下的而是jre/bin目錄下的呢?不信可以做一個實驗,大家可以把jdk /bin目錄下的java.exe剪下到別的地方再執行java程式,發現了什麼?一切OK!(JRE中沒有javac命令,原因很簡單,它不是開發環境)那麼有人會問了?我明明沒有設定jre/bin目錄到環境變數中啊?試想一下如果java為了提供給大多數人使用,他們是不需要jdk做開發的,只需 要jre能讓java程式跑起來就可以了,那麼每個客戶還需要手動去設定環境變數多麻煩啊?所以安裝jre的時候安裝程式自動幫你把jre的 java.exe新增到了系統變數中,驗證的方法很簡單,去Windows/system32下面去看看吧,發現了什麼?有一個java.exe。
3. 難點
如果安裝了JDK,你的電腦就有兩套JRE(JRE本身和JDK中的JRE),前面這套比後面那套少了Server端的Java虛擬機器。
(1)為什麼Sun要讓JDK安裝兩套相同的JRE?這是因為JDK裡面有很多用Java所編寫的開發工具(如javac.exe、jar.exe 等),而且都放置在/lib/tools.jar裡。如果我們將tools.jar改名為tools1.jar,然後執行javac.exe,顯示如下結 果:Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/tools/javac/Main。這個意思是說,你輸入javac.exe與輸入java -cp c:/jdk/lib/tools.jar com.sun.tools.javac.Main 是一樣的,會得到相同的結果。從這裡我們可以證明javac.exe只是一個包裝器(Wrapper),而製作的目的是為了讓開發者免於輸入太長的指命。 而且可以發現/lib目錄下的程式都很小,不大於29K,從這裡我們可以得出一個結論。就是JDK裡的工具幾乎是用Java所編寫,所以也是Java應用 程式,因此要使用JDK所附的工具來開發Java程式,也必須要自行附一套JRE才行,所以位於JDK目錄下的那套JRE就是用來執行一般Java程式 的。
(2)如果一臺電腦安裝兩套以上的JRE,誰來決定呢?這個重大任務就落在java.exe身上。java.exe的工作就是找到合適的JRE來運 行Java程式。java.exe依照以下的順序來查詢JRE:1)自己的目錄下有沒有JRE;2)父目錄有沒有JRE;3)查詢登錄檔: [HKEY_LOCAL_MACHINE/SOFTWARE/JavaSoft/Java Runtime Environment]。所以java.exe的執行結果與你的電腦裡面哪個JRE被執行有很大的關係。
(3)JDK-->JRE-->Bin目錄下有兩個資料夾:server與client,這是真正的jvm.dll所在。 jvm.dll無法單獨工作,當jvm.dll啟動後,會使用explicit的方法(就是使用Win32 API之中的LoadLibrary()與GetProcAddress()來載入輔助用的動態連結庫),而這些輔助用的動態連結庫(.dll)都必須位 於jvm.dll所在目錄的父目錄之中。因此想使用哪個JVM,只需要設定PATH,指向JRE所在目錄下的jvm.dll。
4. 最主流的JDK是Sun公司釋出的JDK,除了Sun之外,還有很多公司和組織都開發了自己的JDK,例如IBM公司開發的JDK,BEA公司的Jrocket,還有GNU組織開發的JDK等等。
普及:Java 與 C++ 的區別
- Java 是純粹的面嚮物件語言,所有的物件都繼承自 java.lang.Object,C++ 為了相容 C 即支援面向物件也支援面向過程。
- Java 通過虛擬機器從而實現跨平臺特性,但是 C++ 依賴於特定的平臺。
- Java 沒有指標,它的引用可以理解為安全指標,而 C++ 具有和 C 一樣的指標。
- Java 支援自動垃圾回收,而 C++ 需要手動回收。
- Java 不支援多重繼承,只能通過實現多個介面來達到相同目的,而 C++ 支援多重繼承。
- Java 不支援操作符過載,雖然可以對兩個 String 物件執行加法運算,但是這是語言內建支援的操作,不屬於操作符過載,而 C++ 可以。
- Java 的 goto 是保留字,但是不可用,C++ 可以使用 goto。
- Java 不支援條件編譯,C++ 通過 #ifdef #ifndef 等預處理命令從而實現條件編譯。
What are the main differences between Java and C++?
JRE or JDK
- JRE is the JVM program, Java application need to run on JRE.
- JDK is a superset of JRE, JRE + tools for developing java programs. e.g, it provides the compiler "javac"