一、虛擬機體系結構
1、 執行引擎:
(1)由軟件實現的執行引擎,每次都一次性解析字節碼;
(2)“即時編譯器”(just-in-time complier),第一次被執行的字節碼會被編譯成本地代碼,
後續的方法調用都直接執行本地代碼,這種方法更快但更耗內存;
(3)自適應優化器。在執行開始的時候會解析字節碼,同時會監控程序的活動,記錄那些
調用頻繁的代碼段,將它編譯成本地方法緩存起來,一個好的自適應優化器可以使得java
虛擬機80-90%都執行本地代碼;
(4)由硬件實現。直接嵌入硬件芯片中,它用本地方法執行字節碼。
2、 類裝載器
(1) 虛擬機內置一個系統類加載器,他沒有父類加載器;
(2) 用戶可以使用java代碼自定義用戶類加載器,以下是一個繼承網絡類加載器的實例:
import java.net.*;
public class ConfigClassLoader extends java.net.URLClassLoader {
/**
* Creates a new instance of ConfigClassLoader.
*/
public ConfigClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
public String toString() {
URL[] urls = getURLs();
StringBuffer sb = new StringBuffer(getClass().getName());
sb.append(" for: ");
for (int i=0; ((urls != null) && (i<urls.length)); ++i) {
sb.append(urls[i].toString()).append(' ');
}
return sb.toString();
}
}
調用實例:
ConfigClassLoader cl =
new ConfigClassLoader(new URL[] {configPath}, Configuration.class.getClassLoader());
(3) 當一個類有用戶自定義的類加載器加載,它所引用的其他類都是用該自定義的類加載器加載;
(4) 每一個自定義的類加載器都有自己的命名空間,不同的命名空間不能相互訪問,除非在程序裏面顯示聲明(public、protected修飾符);
(5) 類加載器通過雙親委派機制來加載類,就是說每個用戶自定義的類加載器必須有一
個父加載器,當使用一個類加載器加載類時,會首先傳遞給父加載器加載,如果父
加載器還有父加載器,會繼續向上傳遞,直到jvm提供的啓動類加載器。
3、 class文件
(1) 由java虛擬機的“機器語言”來替代目標處理器的機器語言,達到平臺無關性的目的;
(2) Class文件的設計緊湊加上它可以按需從任意可以訪問的位置通過類加載器動態加
載,使得java的網絡移動性大大加強。
4、 Java程序設計語言的缺陷
(1) 性能問題。Java虛擬機經過在一個解釋器上執行字節碼->即時編譯器->自適應優化
器性能有了較大改善,但開發者無法確定自己開發的程序在哪一種虛擬機上運行。
當然,Java是一種非常靈活的工具,它提供了很多方法去接解決潛在的性能問題,
如隨程序附帶虛擬機、把對時間要求很嚴格的模塊用本地方法實現、預編譯代碼(
但這樣就損失了Java的動態擴展能力,通常嵌入式系統中就會將程序預編譯好,
直接嵌入到ROM中);
(2) 內存管理。垃圾回收期儘管可以使程序更加健壯,但也給程序運行時的性能帶入了
不確定性,你無法確認垃圾回收器什麼時候開始收集垃圾,無法確認垃圾回收器是
否開始收集垃圾,因爲無法確認它要持續多久。
(3) 線程調度。Java虛擬機規範討論線程調度的地方非常籠統,這種對線程行爲的鬆散
規範有利於將Java虛擬機移植到許多不同類型的硬件上去,但這樣就使得程序員
無法瞭解應該如果調度線程。
(4) 最小公分母。爲了實現平臺無關性,Java在任何嘗試提供跨平臺的API上都會出現
固有的困難。想要給程序提供訪問任何操作系統的系統服務功能的api,就不得不決
定究竟支持哪一些特性。如果該特性只有一種操作系統上存在,API的設計者很有
可能會決定不支持改特性,如果某個特性在大部分的操作系統中,但不是所有的,
設計者可能會決定無論如何都要添加對這個特性的支持。這時就需要在不支持這種
特性的系統平臺上有API模擬實現它。這些最小公分母的選擇都會或多或少得罪
相關操作系統的開發者和終端用戶。
(5) 易於反編譯。因爲java class文件包含了類、方法、字段的詳細信息以及字節碼指令
集等,很易於反編譯,當然可以通過代碼混淆器,通過更改類、字段、方法和局部
變量名來修改類,同時不會改變程序的工作流程,增加解讀的難度。