jvm壓縮包
① jdk 、jre、 jvm概念是什麼關系
jdk包含jre,jre包含jvm。
jdk是開發java代碼用的,包含一些java的庫文件,給你用去寫代碼。有個javac命令可以把.java文件編譯成.class文件
jre是運行java代碼用的。有java命令運行.class文件。
jvm最牛逼。只要符合jvm規則的.class文件都在jvm上面跑,無論是java語言編譯的還是別的語言編譯的都可以。
② 什麼是jvm,jre,jdk及它們之間的關系
JVM:Java虛擬機,它是整個java實現跨平台的最核心的部分,所有的java程序會首先被編譯為.class的類文件,這種類文件可以在虛擬機上執行。
JRE:Java運行環境,光有JVM還不能讓class文件執行,因為在解釋class的時候JVM需要調用解釋所需要的類庫lib。
JDK:Java開發工具包
JDK,JRE,JVM三者關系概括如下:
JDK是JAVA程序開發時用的開發工具包,其內部也有Java運行環境JRE。JRE是Java程序運行時需要的運行環境,就是說如果你光是運行Java程序而不是去搞開發的話,只安裝JRE就能運行已經存在的Java程序了。JDk、JRE內部都包含JAVA虛擬機JVM,JAVA虛擬機內部包含許多應用程序的類的解釋器和類載入器等等。
③ 打開jar格式的壓縮包只需要安裝jvm就可以么
錯 如果你只想打開Jar包查看裡面的內容 WINRAR足夠 和JVM一點關系都沒有 如果你想運行 JVM足夠 java程序 就是運行在JVM平台上的
④ jre和jvm有什麼區別
jdk:是java開發用的,裡面有編譯器。
jre:是運行java程序用的,如果你只是需要運行程序,那隻裝jre就可以了
jvm:jre和jdk都需要jvm的支持,jvm是運行和編譯java程序的核心。
一、 詳細介紹
1、JVM -- java virtual machine
JVM就是我們常說的java虛擬機,它是整個java實現跨平台的 最核心的部分,所有的java程序會首先被編譯為.class的類文件,這種類文件可 以在虛擬機上執行,也就是說class並不直接與機器的操作系統相對應,而是經過虛擬機間接與操作系統交互,由虛擬機將程序解 釋給本地系統執行。
JVM 是 Java 平台的基礎,和實際的機器一樣,它也有自己的指令集,並且在運行 時操作不同的內存區域。 JVM 通過抽象操作系統和 CPU 結構,提供了一種與平台無關的代碼執行方法,即與特殊的實現方 法、主機硬體、主機操作系統無關。但是在一些小的方面, JVM 的實現也是互不相同的,比如垃圾回收 演算法,線程調度演算法(可能不同 OS 有不同的實現)。
JVM 的主要工作是解釋自己的指令集(即位元組碼)到 CPU 的指令集或 OS 的系統調用,保護用戶免被惡意程序騷擾。 JVM 對上層的 Java 源文件是不關心的,它關注的只是由源文件生成的類文件( class file )。類文件的 組成包括 JVM 指令集,符號表以及一些補助信息。
2、JRE -- java runtime environment
JRE是指java運行環境。光有JVM還不能成class的 執行,因為在解釋class的時候JVM需要調用解釋所需要的類庫lib。 在JDK的安裝目 錄里你可以找到jre目錄,裡面有兩個文件夾bin和lib,在 這里可以認為bin里的就是jvm,lib中則是jvm工 作所需要的類庫,而jvm和 lib和起來就稱為jre。所以,在你寫完java程序編譯成.class之後,你可以把這個.class文件 和jre一起打包發給朋友,這樣你的朋友就 可以運行你寫程序了。(jre里有運行.class的java.exe)
JRE 是 Sun 公司發布的一個更大的系統,它裡面就有一個 JVM 。 JRE 就與具體的 CPU 結構和操作系統有關,我們從 Sun 下載 JRE 的時候就看到了不同的各種版本。同 JVM 一起組成 JRE 的還有一些 API (如 awt , swing 等)。 JRE 是運行 Java 程序必不可少的。
JRE ( Java Runtime Environment ),是運行 Java 程序必不可少的(除非用其他一些編譯環境編譯成.exe可執行文件……),JRE的 地位就象一台PC機一樣,我們寫好的Win32應用程序需要操作系統幫 我們運行,同樣的,我們編寫的Java程序也必須要JRE才能運行。
JRE裡面有一個 JVM , JRE 與具體的 CPU 結構和操作系統有關,我們從 Sun 下載 JRE 的時候就看到了不同的各種版本,,同 JVM 一起組成 JRE 的還有 一些 API (如 awt , swing 等), JRE 是 運行 Java 程序必不可少的.
3、JDK -- java development kit
JDK是java開發工具包,基本上每個學java的人都會先在機器 上裝一個JDK,那他都包含哪幾部分呢?讓我們看一下JDK的安裝目錄。在目錄下面有 六個文件夾、一個src類庫源碼壓縮包、和其他幾個聲明文件。其中,真正在運行java時起作用的 是以下四個文件夾:bin、include、lib、 jre。現在我們可以看出這樣一個關系,JDK包含JRE,而JRE包 含JVM。
bin:最主要的是編譯器(javac.exe)
include:java和JVM交互用的頭文件
lib:類庫
jre:java運行環境
(注意:這里的bin、lib文件夾和jre里的bin、lib是 不同的)總的來說JDK是用於java程序的開發,而jre則 是只能運行class而沒有編譯的功能。
eclipse、idea等 其他IDE有自己的編譯器而不是用JDK bin目錄中自帶的,所以在安裝時你會發現他們只要求你 選中jre路徑就ok了。
二、 三者聯系
Java 喊出的帶有標志性的口號「 Write Once , Run Anywhere (一次編寫,到處運行)」,正是建立在 JRE 的基礎之上。何以實現?就是在 Java 應用程序和操作系統之間增加了一虛擬層—— JRE 。
程序源代碼不是直 接編譯、鏈接成機器代碼,而是先轉化到位元組碼( bytecode ) 這種特殊的中間形式,位元組碼再轉換成機器碼或系統調用。前者是傳統的編譯方法,生成的機器代碼就不可避免地跟特殊的操作系統和特殊的機器結構相關。
而 Java 程序的位元組碼文件可以放到任意裝有 JRE 的計算機運行,再由不同 JRE 的將它們轉化成相應的機器代碼,這就實現了 Java 程序的可移植性。這樣程序員也不用去 關心程序運行的具體環境,而可以專心編寫軟體。這種分層抽象、隱藏細節的思想在計算機科學中處處可見,比如機器組織結構的設計、網路協議的實現等。 Pascal 語言的發明者 Niklaus Wirth ,就富有預見性地指出應該有這樣一種可移植的語言,其生成的中間代碼可以在一台假想的機器( a hypothetical machine )上運行。
而 Java 虛擬機( Java virtual machine 或 JVM )就是這樣的一台機器,它模擬實際處理器的結構,解釋位元組碼。 怎麼一會說是 JRE ,一會兒又成了 JVM ,兩者是否同物不同名? 回答是否定的。
JRE的地位就象一台PC機一樣,我們寫好的Win32應用程序需要操作系統幫 我們運行,同樣的,我們編寫的Java程序也必須要JRE才能運行。
要運行Applet,在客戶端必須安裝有 JRE,即「運行時」,容易一點理解,就象所謂的「插件」,要開發JAVA應用程序\Web應用,就必須在伺服器端安裝相應的 JVM+JDK 了(開發應用 Java web應用 時,客戶端不需要安裝任何的JVM)
如果你使用JAVA開發應用,就需要安裝 JRE+JDK,就是 J2SE.
如果在客戶端運行Applet,客戶端瀏覽器必須嵌有JAVA JVM,如果沒有,就需要安裝,即: 在客戶端創建JRE(運行時,包含JVM),而客戶端是不需要做開發的,所以,JDK就沒有必要安裝 了。
不同版本的Applet在不同的JVM下可能無法正常運行,而Microsoft JVM只是Sun JVM的「低版本」,微軟在windows xp/2003中乾脆將JVM去掉了.
⑤ JDK,JRE,JVM區別與聯系
JVM -- java virtual machine
JVM就是我們常說的java虛擬機,它是整個java實現跨平台的 最核心的部分,所有的java程序會首先被編譯為.class的類文件,這種類文件可 以在虛擬機上執行,也就是說class並不直接與機器的操作系統相對應,而是經過虛擬機間接與操作系統交互,由虛擬機將程序解 釋給本地系統執行。
JVM 是 Java 平台的基礎,和實際的機器一樣,它也有自己的指令集,並且在運行 時操作不同的內存區域。 JVM 通過抽象操作系統和 CPU 結構,提供了一種與平台無關的代碼執行方法,即與特殊的實現方 法、主機硬體、主機操作系統無關。但是在一些小的方面, JVM 的實現也是互不相同的,比如垃圾回收 演算法,線程調度演算法(可能不同 OS 有不同的實現)。
JVM 的主要工作是解釋自己的指令集(即位元組碼)到 CPU 的指令集或 OS 的系統調用,保護用戶免被惡意程序騷擾。 JVM 對上層的 Java 源文件是不關心的,它關注的只是由源文件生成的類文件( class file )。類文件的 組成包括 JVM 指令集,符號表以及一些補助信息。
JRE -- java runtime environment
JRE是指java運行環境。光有JVM還不能成class的 執行,因為在解釋class的時候JVM需要調用解釋所需要的類庫lib。 在JDK的安裝目 錄里你可以找到jre目錄,裡面有兩個文件夾bin和lib,在 這里可以認為bin里的就是jvm,lib中則是jvm工 作所需要的類庫,而jvm和 lib和起來就稱為jre。所以,在你寫完java程序編譯成.class之後,你可以把這個.class文件 和jre一起打包發給朋友,這樣你的朋友就 可以運行你寫程序了。(jre里有運行.class的java.exe)
JRE 是 Sun 公司發布的一個更大的系統,它裡面就有一個 JVM 。 JRE 就與具體的 CPU 結構和操作系統有關,我們從 Sun 下載 JRE 的時候就看到了不同的各種版本。同 JVM 一起組成 JRE 的還有一些 API (如 awt , swing 等)。 JRE 是運行 Java 程序必不可少的。
JRE ( Java Runtime Environment ),是運行 Java 程序必不可少的(除非用其他一些編譯環境編譯成.exe可執行文件……),JRE的 地位就象一台PC機一樣,我們寫好的Win32應用程序需要操作系統幫 我們運行,同樣的,我們編寫的Java程序也必須要JRE才能運行。
JRE裡面有一個 JVM , JRE 與具體的 CPU 結構和操作系統有關,我們從 Sun 下載 JRE 的時候就看到了不同的各種版本,,同 JVM 一起組成 JRE 的還有 一些 API (如 awt , swing 等), JRE 是 運行 Java 程序必不可少的.
JDK -- java development kit
JDK是java開發工具包,基本上每個學java的人都會先在機器 上裝一個JDK,那他都包含哪幾部分呢?讓我們看一下JDK的安裝目錄。在目錄下面有 六個文件夾、一個src類庫源碼壓縮包、和其他幾個聲明文件。其中,真正在運行java時起作用的 是以下四個文件夾:bin、include、lib、 jre。現在我們可以看出這樣一個關系,JDK包含JRE,而JRE包 含JVM。
bin:最主要的是編譯器(javac.exe)
include:java和JVM交互用的頭文件
lib:類庫
jre:java運行環境
(注意:這里的bin、lib文件夾和jre里的bin、lib是 不同的)總的來說JDK是用於java程序的開發,而jre則 是只能運行class而沒有編譯的功能。
eclipse、idea等 其他IDE有自己的編譯器而不是用JDK bin目錄中自帶的,所以在安裝時你會發現他們只要求你 選中jre路徑就ok了。
三者聯系
Java 喊出的帶有標志性的口號「 Write Once , Run Anywhere (一次編寫,到處運行)」,正是建立在 JRE 的基礎之上。何以實現?就是在 Java 應用程序和操作系統之間增加了一虛擬層—— JRE 。
程序源代碼不是直 接編譯、鏈接成機器代碼,而是先轉化到位元組碼( bytecode ) 這種特殊的中間形式,位元組碼再轉換成機器碼或系統調用。前者是傳統的編譯方法,生成的機器代碼就不可避免地跟特殊的操作系統和特殊的機器結構相關。
而 Java 程序的位元組碼文件可以放到任意裝有 JRE 的計算機運行,再由不同 JRE 的將它們轉化成相應的機器代碼,這就實現了 Java 程序的可移植性。這樣程序員也不用去 關心程序運行的具體環境,而可以專心編寫軟體。這種分層抽象、隱藏細節的思想在計算機科學中處處可見,比如機器組織結構的設計、網路協議的實現等。 Pascal 語言的發明者 Niklaus Wirth ,就富有預見性地指出應該有這樣一種可移植的語言,其生成的中間代碼可以在一台假想的機器( a hypothetical machine )上運行。
而 Java 虛擬機( Java virtual machine 或 JVM )就是這樣的一台機器,它模擬實際處理器的結構,解釋位元組碼。 怎麼一會說是 JRE ,一會兒又成了 JVM ,兩者是否同物不同名? 回答是否定的。
JRE的地位就象一台PC機一樣,我們寫好的Win32應用程序需要操作系統幫 我們運行,同樣的,我們編寫的Java程序也必須要JRE才能運行。
要運行Applet,在客戶端必須安裝有 JRE,即「運行時」,容易一點理解,就象所謂的「插件」,要開發JAVA應用程序Web應用,就必須在伺服器端安裝相應的 JVM+JDK 了(開發應用 Java web應用 時,客戶端不需要安裝任何的JVM)
如果你使用JAVA開發應用,就需要安裝 JRE+JDK,就是 J2SE.
如果在客戶端運行Applet,客戶端瀏覽器必須嵌有JAVA JVM,如果沒有,就需要安裝,即: 在客戶端創建JRE(運行時,包含JVM),而客戶端是不需要做開發的,所以,JDK就沒有必要安裝 了。
不同版本的Applet在不同的JVM下可能無法正常運行,而Microsoft JVM只是Sun JVM的「低版本」,微軟在windows xp/2003中乾脆將JVM去掉了.
⑥ jvm會先去方法區中找有沒有相應類的.class存在.如果有,就直接使用
1.類載入器深入剖析
Java虛擬機與程序的生命周期 :
當我們執行一個java程序的時候 , 會啟動一個JVM進程 , 當程序執行完之後 , JVM進程就消亡了 ;
在如下情況下JVM將結束聲明周期 :
System.exit(int)方法 , 當執行這個方法的時候 , 虛擬機會退出 ; 這個方法傳入一個整形參數 , 這個參數是狀態嗎 : 如果這個整形是 0 的話 , 就是正常退出 , 如果不是0的話 , 就是異常退出 ;
程序正常結束 ;
程序執行過程中 , 遇到了異常或錯誤 , 而異常終止 : 如果我們在程序中出現了異常 , 而不去處理 , 會將異常一直拋給main函數 , main函數會將異常拋給JVM , JVM如果處理不了異常 , JVM就會異常退出 ;
由於操作系統出現錯誤導致JVM進程終止 : JVM所依賴的平台出現錯誤 , 導致JVM終止 ;
2.類的載入,連接和初始化
載入 : 查找並載入類的二進制數據 , 將class位元組碼文件載入到內存中 ;
連接 :
-
驗證
: 確保被載入的類的正確性 , 使用javac 編譯工具生成的位元組碼文件能通過驗證 , 如果不是由javac編譯生成的位元組碼文件 , 如果自己生成的位元組碼文件不符合JVM虛擬機對位元組碼文件的要求的話 , 可能會出現驗證通不過的情況 ; 比如說隨便拿一個文件 , 將後綴名直接修改為.class , 這樣的位元組碼文件肯定不合法 ;
-
准備
: 為類的靜態變數分配內存 , 並將其初始化為默認值 ;
-
解析
: 把類中的符號引用轉為直接引用 ;
初始化 : 為類的靜態變數賦予正確的初始值(正確的值指的是用戶賦的值) ;
-好像這個與連接階段的准備有些重復 , 在連接的准備階段只是賦予初始變數 , 如果用戶給這個變數賦了初始值 , 那麼這個變數在連接的准備階段仍然會賦予初始值 ;
-在這個階段 , 才會真正的將初始值賦給靜態變數 ;
Java程序對類的使用方式有 主動使用 和 被動使用 ;
所有的JVM實現 , 必須在每個類或者介面 , 被java程序 「首次主動使用」 時才初始化他們 ;
主動使用 :
創建類的實例 ;
訪問某個類或介面的靜態變數 , 或者對該靜態變數賦值 ;
調用類的靜態方法 ;
反射 : Class.forName(「類名」) ;
初始化一個類的子類 , 看做對父類的主動使用 ;
java虛擬機啟動的時候 , 被標明啟動類的類 , 即包含main方法的類 , 程序的入口 ;
除了上面6種主動使用之外 , 其它的情況均為被動使用 , 其它情況都不會執行第三步初始化 ;
3.類的載入
(1)概念
類的載入 : 指的是將類的.class文件中的二進制數據讀入到內存中 , 將其放在運行時數據區的方法區內 , 然後再堆區創建一個java.lang.Class對象 , 用來封裝類在方法區內的數據結構 ;
反射 : 反射就是跟句堆區的位元組碼文件 , 獲取方法去的數據結構 ;
解析 : Class對象是由JVM自己創建的 , 所有的對象都是經過Class對象創建 , 這個Class對象是反射的入口, 通過Class對象 , 可以關聯到目標class位元組碼文件的內部結構 ;
所有的類對應的Class對象都是唯一的一個 , 這個類是由JVM進行創建的 , 並且只有JVM才會創建Class對象 ;
類載入的最終產品是位於堆區中的Class對象 , Class對象封裝了類在方法區內的數據結構 , 並且向Java程序員提供了訪問方法區內的數據結構的介面(反射用的介面) ;
(2)載入.class文件的方式
從本地系統中直接載入 : 編譯好的.class位元組碼文件直接從硬碟中載入 ;
通過網路下載.class文件 : 將class位元組碼文件放在網路空間中 , 使用URLClassLoader來載入在網路上的.class位元組碼文件 , 使用默認的父親委託機制載入位元組碼文件 ;
從zip , jar 等壓縮文件中載入位元組碼文件 : 在開發的時候 , 導入jar包 , 就是這種方式 ;
從專有的資料庫中提取位元組碼文件 ;
將java源文件動態編譯為位元組碼文件 ;
(3)類載入器
l Java虛擬機自帶的類載入器 :
-根類載入器 ( Bootstrap ) : 是C++寫的 , 程序員無法再java代碼中獲取這個類 , 如果使用getClassLoader()方法獲取到的是一個null值 ;
package jvm;
Java代碼
public class ClassLoaderTest {
public static void main(String[] args) throws Exception {
//java.lang包下的類使用的是跟類載入器進行載入的
Class clazz = Class.forName("java.lang.String");
System.out.println(clazz.getClassLoader());
//自定義的類使用的是應用類載入器(系統載入器)
Class clazz2 = Class.forName("jvm.C");
System.out.println(clazz2.getClassLoader());
}
}
class C{}
執行結果 :
null
Java代碼
sun.misc.Launcher$AppClassLoader@1372a1a
-擴展類載入器 ( Extension ) : Java編寫 ;
-系統類載入器(應用載入器) ( System ) : Java編寫 ;
用戶自定義的類載入器 :
-自定義的類載入器都是java.lang.ClassLoader子類 ;
-用戶可以定製類的載入方式
String類是由根類載入器進行載入的 , 我們可以調用Class對象的
關於代理中創建對象的類載入器 : 創建代理對象的時候 , 動態創建一個類 , 然後使用指定的類載入器將這個類載入到內存中 , 然後用載入到內存中的類生成代理對象 ;
創建代理對象的方法 : newProxyInstance(ClassLoader loader , Class [] Interfaces , InvocationHandler h )
loader 是定義的代理類的類載入器 , 中間的介面數組是代理類的要實現的介面列表 , h 是指派方法調用的調用處理程序 ;
類載入器並不需要在某個類被 「首次主動使用」 時再載入它 :
-預載入機制 : JVM規范允許類載入器在預料某個類將要被使用的時就預先載入它 ;
-報錯時機 : 如果在預載入的過程中遇到了位元組碼文件缺失或者存在錯誤的情況 , 類載入器會在程序首次主動使用(上面提到的六種情況)該類的時候報錯(LinkageError錯誤) ;
-不報錯時機 : 如果這個錯誤的位元組碼文件所對應的類一直沒有被使用 , 那麼類載入器就不會報告錯誤 ,即便有錯誤也不會報錯 ;
LinkageError : 這個錯誤是Error的子類 , 程序不能處理這些錯誤 , 這些錯誤都是由虛擬機來處理 , 這個錯誤表示出錯的是子類 , 在一定程序上依賴於另一個類 , 在編譯了前面一個類的時候 , 與後面所依賴的類出現了不兼容的情況 ;
例如 : 我們使用了jdk 1.6 在編譯一個程序 , 但是運行環境是jre1.5的 , 就會出現LinkageError錯誤 ;
4.類的連接
(1)定義
類被載入之後 , 就進入鏈接階段 ; 鏈接 : 將已讀入內存的二進制數據合並到虛擬機的運行時環境中去 ;
鏈接顧名思義就是講類與類之間進行關聯 , 例如我們在類A中調用了類B , 在鏈接過程中 , 就將A與B進行鏈接 ,將面向對象語言轉化為面向過程語言 ;
(2)類的驗證
類文件的結構檢查 : 確保類文件遵從java類文件的固定格式 , 開始類的描述 , 聲明 , 方法調用格式等 ;
語義檢查 : 確保類本身符合java語言的語法規定 , 比如final類型的類沒有子類 , final類型的方法沒有被覆蓋 ,在eclipse中這種錯誤編譯的時候不能通過 , 但是通過其他的方法可以生成錯誤的位元組碼文件 , 這里就是檢測惡意生成的位元組碼文件 ;
位元組碼驗證 : 確保位元組碼流可以被JVM安全的執行 , 位元組碼流代表java方法(包括靜態方法和實例方法) , 它是由被稱作操作碼的單位元組指令組成的序列 , 每一個操作碼後面跟著一個或多個操作數 , 位元組碼驗證步驟會檢查每個操作碼是否合法 , 即是否有著合法的操作數 ;
下面是指令碼組成的序列 , 類似於微指令 :
Jvm編譯指令代碼代碼
// Compiled from ByteToCharCp1122.java (version 1.5 : 49.0, super bit)
public class sun.io.ByteToCharCp1122 extends sun.io.ByteToCharSingleByte {
// Field descriptor #17 Lsun/nio/cs/ext/IBM1122;
private static final sun.nio.cs.ext.IBM1122 nioCoder;
// Method descriptor #18 ()Ljava/lang/String;
// Stack: 1, Locals: 1
public java.lang.String getCharacterEncoding();
0 ldc <String "Cp1122"> [1]
2 areturn
Line numbers:
[pc: 0, line: 25]
// Method descriptor #2 ()V
// Stack: 2, Locals: 1
public ByteToCharCp1122();
0 aload_0 [this]
1 invokespecial sun.io.ByteToCharSingleByte() [25]
4 aload_0 [this]
5 getstatic sun.io.ByteToCharCp1122.nioCoder : sun.nio.cs.ext.IBM1122 [23]
8 invokevirtual sun.nio.cs.ext.IBM1122.getDecoderSingleByteMappings() : java.lang.String [27]
11 putfield sun.io.ByteToCharSingleByte.byteToCharTable : java.lang.String [24]
14 return
Line numbers:
[pc: 0, line: 28]
[pc: 4, line: 29]
[pc: 14, line: 30]
// Method descriptor #2 ()V
// Stack: 2, Locals: 0
static {};
0 new sun.nio.cs.ext.IBM1122 [15]
3 p
4 invokespecial sun.nio.cs.ext.IBM1122() [26]
7 putstatic sun.io.ByteToCharCp1122.nioCoder : sun.nio.cs.ext.IBM1122 [23]
10 return
Line numbers:
[pc: 0, line: 22]
}
l 二進制兼容性的驗證 : 確保相互引用的類之間協調一致的 ; 例如在A類的a()方法中調用B類的b()方法 , JVM在驗證A類的時候 , 會驗證B類的b()方法 , 加入b()方法不存在 , 或者版本不兼容(A,B兩類使用不同的JDK版本編譯) , 會拋出NoSuchMethodError錯誤 ;
(3)准備階段
在准備階段 , JVM為類的靜態變數分配內存空間 , 並設置默認的初始值 . 例如下面的Sample類 , 在准備階段 ,為int類型的靜態變數分配4個位元組 , 並賦予初始值 0 ; 為long 類型的靜態變數 b , 分配8個位元組 , 並賦予初始值 0 ;
PS : 在java中基本類型變數佔用的空間是一定的 , java運行在JVM上的 , 在C中 , 就要根據平台變化而變化了 ;
public class Sample {
Java代碼
private static int a = 1 ;
private static long b ;
static {
b = 2 ;
}
(4)類的解析
在解析階段 , JVM 會把類的二進制數據中的符號引用替換為直接引用 , 例如在A類中的a()方法引用B類中的b()方法 ;
在A類的二進制數據中包含了一個對B類的b()方法的符號引用 , 這個符號引用由b()方法的全名和相關的描述符組成 , 在Java解析階段 , 就會把這個符號引用替換為指針 , 這個指針就是C語言中的指針了 , 該指針指向B類的b()方法在方法區中的內存位置 , 這個指針就是直接引用 ;
5.類的初始化
在初始化階段 , Java虛擬機執行類的初始化操作 , 為類的靜態變數賦予初始值 , 在程序中 , 靜態變數初始化有兩種途徑 :
直接在聲明處進行初始化 , 例如下面的Sample中的 變數a ;
在靜態代碼塊中進行初始化 , 例如下面的Sample中的變數b ;
Java代碼
public class Sample {
private static int a = 1 ;
private static long b ;
static {
b = 2 ;
}
}
6.面試題介紹
Java代碼
public class PrepareOrInit {
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
System.out.println(singleton.count1);
System.out.println(singleton.count2);
}
}
class Singleton{
private static Singleton singleton = new Singleton() ;
public static int count1 ;
public static int count2 = 0 ;
private Singleton(){
count1 ++ ;
count2 ++ ;
}
public static Singleton getInstance(){
return singleton ;
}
}
執行結果 : 1 0
分析 : 這段代碼與類的鏈接中的准備階段 和 初始化階段 有關系 , 准備階段是給靜態的欄位賦予默認值 , 初始化階段給靜態變數賦予正確的值 , 即用戶的值 ;
在主函數中 , 調用了類的靜態方法 , 相當於主動使用 , 這里調用了類的靜態方法 ;
之後進行連接的准備操作 , 給類中的靜態變數賦予初值 , singleton值為null , count1 與 count2 值為0 ;
執行初始化操作 , 給類中的靜態變數賦予正確的值 , 給singleton變數賦予正確的值 , 調用構造方法 , 此時count1與 count2執行自增操作 , 兩者都變成1 , 然後執行count1的賦予正確值操作 , 這里用戶沒有賦值操作 , count2 用戶進行了 賦值為0的操作 , 0將原來的1覆蓋掉了 , 因此結果為 1 , 0 ;
Java代碼
public class PrepareOrInit {
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
System.out.println(singleton.count1);
System.out.println(singleton.count2);
}
}
class Singleton{
public static int count1 ;
public static int count2 = 0 ;
private static Singleton singleton = new Singleton() ;
private Singleton(){
count1 ++ ;
count2 ++ ;
}
public static Singleton getInstance(){
return singleton ;
}
}
執行結果 : 1 1
在准備階段count1 和 count2 都賦值為0 , 然後在初始化階段 , 全部賦值為1 ;
⑦ 寫的打包好的jar軟體為什麼在電腦上顯示壓縮包,運行不了。
辛辛苦苦寫了個java的DES字元加解密程序,准備送給朋友的,做完導出成JAR文件,卻發現不能運行。Could not find the main class:Mycipher.jar Program will exit.郁悶大了,之前做個很多的jar文件都能運行的,這次確不行,上網搜了搜,問的一大堆,卻沒真正解決問題的原因,決定自己動手了。
程序再Eclipse中能運行,程序肯定沒有問題,用Eclipse的向導導出應該也不會有問題,唉,直接執行不了,到cmd試一下,java -jar MyCipher.jar,報錯了,一看錯誤,是某個類找不到,這個類是我應用的jar文件里的,這讓我想到了jvm的類裝載機制,一定是類裝載器在當前路徑里找不到我引入的jar文件里的類。終於讓我發現的問題的真正原因。
解決辦法:
1.把lib目錄里的jar文件一一解壓,把解壓後的類文件連同目錄添加到Mycipher.JAR文件中,很easy的搞定。
2.修改MANIFEST.MF文件的Class-Path屬性的值(目錄路徑用/或者.代替,jar之間用空格分開)如:Class-Path: ../lib/miglayout-3.5.5.jar ../lib/TableLayout.jar ../lib/swing-layout-1.0.jar,同時把用到的jar文件放到指定的路徑下。謝謝採納
⑧ JRE與JVM、JDK的區別
jre是java的運行環境,jdk是java的開發工具包,jvm則是讓java能夠在任何平台運行的虛擬機。其中關系是jdk包含jre和tools(工具類),而jre下包含類庫和jvm
⑨ 下了java後,打開壓縮包,但是裡面找不到除 Shimeji.exe 這個格式之外的Shimeji ,
認准這個jar後綴的文件再這樣打開就對了。沒有這個shimeji.jar就重新下過吧
⑩ 1. JDK、JRE、JVM分別表示什麼意思。
JVM :JVM是Java Virtual Machine(Java虛擬機)的縮寫,它是整個java實現跨平台的最核心的部分,所有的java程序會首先被編譯為.class的類文件,這種類文件可以在虛擬機上執行,也就是說class並不直接與機器的操作系統相對應,而是經過虛擬機間接與操作系統交互,由虛擬機將程序解釋給本地系統執行。JVM是Java平台的基礎,和實際的機器一樣,它也有自己的指令集,並且在運行時操作不同的內存區域。 JVM通過抽象操作系統和CPU結構,提供了一種與平台無關的代碼執行方法,即與特殊的實現方法、主機硬體、主機操作系統無關。JVM的主要工作是解釋自己的指令集(即位元組碼)到CPU的指令集或對應的系統調用,保護用戶免被惡意程序騷擾。 JVM對上層的Java源文件是不關心的,它關注的只是由源文件生成的類文件(.class文件)。
JRE:JRE是java runtime environment(java運行環境)的縮寫。光有JVM還不能讓class文件執行,因為在解釋class的時候JVM需要調用解釋所需要的類庫lib。在JDK的安裝目錄里你可以找到jre目錄,裡面有兩個文件夾bin和lib,在這里可以認為bin里的就是jvm,lib中則是jvm工作所需要的類庫,而jvm和lib和起來就稱為jre。所以,在你寫完java程序編譯成.class之後,你可以把這個.class文件和jre一起打包發給朋友,這樣你的朋友就可以運行你寫程序了(jre里有運行.class的java.exe)。JRE是Sun公司發布的一個更大的系統,它裡面就有一個JVM。JRE就與具體的CPU結構和操作系統有關,是運行Java程序必不可少的(除非用其他一些編譯環境編譯成.exe可執行文件……),JRE的地位就象一台PC機一樣,我們寫好的Win32應用程序需要操作系統幫我們運行,同樣的,我們編寫的Java程序也必須要JRE才能運行。
JDK:JDK是java development kit(java開發工具包)的縮寫。每個學java的人都會先在機器上裝一個JDK,那 讓我們看一下JDK的安裝目錄。在目錄下面有六個文件夾、一個src類庫源碼壓縮包、和其他幾個聲明文件。其中,真正在運行java時起作用的是以下四個文件夾:bin、include、lib、jre。現在我們可以看出這樣一個關系,JDK包含JRE,而JRE包含JVM。
bin:最主要的是編譯器(javac.exe)
include:java和JVM交互用的頭文件
lib:類庫
jre:java運行環境
(注意:這里的bin、lib文件夾和jre里的bin、lib是不同的)總的來說JDK是用於java程序的開發,而jre則是只能運行class而沒有編譯的功能。eclipse、idea等其他IDE有自己的編譯器而不是用JDK bin目錄中自帶的,所以在安裝時你會發現他們只要求你選jre路徑就ok了。