JVM是什麼?
JVM(Java Virtual Machine,Java虛擬機):java程序首先需要通過javac來編譯,生成.class文件,然後通過java.exe(windows上)去運行,實際上java.exe是會去裝載jvm.dll不同平臺下是不一樣的(linux下的libjvm.dll)。
jvm是jre的一部分,他是一個虛構出來的計算機,擁有自己完善的硬件架構,如處理器、堆棧、寄存器等。
更多關於JVM的概念介紹:百度百科
JVM結構
JVM內部大概分爲三個部分,分別是類裝載器(ClassLoader)子系統,運行時數據區(Runtime Data Area)、和執行引擎(ExecutionEngine):
類裝載器(ClassLoader)子系統
其主要作用是將class文件進行裝載,然後可以得到該類的類類型,然後類類型的實例化就是新建每個新的對象,但是他們的信息都是與模板一樣:如下圖
類加載器出去用戶自定義有三種:
- BootStrap:啓動類加載器,C++編寫的,java的根基 rt.jar (Runtime)
- Extension:擴展類加載器 Java 用於java擴展的 jar
- AppClassLoader:應用程序類加載器,也叫系統類加載器,加載當前應用的classpath的所有類
參考代碼,查看結果:
public class MyObjectDemo01 {
public static void main(String[] args) {
Object object = new Object();
// System.out.println(object.getClass().getClassLoader().getParent().getParent());
// System.out.println(object.getClass().getClassLoader().getParent());
// 這是屬於java自己的類,是使用BootStrap加載器進行加載的,所以上面兩個寫出時會報空指針異常找不到其父類 null
System.out.println(object.getClass().getClassLoader());
MyObjectDemo01 myObjectDemo01 = new MyObjectDemo01();
// null
System.out.println(myObjectDemo01.getClass().getClassLoader().getParent().getParent());
// sun.misc.Launcher$ExtClassLoader@3a71f4dd
System.out.println(myObjectDemo01.getClass().getClassLoader().getParent());
// sun.misc.Launcher$AppClassLoader@18b4aac2 自己定義的類,走的是AppClassLoader加載器
// sun.misc.Launcher JVM的入口程序
System.out.println(myObjectDemo01.getClass().getClassLoader());
}
}
null
null
sun.misc.Launcher$ExtClassLoader@3a71f4dd
sun.misc.Launcher$AppClassLoader@18b4aac2
首先是自己的類,會通過AppClassLoader進行類加載,但不是第一次就是通過該加載器加載,後面會講爲什麼。而BootStrap是使用c寫的,所以打印的時候會是null。
雙親委派
首先參考一段代碼:
public class String {
public static void main(String[] args) {
/**
* 錯誤: 在類 java.lang.String 中找不到 main 方法, 請將 main 方法定義爲:
* public static void main(String[] args)
* 否則 JavaFX 應用程序類必須擴展javafx.application.Application
*/
System.out.println("我是自己定義的類...");
}
}
我這裏的包名:package java.lang;這樣情況如果java不存在一個類似於安全校驗的東西,那麼下一個使用String類的對象就不知道改使用哪個,所以引出雙親委派和沙箱安全
當一個類接收到了類加載器請求,該發出請求的類加載器不會自己先去嘗試加載這個類,而是將這個請求委派給父類去完成,所以,所有的加載請求都會傳送到啓動類加載器(BootStrap)進行加載,如果父類反饋自己無法完成此次加載(就是在其加載路徑下沒有找到對應的class文件),子類加載器纔會去嘗試自己加載。
這樣做的好處就是,不管是使用什麼類加載器去加載String,都會先通過父加載器(Bootstrap)進行加載,這樣能保證最後加載到的String對象是同一個對象.
沙箱安全:JVM將不同的代碼放在不同的域中,從而控制權限
謝謝大家閱讀!!