您的位置:首页 > 编程语言 > Java开发

Java ClassLoader深入解析(一)

2016-08-13 22:21 337 查看
一、类加载器原理简介

Java 编译器会为虚拟机转化源指令。虚拟机代码存储在以.class为扩展名的类文件中,每个类文件都包含某个类

或者接口的定义和代码实现。这些类文件必须由一个程序进行解释,该程序能够将虚拟机的指令集翻译成目标机器的机器语言。

请注意,虚拟机只加载程序执行时所需要的类文件。例如,假设程序从MyProgram.class开始运行,下面是虚拟

机执行的步骤。

(1)虚拟机有一个用于加载类文件的机制,例如,从磁盘上读取文件或者请求web上的文件;它使用该机制

来加载MyProgram类文件中的内容。

(2)如果MyProgram类拥有类型为另一个类的域,或者是拥有超类,那么这些类文件也会被加载

(3)接着,虚拟机执行MyProgram中的main方法(它是静态的,无需创建类的实例)

(4)如果main方法或者main调用的方法要用到更多的类,那么接下来就会加载这些类。然而,类加载机制并

非只使用单个的类加载器。每个Java程序至少拥有三个类记载器。

 -引导类加载器

 -扩展类加载器

 -系统类加载器(有时也称为应用类加载器)

引导类加载器负责加载类(通常从Jar文件rt.jar中进行加载)。它是虚拟机不可分割的一部分,而且通常是用

C语言来实现的。引导类加载器没有对应的ClassLoader对象,如果,该方法:
String.class.getClassLoader();将返回null.

扩展类加载器用于jre/lib/ext目录加载“标准的扩展”。可以将JAR文件放入该目录,这样即使没有任何类路

径,扩展类加载器也可以找到其中的各个类。

系统类加载器用于加载应用类。它在有CLASSPATH环境变量或者-classpath命令行选项设置类路径的目录

或者是JAR/ZIP文件里查找这些类。
在Oracle的Java语言实现中,扩展类加载器和系统类加载器都是用Java来实现的。它们都是URLClassLoader类的实例。

二、类加载器的层次结构

类加载器有一种父/子关系。除了引导类加载器外,每个类加载器都有一个父类加载器。根据规定,类加载器

会为它的父类加载器提供一个机会,以便加载任何给定的类,并且只有在其父类加载失败时,它才会加载该给该给定类。例如,当要求系统加载器加载一个系统类(比如,java.util.ArrayList)时,它首先要求扩展类加载器进行加载,该扩展类加载器则首先要求引导加载器进行加载。引导类查找并加载rt.jar中的这个类,而无须其他类加载做更多的搜索。



加载方式1:

URL url=new URL("file:///path/to/plugin.jar");
URLClassLoader pluginLoader=new URLClassLoader(new URL[]{url});
Class<?> cl=pluginLoader.loadClass("mypackage.class");


因为在URLClassLoader构造器中没有指定类加载器,因此pluginLoader的父亲就是系统类加载器.

加载方式2:

Class.forName(class-NameString);




三、上下文类加载器

     每个线程都有一个对类加载器的引用,称为上下文加载器。主线程的上下文类加载器是系统类加载器。当新线程创建时,它的上下文加载器会被设置创建该线程的上下文类加载器。因此,如果你不做任何特殊的操作,那么所有线程就将它们的上下文加载器设置为系统类加载器。

但是,我们也可以通过下面的调用将其设置为任何类的加载器

Thread t=Thread.currentThread();
t.setContextClassLoader(loader);


    然后助手方法可以获取这个上下文类加载器:



Thread t=Thread.currentThread();
ClassLoader loader=t.getContextClassLoader();
Class cl=loader.loadClass(className);



四、将类加载器作为命令空间

每个Java程序员都知道,包的命名是为了消除名字冲突。在标准类库中,有两个名字为java.util.Date和java.sql.Date.

使用简单的名字只是为了方便程序员,它们要求程序包含恰当的import语句。在一个正在执行的程序中,所有的类名都包

括它的包名。

然而,令人惊奇的是,在同一个虚拟机中,可以有两个类,它们的类名和包名是相同的。类是由它的全名和类加载器

确定的。这项技术在加载来自多处的代码时很有用。例如,浏览器为每一个web页面都使用了一个独立的applet类加载器的

实例。这样,虚拟机就可以区分来自不同web页的各个类,而不用管它们的名字是什么。

如何编写自己的类加载器 正在编写中。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息