首页 > 代码库 > Java基础知识——类装载器与反射机制

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的安全机制允许,反射机制可以绕过限制,访问私有变量、调用私有方法。


本文出自 “quietboy's blog” 博客,请务必保留此出处http://quietboy.blog.51cto.com/6711298/1429347