现在的位置: 首页 > 综合 > 正文

黑马程序员_类加载器

2014年02月05日 ⁄ 综合 ⁄ 共 4251字 ⁄ 字号 评论关闭

----------------------android培训java培训、期待与您交流!
-------------------------------------

类加载器基本概念
 类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。
Java 虚拟机使用 Java 类的方式如下:
1,Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。
2,类加载器负责读取 Java 字节代码,并转换成 java.lang.Class 类的一个实例。每个这样的实例用来表示一个 Java 类。
3,通过此实例的 newInstance()方法就可以创建出该类的一个对象。
基本上所有的类加载器都是 java.lang.ClassLoader 类的一个实例。

ClassLoader 中与加载类相关的方法
 java.lang.ClassLoader类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个 Java 类

,即java.lang.Class类的一个实例。除此之外,ClassLoader还负责加载 Java 应用所需的资源,如图像文件和配置文件等。
getParent() 返回该类加载器的父类加载器。
loadClass(String name) 加载名称为 name的类,返回的结果是 java.lang.Class类的实例。
findClass(String name) 查找名称为 name的类,加发起者具有的特有内容
findLoadedClass(String name) 查找名称为 name的已经被加载过的类,返回的结果是 java.lang.Class类的实例。
defineClass(String name, byte[] b, int off, int len) 把字节数组 b中的内容转换成 Java 类,返回的结果是 java.lang.Class类的实例。这个

方法被声明为final的。

-----
Java 中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由 Java 应用开发人员编写的。系统提供的类加载器主要有下面三个:
A,引导类加载器(bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。
B,扩展类加载器(extensions class loader):它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并

加载 Java 类。
C,系统类加载器(system class loader):它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。
自己编写的类加载器的父类加载器是系统类加载器。

找出类加载器的树状组织结构:
public class ClassLoaderTree {  
 
    public static void main(String[] args) {  
        ClassLoader loader = ClassLoaderTree.class.getClassLoader();//.class后得到的就是Class对象,其具有     

//Class中方法: getClassLoader() 返回该类的类加载器ClassLoader。  
        while (loader != null) //loader=null时,就代表类加载器是祖宗:BootStrap
 {  
            System.out.println(loader.toString());  //把loader变成字符串
            loader = loader.getParent(); 递归调用getParent()方法来输出全部的父类加载器。 
        }  
    }  
 }
-------

类加载器的委托机制:
类加载器加载类的顺序是由上而下进行的,当需要查找要调用的类时,它先委托给自己的父类加载器进行加载,当查找不到的时候它就会调用本身类加载器进

行加载,当找不到的时候才会出现找不到类的异常。每个ClassLoader本身只能分别加载特定位置和目录中的类,但它们可以委托其他的类装载器去加载类,这

就是类加载器的委托模式。ClassLoad中loadClass()方法已完成机制

Java提供了抽象类ClassLoader,所有用户自定义类装载器都实例化自ClassLoader的子类。 System Class Loader是一个特殊的用户自定义类装载器,由JVM

的实现者提供,在编程者不特别指定装载器的情况下默认装载用户类。系统类装载器可以通过ClassLoader.getSystemClassLoader() 方法得到。

加载类的过程:
真正完成类的加载工作是通过调用defineClass来实现的;而启动类的加载过程是通过调用loadClass来实现的。前者称为一个类的定义加载器(defining

loader),后者称为初始加载器(initiating loader)。在 Java 虚拟机判断两个类是否相同的时候,使用的是类的定义加载器。也就是说,哪个类加载器

启动类的加载过程并不重要,重要的是最终定义这个类的加载器。两种类加载器的关联之处在于:一个类的定义加载器是它引用的其它类的初始加载器。

 

创建自己的类加载器:

自己开发的类加载器只需要覆写findClass(String name)方法即可。java.lang.ClassLoader类的方法loadClass()封装了前面提到的代理模式的实现。该方

法会首先调用findLoadedClass()方法来检查该类是否已经被加载过;如果没有加载过的话,会调用父类加载器的loadClass()方法来尝试加载该类;如果父类

加载器无法加载该类的话,就调用findClass()方法来查找该类。因此,为了保证类加载器都正确实现代理模式,在开发自己的类加载器时,最好不要覆写

loadClass()方法,而是覆写findClass()方法。

public class FileSystemClassLoader extends ClassLoader {

    private String rootDir;

    public FileSystemClassLoader(String rootDir) {
        this.rootDir = rootDir;
    }

    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] classData = getClassData(name);
        if (classData == null) {
            throw new ClassNotFoundException();
        }
        else {
            return defineClass(name, classData, 0, classData.length);
        }
    }

    private byte[] getClassData(String className) {
        String path = classNameToPath(className);
        try {
            InputStream ins = new FileInputStream(path);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int bufferSize = 4096;
            byte[] buffer = new byte[bufferSize];
            int bytesNumRead = 0;
            while ((bytesNumRead = ins.read(buffer)) != -1) {
                baos.write(buffer, 0, bytesNumRead);
            }
            return baos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private String classNameToPath(String className) {
        return rootDir + File.separatorChar
                + className.replace('.', File.separatorChar) + ".class";
    }
 }
说明:类 FileSystemClassLoader继承自类 java.lang.ClassLoader。一般来说,自己开发的类加载器只需要覆写 findClass(String name)方法即可。

java.lang.ClassLoader类的方法 loadClass()封装了前面提到的代理模式的实现。{该方法会首先调用 findLoadedClass()方法来检查该类是否已经被加载

过;如果没有加载过的话,会调用父类加载器的 loadClass()方法来尝试加载该类;如果父类加载器无法加载该类的话,就调用 findClass()方法来查找该类

。}因此,为了保证类加载器都正确实现代理模式,在创建自己的类加载器时,最好不要覆写 loadClass()方法,而是覆写 findClass()方法。
类 FileSystemClassLoader的 findClass()方法首先-->根据类的全名在硬盘上查找类的字节代码文件(.class 文件)-->然后读取该文件内容-->最后通过

defineClass()方法来把这些字节代码转换成 java.lang.Class类的实例。

 

----------------------android培训java培训、期待与您交流!
----------------------详细请查看:
http://edu.csdn.net/heima(日记必用代码)

抱歉!评论已关闭.