<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Java類加載體系

    早期的java程序員可能只要懂基本語法,還有少數的項目經驗就可以找到一份比較好的工作。Java和java社區的發展,更多的人了解它,深入它。現在java程序員了解一些語法我看還遠遠不夠了,對于jvm的了解和深入是非常重要的。網民的增多,網站的剛性需求,很多網站面臨高性能,高并發等等一系列的問題。沒有深入jvm的java程序員是很難寫出高質量高并發的代碼(也許一棒子打死所有人了,但我想絕大部分是肯定的)。

     

    Osgi也許你并不陌生,但是他底層的實現機制你可能沒去了解過。如果你是個打破砂鍋問到底的人,你肯定會想知道osgi是如何做到的。但是你沒有了解jvm的類加載體系,你肯定很難理解osgi是如果做到類隔離等一系列的問題。不過想完整理解osgi還需要其他很多方面的知識,但是它基本的機制還是的了解jvm的類加載機制。

     

    Java類庫有些包只是定義了一個標準,具體的實現都是由具體的供應商來提供。Java與數據庫連接就是一個很好的例子。Java.sql類庫只是定義了java與數據庫連接的標準,那么與mysql就需要msyql的驅動,oracle就需要oracle的驅動,而java.sql類庫是由bootstrap classloader加載,驅動包中的類是由system classloader來加載,不同類加載器加載的類是無法相互認識,所以自然也無法正常提供功能了。jvm又是提供了什么機制讓他們交互呢?如果你確實對這些問題毫無頭緒的話,那么我覺得你真的要好好理解下jvm類加載體系。

     

    這篇文章主要是介紹下jvm類加載的機制基礎知識。關于其他相關涉及,有時間的話,我會單獨寫文章來介紹。

     

    1 java類加載器

    http://www.tkk7.com/images/blogjava_net/yangpingyu/classloader-1.jpg

    1.1 Bootstrap classloader:sun jdk是用c++實現,所以在代碼中你是無法獲取此加載器的實例。此加載器主要負責加載$JAVA_HOME/jre/lib/rt.jar。java類中獲取結果為null,這里可以用一個例子跑下證明:

    public class Test {

             public static void main(String[] arg) throws Exception{

                       ClassLoader classloader = Test.class.getClassLoader();

                       System.out.println(classloader);

                       System.out.println(classloader.getParent());

                       System.out.println(classloader.getParent().getParent());

             }

    }

    輸出結果:

    sun.misc.Launcher$AppClassLoader@19821f

    sun.misc.Launcher$ExtClassLoader@addbf1

    null

    最后輸出的null就是代表bootstrap classloader。

     

    1.2 Extension classloader:主要加載擴展功能的jar,$JAVA_HOME/jre/lib/ext/*.jar。

    1.3 System classloader:加載claspath中的jar包。

    1.4自定義 classloader:主要加載你指定的目錄中的包和類。

     

    2 雙親委派模型

    系統運行時,我們請求加載String類,此時System Classloader自己不找classpath中的包,把請求轉發給Extension Classloader,但它也不做查找,又轉發給Bootstrap Classloader,但是它發現自己沒有parent了。于是他在rt.jar包中找到String類并加載到jvm中提供使用。Jvm為什么要這么實現呢?其實和java安全體系有關。假設jvm不是這么實現,我們自定義一個String類,做一些破壞,那么運行jvm的機器肯定要受到損壞。具體例子:

    public class String {

             public static void main(String[] args) {

                       System.out.println("hello world");

             }

    }

    我們運行自定義String類的時候報錯了,說沒有main方法,可我們定義的明明有的,嘿嘿,委派機制的緣故最后加載到的是由bootstrap classloader在rt.jar包中的String,那個類是沒有main方法,因此報錯了。

    http://www.tkk7.com/images/blogjava_net/yangpingyu/classloader-2.jpg

    3 類隔離

    jvm中的類是:類加載器+包名+類名。比如:URLClassLoader1,URLClassLoader2分別加載com.test.Test的時候會加載兩次,因為每個classloader中的類對于其他classloader來說是隔離的,不認識的。例子:

    import java.net.URL;
    import java.net.URLClassLoader;

    public class CustomClassloaderTest {
        
    public static void main(String[] args) throws Exception {
            URL url = 
    new URL("file:/g:/");
            URLClassLoader ucl = 
    new URLClassLoader(new URL[]{url});
            Class c = ucl.loadClass("Yang");
            c.newInstance();
            System.out.println(c.getClassLoader());

            URLClassLoader ucl2 = 
    new URLClassLoader(new URL[]{url});
            Class c2 = ucl2.loadClass("Yang");
            c2.newInstance();
            System.out.println(c2.getClassLoader());
        }
    }

    大家把Yang類存在g盤下。

    public class Yang {
        
    static {
            System.out.println("Yang");
        }
    }

    運行結果:

    Yang

    java.net.URLClassLoader@c17164

    Yang

    java.net.URLClassLoader@61de33

    看到每次加載Yang類的時候都輸出Yang,說明Yang類被加載了兩次。

    如果你不確信,可以修改下代碼,讓同一classloader加載Yang類兩次

     

    import java.net.URL;
    import java.net.URLClassLoader;

    public class CustomClassloaderTest {
        
    public static void main(String[] args) throws Exception {
            URL url = 
    new URL("file:/g:/");
            URLClassLoader ucl = 
    new URLClassLoader(new URL[]{url});
            Class c = ucl.loadClass("Yang");
            c.newInstance();
            System.out.println(c.getClassLoader());

            Class c2 = ucl.loadClass("Yang");
            c2.newInstance();
            System.out.println(c2.getClassLoader());
        }
    }

    看看輸出結果:

    Yang

    java.net.URLClassLoader@c17164

    java.net.URLClassLoader@c17164

    結果中只輸出了一次Yang。因此可以證明我們最開始說的類隔離。

     

    4 線程上下文類加載器

    我們理解了雙親委派模型,那么目前只有由下向上單向尋找類(system->extension->bootstrap)

    。我們在最開始的時候說過,java.sql包中的類由bootstrap或extension classloader加載,而mysql驅動包是在classpath中由system來加載,但bootstrap中的類是無法找到system classloader中的類,此時靠線程上下文類加載器來解決。線程上下文類加載器主要就是能讓jvm類加載模型具有了向下尋找的可能,bootstrap->extension->system,如果不做任何設置,線程上下文類加載器默認是system classloader。本來這里想寫一個例子的,可是有點麻煩,所以下次單獨寫一篇關于這方面的知識。

     

    posted on 2011-05-14 21:41 yangpingyu 閱讀(1022) 評論(2)  編輯  收藏 所屬分類: java基礎

    評論

    # re: Java類加載體系[未登錄] 2011-11-19 21:35 Alex

    請問你用的是哪個jdk,我嘗試的情況是,兩個classloader 加載同一個class,static仍然只是被執行一次的。  回復  更多評論   

    # re: Java類加載體系 2011-11-30 15:11 yangpingyu

    @Alex
    我在家里用的好像是jdk1.6版本。  回復  更多評論   

    <2011年11月>
    303112345
    6789101112
    13141516171819
    20212223242526
    27282930123
    45678910

    導航

    統計

    常用鏈接

    留言簿

    隨筆分類

    隨筆檔案

    收藏夾

    linux

    產品交互

    分析,設計,架構

    安全

    技術牛人

    數據庫

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 国产一精品一AV一免费| 插鸡网站在线播放免费观看| 国产做床爱无遮挡免费视频| 91亚洲性爱在线视频| 2019中文字幕免费电影在线播放| 影音先锋在线免费观看| 国产成人精品日本亚洲网址| 两个人看的www免费| 国产亚洲日韩在线三区| 日韩电影免费在线观看| 亚洲色欲www综合网| 4hu四虎最新免费地址| 亚洲欭美日韩颜射在线二| 日韩av无码免费播放| 亚洲国产精品无码久久久不卡| 国产精品白浆在线观看免费| 亚洲网站免费观看| 免费高清国产视频| 亚洲美女免费视频| 特级淫片国产免费高清视频| 日韩精品免费一线在线观看 | 男人天堂免费视频| 亚洲图片一区二区| 女人18毛片水真多免费播放| 全部在线播放免费毛片| 久久亚洲伊人中字综合精品| 无限动漫网在线观看免费| 深夜A级毛片视频免费| 亚洲成av人片天堂网| 色窝窝免费一区二区三区| 香蕉97碰碰视频免费| 亚洲电影一区二区三区| 免费看的黄色大片| 爽爽爽爽爽爽爽成人免费观看| 亚洲免费一级视频| 亚洲中文无韩国r级电影| 亚洲毛片在线免费观看| 黄色一级毛片免费| 亚洲成av人片不卡无码| 亚洲一级黄色视频| 无码一区二区三区免费视频 |