Java 基礎中一些值得聊的話題 載入篇
在開始Java的類載入旅程之前,可以先參考這裡(http://blog.csdn.net/liweisnake/article/details/8470285)了解一些類載入器在Tomcat中的應用。
在最初執行java這個命令時,便會調用 ClassLoader 的 getSystemClassLoader 方法顯式或者隱式載入 main 方法所在的類及其所引用的類。getSystemClassLoader 會返回 AppClassLoader,後者是 URLClassLoader 的一個子類。
先有雞還是先有蛋?
所以,最初的一個問題是:先有雞還是先有蛋?因為 ClassLoader 的整套體系是打包在 jre/lib/rt.jar 中的。只有 rt.jar 先被載入進來,才能夠載入別的類;但是 rt.jar 又是被誰載入的呢?自然就是大名鼎鼎的 BootstrapClassLoader。它就是「雞」。所以嚴格來講,BootStrapClassLoader 並不是整個體系中的一部分(可以用 -Xbootclasspath 指定bootstrap 載入的位置)。
當 rt.jar 被載入進來後,ClassLoader 會調用 getSystemClassLoader,其中最重要的一步就是初始化 Launcher、ExtClassLoader 以及AppClassLoader,另外就是將 ContextClassLoader 設為 AppClassLoader。ExtClassLoader 與 AppClassLoader 都是 URLClassLoader 的子類,分別會載入 java.ext.dirs 和 java.class.path 路徑下的 jar資源,前者一般指向 jre/lib/ext 下的所有jar,後者就是我們經常念叨的classpath。區分這兩個 ClassLoader 的主要目的是,讓他們形成層級關係,ExtClassLoader 為 AppClassLoader 的父 ClassLoader,有了層級關係,便可隨意使用雙親委託模型了。
ClassLoader extcl;
try {
extcl = ExtClassLoader.getExtClassLoader();
} catch (IOException e) {
throw new InternalError(
"Could not create extension class loader");
}
// Now create the class loader to use to launch the application
try {
loader = AppClassLoader.getAppClassLoader(extcl);
} catch (IOException e) {
throw new InternalError(
"Could not create application class loader");
}
// Also set the context class loader for the primordial thread.
Thread.currentThread().setContextClassLoader(loader);
ClassLoader究竟幹了什麼?
接下來一個比較重要的問題是ClassLoader究竟幹了什麼?通常我們只知道它載入了一個類進了jvm,但是具體做了什麼呢?
Java設計者把classloader載入一個類的過程分為4步:
第一步,從某個地方得到我們想要的位元組碼二進位流;
第二步,讀入位元組碼流並轉化為Class;
第三步,鏈接;
第四步,初始化。
其中,第二步一般比較固定,因此ClassLoader提供了defineClass來完成這步;
protected final Class defineClass(String name, byte[] b, int off, int len,
ProtectionDomain protectionDomain)
throws ClassFormatError
{
protectionDomain = preDefineClass(name, protectionDomain);
Class c = null;
String source = defineClassSourceLocation(protectionDomain);
try {
c = defineClass1(name, b, off, len, protectionDomain, source);
} catch (ClassFormatError cfe) {
c = defineTransformedClass(name, b, off, len, protectionDomain, cfe,
source);
}
postDefineClass(c, protectionDomain);
return c;
}
而 ClassLoader 提供了另一個方法 findClass 來完成第一步及第二步,即從某個地方讀入類的二進位流,然後調用 defineClass 返回 Class
protected Class findClass(final String name)
throws ClassNotFoundException
ClassLoader提供了resolveClass方法完成第三步鏈接的工作。
protected final void resolveClass(Class c)
除非特殊需要,否則盡量重載 findClass 而不是 loadClass。
loadClass 是 Java 1.0 就存在的類,為了增強可擴展性,將findClass和resolveClass封裝到了loadClass中,一般我們只需要定義類的載入路徑,因此僅需覆蓋findClass。
通常我們顯示載入類一般會用到ClassLoader.loadClass、Class.forName,他們的區別見這裡(http://blog.csdn.net/liweisnake/article/details/8857744)。
resolveClass做了什麼?
resolveClass最終調用了一個本地方法做link,這裡的link主要做了這麼幾步事情:
驗證Class以確保類裝載器格式和行為正確;
準備後續步驟所需的數據結構;
解析所引用的其他類。
ClassNotFoundException、NoClassDefFoundError、ClassCastException常見問題
ClassNotFoundException一般發生在顯式類載入;NoClassDefFoundError一般發生在隱式載入;ClassCastException一般發生在jar包衝突,比如某個jar包已經被更上層的載入器載入了,但你卻要求他強制轉為下層載入器載入的同名類;
鏈接的相關知識
接下來講講鏈接的相關知識。
為什麼會發明鏈接器?
最初程序員寫程序都在一個文件里,隨著程序規模的增加,逐漸發現越來越難以維護,擴展。於是,分多個文件和模塊就成為必然。
但是文件間必然相互調用,這就帶來了另一個問題:文件A引用了B的某個變數或方法,但是運行時A並不知道他們在內存中的位置。於是人們發明了鏈接,這種方式會在編譯階段將需要引用的變數或者方法作個記號,這時形成A.o和B.o兩個目標文件;通過ld鏈接器的鏈接,會將B中變數或方法的地址重新修改A的記號最終形成一個可執行文件,實際上就是把A和B合在一起工作了。
這種方式就是靜態鏈接。
但是靜態鏈接有個問題,比如A需要B模塊的方法,C需要B模塊的變數,D需要B模塊的方法……如此一來,當我們編譯為A, C, D幾個可執行文件時,他們都會在內存中引用B,即B在內存中有多份拷貝。這帶來很多問題:首先浪費了內存;其次修改了B模塊需要重新修改並發布A, C, D幾個可執行文件,這是非常不方便的;於是動態鏈接的一個思想是在A, C, D調用時再確定記號的地址,而B則通過延遲載入的方式按需載入到內存(如果已經載入則不再重複)。這樣一來,內存中總是只有一份B的拷貝,解決了上面的問題。Java的類載入機制即是這種靈活的方式。
想要系統學習Java知識 加入學習群一四四九零一零七六 可以免費學習java還有大量學習乾貨哦
![](https://pic.pimg.tw/zzuyanan/1488615166-1259157397.png)
![](https://pic.pimg.tw/zzuyanan/1482887990-2595557020.jpg)
※當你寫Java HelloWorld時候,背後到底發生什麼?
※解析JavaScript函數的多種寫法
※C語言 代碼之坦克大戰
TAG:IT技術java交流 |
※不覺得 Sense 8 中映射的社會話題更值得一聊嗎
※他都不會老啊!金在中 Rising Sun 時期舊圖成為話題
※Red Velvet Wendy金髮造型在北邊成話題!本來的發色不是很好嗎?
※讓人大打出手的AJ又回來了!今年更多的話題或許還需要Virgil Abloh的支持?
※當楊天寶佔領話題榜的時候,別忘了還有另一個Angela
※再次因「美貌」而登上了熱搜!RedVelvet 成員 Irene 機場照成為話題
※YG背鍋?BlackPink Lisa 入鏡引擁堵成為話題
※Kylie Jenner首次談到整容話題!「我真的沒動過刀」!
※話題|你老買converse和vans大概是因為……
※Redvelvet 艾琳 「不經意間的皺眉」成為話題
※小圈子話題—Instagram 推出個性化 Stories 分享功能
※Air Jordan 3 Tinker只是開胃,聊天記錄曝光一大波話題Air Jordan正在靠近!
※話題丨Yeezy挑戰iPhone銷量!不限量真的好嗎?
※美容話題 | Peter Philips 顏色是情感的化身
※熱議話題!反鉤 TS x Air Jordan 1 市場行情如何了?
※比冠軍套裝話題度還高!倫納德能否成為New Balance的「下一個庫里」呢?
※「四胞胎」的顏值巔峰?RedVelvet 出道曲舊照成為話題
※老外最想聊的話題之Healthy Eating&Tea TalK
※Redvelvet 成員 Wendy「清爽」機場照成為話題
※Angelababy又一部現代劇?女性話題題材?配角陣容強大