Java基礎知識——類裝載器與反射機制

類裝載器ClassLoader

類裝載器就是尋找類的字節碼文件,並構造出類在JVM內部表示的對象組件。

類裝載器把一個類裝入JVM中,要經過三步:

1.裝載:查找和導入Class文件;

2.鏈接:執行校驗、準備和解析(解析是可以選擇的);

3.初始化:對類的靜態變量、靜態代碼塊執行初始化工作;

 

類裝載工作由ClassLoader及其子類負責。JVM在運行時會產生三個ClassLoader:根裝載器、ExtClassLoader(擴展類裝載器)和AppClassLoader(系統類裝載器)。

根裝載器不是ClassLoader的子類,它使用C++編寫,因此,我們在JAVA中看不到它,根裝載器負責裝載JRE的核心類庫,如JRE目標下的rt.jarcharsets.jar等。

ExtClassLoaderAppClassLoader都是ClassLoader的子類。其中,ExtClassLoader負責裝載JRE擴展目錄ext中的類包,AppClassLoader負責裝載Classpath路徑下的類包。

這三個類裝載器之間存在父子層級關係,即根裝載器是ExtClassLoader的父裝載器,ExtClassLoaderAppClassLoader的父裝載器。

 

publicclass ClassLoaderTest {

    publicstaticvoid main(String[] args) {

        ClassLoader loader = Thread.currentThread().getContextClassLoader();

        System.out.println("current loader---"+loader);

        System.out.println("parent loader---"+loader.getParent());

        System.out.println("grandparent loader---"+loader.getParent().getParent());

    }

}

 

上面代碼運行結果:

current  loader---sun.misc.Launcher$AppClassLoader@20cf2c80

parent  loader---sun.misc.Launcher$ExtClassLoader@1729854

grandparent loader---null

 

由於根加載器在java中訪問不到,所以返回null

 

每一個類在JVM中都擁有一個對應的java.lang.Class對象,它提供了類結構信息的描述。Class對象是在裝載類時由JVM通過調用類裝載器中的defineClass()方法自動構造的。

 

Java反射機制

Class反射對象描述類語義結構,可以從Class對象中獲取構造函數、成員變量、方法等類元素的反射對象,並以編程的方式通過這些反射對象對目標類對象進行操作。這些反射對象類在java.lang.reflect包中。主要的反射類有ConstructorMethodFieldClassLoader等。

 

publicclass PrivateCar {

    private String color;

    protectedvoid drive(){

        System.out.println("Drive private car! The color is :"+color);

    }

}

 

publicclass PrivateCarReflect {

    publicstaticvoid main(String[] args) throws Throwable {

        //通過類裝載器獲得PrivateCar類對象

        ClassLoader loader = Thread.currentThread().getContextClassLoader();

        Class clazz = loader.loadClass("com.quietboy.reflect.PrivateCar");

        //得到實例

        PrivateCar pcar =  (PrivateCar)clazz.newInstance();

        //訪問屬性,並設置屬性

        Field color = clazz.getDeclaredField("color");

        color.setAccessible(true);//取消Java語言訪問檢查,以訪問private變量

        color.set(pcar, "紅色");

        //訪問方法,並調用方法

        Method drive = clazz.getDeclaredMethod("drive", null);

        drive.setAccessible(true);//取消Java語言訪問檢查,以訪問protected方法

        drive.invoke(pcar, null);

       

    }

}

 

只要JVM的安全機制允許,反射機制可以繞過限制,訪問私有變量、調用私有方法。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章