java的這種適合網路環境的能力是由其體繫結構決定的,它可以保證安全的、健壯的且和平台無關的程式通過網路傳播,在很多不同的電腦和裝置上運行。
體繫結構包括四個獨立但相關的技術:
- java程式設計語言
- java class檔案
- java應用編程介面(API)
- java虛擬機器
用java程式設計語言編寫原始碼,把它編譯成java class檔案,然後再在java虛擬機器中運行class檔案。當程式啟動並執行時候,它通過調用class檔案中實現了java API的方法來滿足程式的java API調用。
java虛擬機器和java API組成了一個“平台”,所有java程式都在這上面編譯。被稱為“java運行時系統”,或者“java平台”。
----------------java虛擬機器:
java面向網路的核心就是java虛擬機器,它支援java面向網路體繫結構三大支柱的所有方面:平台無關性、安全性、網路移動性。
java虛擬機器上一台抽象的電腦,其規範定義了每個java虛擬機器都必須實現的特性,但是為每個特定實現都留下了很多選擇。(比如都要能執行位元組碼,但是執行的技術可以自己選擇)。
java虛擬機器的主要任務就是裝載class檔案並執行其中的位元組碼。虛擬機器包含一個類裝載器,它可以從程式和API中裝載class檔案。java API中只有程式執行時需要的那些類才會被裝載。位元組碼由執行引擎來執行。
不同java虛擬機器中,執行引擎可能實現得非常不同:
- “一次性解釋位元組碼”,是軟體實現的虛擬機器中,最簡單的引擎。
- “即使編譯器”,更快、但是消耗記憶體。這時,在第一次被執行的位元組碼會被編譯成本地機器代碼。編譯出的本地機器代碼會被緩衝,當方法以後被調用的時候可以重用。
- “自適應最佳化器”,這時,虛擬機器開始的時候解釋位元組碼,但是會見時運行中的程式活動,並記錄下使用最頻繁的程式碼片段,程式運行時時,虛擬機器會只把活動最頻繁的代碼編譯成本地機器代碼,其它的代碼由於使用不頻繁,繼續保留成位元組碼——由虛擬機器繼續解釋它們。
- 最後一種虛擬機器由硬體晶片後成,它用本地方法執行java位元組碼,這種執行那個引擎實際上是內嵌在晶片裡的。
當java虛擬機器由主機作業系統的軟體實現時,java程式通過調用本地方法和主機互動。
java中有兩種方法:java方法和本地方法。
- java方法是由java語言編寫,編譯成位元組碼,儲存在class檔案中。
- 本地方法是由其它語言(比如C、C++,或者組合語言)編寫的,編譯成和處理器相關的機器代碼。儲存在動態連結程式庫中,格式是各個平台專有的。
java方法是平台無關的。
本地方法是平台有關的。
運行中的java程式調用本地方法時,虛擬機器裝載包含這個本地方法的動態庫,並調用這個方法。本地方法是聯絡java程式和底層主機作業系統的串連方法。
----------------類裝載器體繫結構:
一個java程式可以使用兩種類裝載器:啟動類裝載器和使用者定義類裝載器。
啟動類裝載器(系統唯一)是java虛擬機器實現的一部分。
java程式能夠在運行時安裝使用者定義的類裝載器。這種類裝載器能夠使用自訂的方式來裝載類。
啟動類裝載器是虛擬機器實現的本質部分,但是使用者定義類裝載器不是。但使用者類裝載器能夠用java編寫,能夠被編譯成class檔案,能夠被虛擬機器裝載,能夠像其他類一樣執行個體化,他們實際上只是運行中的java應用程式可執行代碼的一部分。
由於有使用者定義類裝載器,所以不必在編譯的時候就知道運行中的java程式中最終會加入的所有類。使得在運行時擴充java程式稱為可能。但它運行時程式能夠決定它需要哪些額外的類,能夠決定是使用一個或是更多的使用者定義類裝載器來裝載。
每一個類被裝載的時候,java虛擬機器都監視這個類,看他到底是被哪個類裝載器裝載。當被裝載的類引用了另一個類時,虛擬機器會使用裝載第一個類的類裝載器來裝載被引用的類。
java程式能夠從一個或多個類中執行個體化多個使用者定義類裝載器。所以需要多少個使用者定義類裝載器就能建立多少個。被不同的類裝載器裝載的類存放在不同的命名空間中,它們不能互相訪問,除非應用程式顯示地允許這樣做。
當編寫應用程式的時候,從不同源檔案裝載的類可以分隔在不同的命名空間中。這樣就能夠使用java類裝載器的體繫結構來控制任何從不同源檔案中裝載的代碼之間的互相應用,特別是能夠阻止惡意代碼擷取訪問和破壞善意代碼的許可權。
網路移動性的支援:允許執行個體化使用者定義類裝載器來知道如何從網路下載class檔案。
安全性的支援:允許使用不同的使用者定義類裝載器裝載不同來源的class檔案,把不同來源的class檔案放置在不同的命名空間中,這就能夠限制或阻止不同來源的代碼之間的互相訪問。
----------------java class檔案:
平台無關性:
- 為java程式提供獨立於底層主機平台的二進位形式的服務。
- java class檔案是可以運行在任何支援java虛擬機器的硬體平台和作業系統的二進位檔案。
- java編譯器把java源檔案的指令翻譯成位元組碼,這種位元組碼就是java虛擬機器的“機器語言”。
- java class檔案中位元組順序是高位在前,這與使用何種平台產生這個檔案和何種平台上使用這個檔案都沒關係。
網路移動性:
- class檔案設計得緊湊,因此可快速在網路上傳送。
- 由於java程式是動態連結和動態擴充的,class可以在需要的時候下載。
----------------java API:
java API是運行庫的集合,它提供一套訪問主機系統資源的標準方法。
所有被裝載的class檔案和所有已經裝載的動態庫共同組成了java虛擬機器上啟動並執行整個程式。
平台無關性:在每個特定的主機平台上都明確地實現了java虛擬機器和java API。
----------------java程式設計語言:
java能夠提高開發人員的效率,這種效率主要來自java對直接記憶體操作的約束。
(在C++中:不再使用的對象沒有被釋放會導致記憶體流失;多次釋放一個對象會導致記憶體衝突。這兩種情況都會導致C++程式崩潰。)
提高開發人員的效率+為終端使用者增強健壯性。
----------------java體繫結構的代價:
- 和其它技術(如C++)相比,java程式的執行速度可能較低,這是java在面向網路特性上的主要代價之一(虛擬機器效能問題[執行引擎的效率])。
- 因為跨平台,所以要保證在多種虛擬機器上都有令人滿意的效能。隨著代碼和對象通過網路在虛擬機器之間移動,開發人員也無從知曉他們的程式究竟會運行在哪些虛擬機器上
- java在記憶體管理和線程調度上的缺陷,垃圾收集器可以使得許多程式更加健壯,但是在程式運行時的效能加入了一些不確定性(無法確定gc什麼時候開始收集垃圾,無法確認是否開始收集垃圾,無法確認垃圾收集要持續多長時間);java虛擬機器規範討論區對話調度的地方非常籠統,這種對線程行為的鬆散規範有利於將java虛擬機器移植到許多不同類型的硬體上去,但是這種線程管理使得程式員無法瞭解應該如何調度線程,無法控制線程調度。
- 為了實現平台無關性,引發的最小公分母問題。各個作業系統之間雖然有許多共性,但是每個作業系統通常都有一些自己的特性。在大多數os上由的特性,可能會被添加到java的os系統服務API中,但是這時還要在不具備這個特性的的os上由API類比實現它。
- 容易被逆向編譯。因為java class檔案與java程式語言之間是緊密聯絡的,和java天生的動態連結特性,所以從一個類到另一個類的引用時符號化的。在java class中,指向另一個類的引用通過字串清楚地標明了所指向的這個類的名字。如果引用指向一個欄位,則這個欄位的名稱和描述符(欄位類別)都會被詳細說明;如果這個引用指向的是一個成員方法,則這個成員方法的名稱和描述符(傳回型別,方法參數數量和類型)也會被詳細說明。還包含了自己欄位和成員方法的符號引用和可選的調試資訊(包含局部變數名稱和類型)。
一個class檔案的符號資訊,以及位元組碼指令集和java語言之間的密切關係,這些方法使得把java class檔案逆向編譯為java源碼檔案相當容易。
(可以用混淆器來混淆你的class檔案,通過改變類、欄位、方法和、局部變數的名字,但它不改變工作流程)。
----------------總結:
java程式設計語言是一種十分通過的語言,它和其他技術相比有著明顯的優勢,特別是java能在極大程度上提高程式員的效率,增強程式的健壯性,與老的程式設計技術(比如C、C++)相比,具有過得去的效能。