ClassLoader的定义:
ClassLoader是java中的类加载器,而且不止一种.
与c/c++不同,Java编写的程序不是可执行文件.exe,而是由许多独立的类文件组成,而且这些类文件不是全部都装入内存,而是根据需要来加载进去.ClassLoader是JVM实现的一部分,ClassLoader包括bootstrap classloader(启动类加载器),在JVM运行的时候加载Java的核心API,其中就包括用户定义的ClassLoader,这是指通过Java程序实现的两个ClassLoader:
ExtClassLoader,它的作用是用来加载Java扩展的API;
AppClassLoader,它是用来加载用户机器上CLASSPATH配置目录中的class的.
通常在没有指定ClassLoader的情况下,程序员自定义的类就由AppClassLoader来加载.
ClassLoader加载的流程:
当运行一个程序,JVM启动,运行bootstrap classloader,该ClassLoader加载Java核心API,然后调用ExtClassLoader来加载扩展API,最后AppClassLoader加载CLASSPATH目录下定义的class.
通过代码来看:
protected synchronized Class loadclass(String name,boolean resolve)
throw ClassNotFoundExciption{
//首先检查该类name指定的class是否被加载
Class c = findloadedClass(name);
if(c == null){
try{
if(parent != null){
//如果parent不为空,则调用loadClass进行加载
c = parent.loadClass(name,false);
}else{
c = findbootstrapClass0(name);
}
}catch(ClassNotFoundExciption e){
e.findClass(name);
}
}
if(resolve){
resolveClass(c);
}
return c;
}
从上面的代码来看,一个类加载的过程使用了一种父类委托模式, 使用这种模式的好处是:
1. 可以避免重复加载,当父类已经加载了这个类,那么子类就没有必要对其进行加载;
2. 这样更安全,如果不这样加载,那么随时可以使用自定义的String来动态替代Java核心API中定义的类型,这样会存在非常大的安全隐患,String在启动时就已经被加载,所以,用户自定义类是无法加载自定义的ClassLoader的.
下面来看看方法:
1. loadClass():
ClassLoader.llaoderClass(String name, boolean resolve)是ClassLoader的入口点.其中的name,是指JVM需要的类的名称,resolve是指告诉方法是否需要解析类.
2. defineClass():
它接受由原始字节组成的数组,并把它转化为Class对象,原始数组包含从文件系统或网络装入的数据,defineClass管理JVM的许多复杂的实现层面.此方法不能被覆盖,因为它被标记成了final.
3. findSystemClass():
从本地文件系统装入文件,它在本地文件系统中寻找类文件,,如果存在,就使用defineClass将他转换成为Class对象,将该文件转换成类.
4. resolveClass():
可以不完全地(不带解析)装入类,也可以完全地(带解析)装入类,这完全取决于resolve这个参数.
5. findLoadedClass():
findLoadedClass充当一个缓存,当请求loadClass是,调用这个方法来查看ClassLoader是否已装入这个类.这样可以避免重新装入已存在类带来的麻烦.
6. findClass():
findClass方法包含ClassLoader的所有特殊代码,而无需赋值其他代码;