`
xingsan_zhang
  • 浏览: 54146 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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的父装载器。

 

public class ClassLoaderTest {

    public staticvoid 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等。

 

public class PrivateCar {

    private String color;

    protected void drive(){

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

    }

}

 

public class PrivateCarReflect {

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

分享到:
评论
1 楼 zhang_yi_yi 2014-06-26  

相关推荐

Global site tag (gtag.js) - Google Analytics