读书人

类加载器初始学习

发布时间: 2012-08-30 09:55:54 作者: rapoo

类加载器初步学习

? ? 近期学习java的classloader(类加载器),有必要记录下,好记性不如烂笔头,这里略去代码测试部分,纯粹记录脑中所想,如有纰漏、错误请大家及时提出,也是帮我提高。

?

系统类加载器:

? 当java虚拟机(jvm.dll)启动后,会创建三个类加载器BootStrapClassLoader、ExtClassLoader、AppClassLoader,它们是java虚拟机的一部分,一直逗留在内存中,直到java虚拟机终止才会在内存中消失,它们都有自己的管辖目录范围,在管辖内寻找类(.class文件)来加载。

BootStrapClassLoader:c++编写,在java中表现形式为null。

ExtClassLoader:java编写,源代码在sun.misc.Launcher类中,它是一个内部类。

AppClassLoader:java编写,源代码也在sun.misc.Launcher类中,它也是一个内部类。

简单理解,ExtClassLoader和AppClassLoader被设计成单例模式,在内存中分别只有一个对象。

?

用户创建类加载器:

? 用java编写的类加载器都要直接或者间接继承类java.lang.ClassLoader,包括用户(用户指程序员)自己编写的,也包括系统类加载器ExtClassLoader和AppClassLoader。

??父子委托模式是在java.lang.ClassLoader中的loadClass方法描述的,ExtClassLoader和AppClassLoader在加载类的时候也会调用loadClass方法。具体代码如下:
    protected ClassLoader() {        this(checkCreateClassLoader(), getSystemClassLoader());    }    protected ClassLoader(ClassLoader parent) {        this(checkCreateClassLoader(), parent);    }

? 具体细节查看javadoc或者sourcecode.

?

按javadoc中描述,继承java.lang.ClassLoader后需要覆盖findClass方法,实现具体的加载类的过程,用户编写的类加载器也可以有自己的管辖目录范围,可以在覆盖findClass方法时定义。java.net.URLClassLoader 是系统API提供的可直接使用的类加载器,它继承了java.lang.ClassLoader,也覆盖了构造函数,也覆盖了findClass方法。ExtClassLoader和AppClassLoader都是继承了java.net.URLClassLoader来扩展自己的功能的。绕开父子委托模式? 我个人简单认为可以把parent设置成null或者直接使用findClass方法,避免使用直接继承类java.lang.ClassLoader的loadClass方法。

类加载器有两种,一种是系统类加载器(在内存中只有一份),另一种是用户自己定义类加载器(在内存中可以有很多份,根据new的次数)。

?

class文件在内存中的形态:

? ? 同一个class文件可以被不同的类加载器对象加载,每个类加载器对象只能对它加载一次(如果用loadClass方法的话)。这样看来class文件在内存中可能会有很多份,每一份都是一个class对象,大家都知道在new的时候就是根据这个class对象为模板创建对象的,当内存里有很多class对象的时候,new的时候会根据系统类加载器(BootStrapClassLoader、ExtClassLoader、AppClassLoader)加载的那个class对象为模板创建对象,效果和其他份class对象的newInstance()一样。class对象newInstance()的时候返回一个Object对象,如果对它向下转型为具体类的时候可能会出现奇怪的现象,见?http://www.iteye.com/problems/77669? 在向下转型的时候,对比的是class对象是否相等,不同的类加载器加载的class对象是不同的,是各占一个内存空间的,所以出现连接中的问题。

?

? ? 上面的内容都是根据现象推出来的,还没有足够的证据支持,下一步继续学习jvm规范,希望能找到依据,内部实现机制还是很多不了解。

?

?

读书人网 >编程

热点推荐