类装载器是用来把类(class)装载进JVM的。JVM规范定义了两种类型的类装载器:根装载器(bootstrap)和用户自定义装载器(user-defined class loader)。根装载器是
Java虚拟机实现的一部分,根装载器以某种默认的方式将类装入,包括那些Java API的类。
bootstrap是JVM自带的类装载器,用来装载核心类库,如java.lang.*等。由例1可知java.lang.Object是由bootstrap装载的。Java提供了抽象类ClassLoader,所有用户自定义类装载器都实例化自ClassLoader的子类。System Class Loader是一个特殊的用户自定义类装载器,由JVM的实现者提供,在不特别指定装载器的情况下默认装载用户类。系统类装载器可以通过ClassLoader.getSystemClassLoader() 方法得到。在运行期间一个
Java程序能安装用户自己定义的类装载器。根装载器是虚拟机固有的一部分,而用户定义的类装载器则不是,它是用Java语言写的,被编译成class文件之后然后再被装入到虚拟机,并像其它的任何对象一样可以被实例化。下面通过一个例子来说明
public class LoaderExam
{
public static void main(String[] args)
{
Class c;
ClassLoader cl;
cl = ClassLoader.getSystemClassLoader();
System.out.println(cl);
while (cl != null)
{
cl = cl.getParent();
System.out.println(cl);
}
try
{
c = Class.forName("java.lang.Object");
cl = c.getClassLoader();
System.out.println("java.lang.Object’s loader is " + cl);
c = Class.forName("LoaderExam");
cl = c.getClassLoader();
System.out.println("LoaderExam's loader is " + cl);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
运行的结果如图所示:
第一行表示,系统类装载器实例化自类
sun.misc.Launcher$AppClassLoader
第二行表示,系统类装载器的
parent
实例化自类
sun.misc.Launcher$ExtClassLoader
第三行表示,系统类装载器
parent
的
parent
为
bootstrap
第四行表示,核心类
java.lang.Object
是由
bootstrap
装载的
第五行表示,用户类
LoaderExam
是由系统类装载器装载的
Java的类装载模型是一种
双亲委托模型
。
在此模型下,当一个装载器被请求装载某个类时,它首先委托自己的
parent
去装载,若
parent
能装载,则返回这个类所对应的
Class
对象,若
parent
不能装载,则由
parent
的请求者去装载。如图2所示:
loader2的parent为loader1,loader1的parent为system class loader。假设loader2被要求装载类MyClass,在双亲委派模型下,loader2首先请求loader1代为装载,loader1再请求系统类装载器去装载MyClass。若系统装载器能成功装载,则将MyClass所对应的Class对象的reference返回给loader1,loader1再将reference返回给loader2,从而成功将类MyClass装载进虚拟机。若系统类装载器不能装载MyClass,loader1会尝试装载MyClass,若loader1也不能成功装载,loader2会尝试装载。若所有的parent及loader2本身都不能装载,则装载失败。
双亲委托模型为什么更安全了?根据一个类的存放位置,这个类最终只能由一个特定的类装载器去装载,对于一个已被父级类装载的类来说,JVM默认也使用这个父级装载器去装载他们所调用的其他类,由于父级类装载器不会委托子级类装载器去装载类,所以,在一般情况下,一个已被父级类装载器装载的类无法调用那些只能被子级类装载器发现和装载的其他类。这样的双亲委托模型也就更加安全了。这样也就不难理解为什么junit.jar不能安装在JDK ext目录下。
AOP
是
Aspect Oriented Programming
的缩写,意思是面向方面编程。
AOP
的核心思想:自己做一个类装载器,在自己的类装载器中制造一个与装载进来的类一模一样的类,然后在这个类内加一些方法来完成某一特定的功能。