JVM类加载机制(算是白话)有问题欢迎评论
生活随笔
收集整理的這篇文章主要介紹了
JVM类加载机制(算是白话)有问题欢迎评论
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
JVM類加載機制
類加載運行全過程
首先當我們用java命令運行某個類的main函數啟動程序時,首先需要通過類加載把主類加載到JVM中(就是這個類分配內存 分配內存的方法在后續會寫 往下看)
當執行java指令(也可以叫命令)時主要做了一些事(就是如何把這個類加載到jvm內存中)
首先有一個java.com.tuling.jvm.Math類我們對它使用java這個指令 這里是c++實現的 然后它主要做了Math(表示使用了java這個指令 然后它做的事情看箭頭)這是第一步 ---》在Windows系統下java.exe(這個可以說是java指令)調用底層的jvm.dll(相當于java的jar 這是c++的庫函數)然后創建java虛擬機(c++實現)這是第二步 ---》然后創建一個引導類加載器實例(c++實現)到這里往下有兩個選擇 這里先寫一個 另一個會在下面寫 這是第三步 --c++調用java代碼創建JVM啟動器實例sun.misc.Launcher,該類由引導類加載器負責加載 然后創建其他類加載器(類加載器都有什么會在下面寫)這里的是當第三部執行會做的一些事情--》然后就運行sun.misc.Launcher(讀音老車).getLauncher()這個方法 這是第四步 --第四步會獲取運行類自己的類加載器ClassLoader是AppClassLoader的實例--》launcher.getClassLoader() 【launcher是創建對象的一個變量名 類型為Launcher(讀音老車)這個類主要是用來加載類的java層面】 這是第五步 --調用loadClass加載要運行的類Math 也就是從第五步才開始加載我們自己寫的Math類--》classLoader.loadClass("com.tuling.jvm.Math")就是通過這個方法加載我們自己寫的類 這是第六步 --加載完成時JVM會執行Math類的main方法入口--》Math.main() 第七步 一個類的加載就算完了 --java程序運行結束--》JVM銷毀第八部上面寫到還有另外一個選擇 這個選擇就是從上面的第三步開始 --c++發起調用--》 Main.main() 第四步 --java程序運行結束--> JVM銷毀 第五步 以上就是一個類加載時的大體流程每一個為了方便看 每一個換行表示一步!!!!!!!!!!!!其中loadClass的類加載過程有一下幾步
加載》》驗證》》準備》》解析》》初始化》》使用》》卸載
其中 加載、驗證、準備、解析、初始化 這五部為重要
這里將要說的 類加載器和雙親委派機制
可以通過Class類中的getClassLoader()方式得到 類的加載器上面說的類加載過程主要是通過類加載器實現 java的加載器為引導類加載器、擴展類加載器、應用程序類加載器、自定義類加載器引導類加載器:負責加載支撐JVM運行的一些類位于JRE的lib目錄下的核心類庫,比如tr.jar、charsets.jar等擴展類加載器:負責加載支撐JVM運行的一些類位于JRE的ext擴展目錄下的jar包應用程序加載器:負責加載ClassPath下類 主要加載我們自己寫的一類自定義類加載器:負責加載我們自己設置的路徑下的類類加載器初始化過程 在sum.misc.Launcher類中的構造方法中實現 (這里實現了擴展類加載器、應用程序類加載器 都是這個Launcher類中的內部類)sum.msic.Launcher初始化使用單例模式設計,但是構造方法是被public修飾很奇怪構造方法中創建的擴展類加載器代碼為 sum.msic.Launcher.getExtClassLoader()應用程序類加載器代碼為 sum.msic.Launcher.getAppClassLoader()通過上面說的那八步根據看Launcher源碼所得出 JVM默認使用Launcher的getClassLoader()方法返回的類加載器的實例來加載我們的應用程序 默認返回AppClassLoader 由c++調用 根據上面寫的一個類的加載第四步得到 雙親委派機制!!!!!!!!!JVM類加載器是有一個結構從自定義加載器開始往上找引導類加載 《--- 擴展類加載器 《--- 應用程序類加載器 《--- 自定義加載器失敗后從引導類加載器引導類加載器(爺爺) ---》 擴展類加載器(爸爸) ---》 應用程序類加載器(兒子) ---》 自定義加載器(孫子)以上是雙親委派大體流程 下面詳細說怎么個過程根據上面說的一個類的加載 類的加載其實有一個叫雙親委派的機制 雙親委派機制的流程 在加載到某個類時會先委托父加載器 讓父加載器尋找這個類,找不到再委托上層父加載器(爺爺)加載這個類 如果所有父加載器在自己的加載類的路徑下都找不到這個類,則在自己的類加載路徑中查找并載入目標類比如Math類(自己寫的一個類上面提到用來當一個例子),最先會找應程序類加載器加載,應用程序類加載器會先委托擴展類加載器加載,擴展類加載器再委托引導類加載器,頂層引導類加載器在自己的類加載路徑里找了半天找不到Math類就會 向下退回加載Math類的請求,擴展類加載器收到回復就自己加載,在自己的類加載路徑中查找并載入目標類,如果沒找到Math類 又會向下退回加載Math類的請求 當應用程序類加載器收到回復就自己加載,在自己的類加載路徑中查找并載入目標類(Math這個類)找到了就自己加載找不到就給自定義加載器(如果有的話)也是跟上面的加載器的過程一樣 雙親委派機制一句話就是 先給兒子 兒子讓父加載 父有就加載 沒有就向下退回讓它自己加載 向上的過程沒有去加載類路徑中查找 向下的時候查找的至于為什么應用程序類加載器為兒子 擴展類加載器為父 引導類加載器為爺爺(這個是c++實現在java層面看不到 要看java源碼才能看到) 兒子跟父 可以在Launcher這個類的構造方法中查看 打開idea搜索這個類即可 雙親委派機制的源碼在ClassLoader類的loadClass()方法中可以看到 就在那個 if (parent != null) {}在這個if中的哪行代碼就是// First, check if the class has already been loaded雙親委派首先會檢查這個類是否加載 上面的英文是源碼中的 到loadClass()方法中就能看到 自己寫一個類在這個方法中弄一個條件斷點 name.eaquals("包名加類名")為什么會有雙親委派機制!!!!!!!!!!!!!!!!!!!!!!!!!!1、沙箱安全機制:自己寫的java.lang.String.class類不會被加載,防止核心API被隨意篡改2、避免類的重復加載:當父親已經加載了該類時,就沒有必要子ClassLoader再加載一次,保證類被加載的唯一性全盤負責委托機制全盤負責是指當一個ClassLoader裝在一個類時,除非顯示的使用另外一個類加載(ClassLoader) 否側該類中用到的別的類也用這個類加載器(ClassLoader)加載自定義類加載器實例自定義類加載至于要集成java.lang.ClassLoader這個類,這個類由兩個核心方法,一個是loadClass(String,boolean),實現了雙親委派機制, 還有一個方法是findClass,默認實現是空方法findClass()這個方法根據看源碼上面注釋 作用就是加載類的字節碼文件 就是寫一個io流把這個字節碼加載進來就行 然后defineClass(String name, byte[] b, int off, int len,ProtectionDomain protectionDomain)調用這個方法 參數可以參考ClassLoader中調用這個方法的地方 把b參數換成我們剛剛用io流加載的哪個字節碼文件即可defineClass()這個方法根據源碼注釋寫到是用來解析這個字節碼的打破雙親委派機制!!!!!!!!!!!!!!!!!打破雙親委派機制根據上面步驟加上重寫loadClass方法即可 傳的參數也可以參考ClassLoader()源碼中調用這個方法的地方從C++到java類的過程
一個類的加載
總結
以上是生活随笔為你收集整理的JVM类加载机制(算是白话)有问题欢迎评论的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 外星人装Ubuntu18.04
- 下一篇: 2020车工(中级)模拟考试系统及车工(