java程序不是本地的可执行程序,它的执行依赖jvm,jvm运行后将 class 文件加载到jvm,然后才能在jvm内部运行。负责加载这些class的组件就是ClassLoader。
JVM本身包含了一个ClassLoader称为**BootstrapClassLoader**,和JVM自身一样,**BootstrapClassLoader**是用本地代码(c/c++等)实现的,它负责加载核心Java class(如rt.jar里的class)。另外JVM还提供了两个ClassLoader,它们都是用Java语言编写的,由BootstrapClassLoader加载到jvm,它们是**ExtClassLoader**和**AppClassLoader**,其中**ExtClassLoader**负责加载Java扩展 class(如jre/lib/ext下的类),**AppClassLoader**负责加载应用程序自身的类(如-classpath下的class)。
我们可以通过JVM参数 -Xbootclasspath 指定自定义的BootstrapClassLoader,但通常是不需要的。
当运行一个程序的时候,JVM启动,运行Bootstrap ClassLoader,该ClassLoader加载java核心API(ExtClassLoader和AppClassLoader也在此时被加载),然后调用ExtClassLoader加载扩展API,最后调用AppClassLoader加载应用CLASSPATH下定义的Class,这就是一个程序最基本的加载流程。
JVM自带的ClassLoader只是懂得从本地文件系统加载标准的java class文件,但是我们可能会有下面的应用场景:
1)在执行类加载之前,自动验证数字签名
2)动态地创建符合用户特定需要的定制化构建类
3)从特定的场所取得 class,例如数据库、网络等
4) 自定义加解密Class 等等
这时候我们就需要定制自己的ClassLoader,java提供了很方便的api供我们定制自己的ClassLoader。
事实上当使用Applet的时候,就用到了特定的ClassLoader,因为需要从网络上加载java class,并且要检查相关的安全信息。另外,应用服务器大都使用了自定义ClassLoader技术,了解类加载原理也有助于我们更好地开发自己的应用。
##ClassLoader结构
java中内置了很多类加载器,本文只讨论几个核心类加载器:
**ClassLoader**:所有类加载器的基类,它是抽象的,定义了类加载最核心的操作。
**SecureClassLoader**:继承自ClassLoader,添加了关联类源码、关联系统policy权限等支持。
**URLClassLoader**:继承自SecureClassLoader,支持从jar文件和文件夹中获取class
**ExtClassLoader**:扩展类加载器,继承自URLClassLoader,负责加载java的扩展类(javax.*等),查看源码可知其查找范围为System.getProperty("java.ext.dirs"),通常是jre/lib/ext
**AppClassLoader**:应用类加载器,继承自URLClassLoader,也叫系统类加载器(ClassLoader.getSystemClassLoader()可得到它),它负载加载应用的classpath下的类,查找范围System.getProperty("java.class.path"),通过-cp或-classpath指定的类都会被其加载
java没有提供Launcher的源码,可参考openjdk的Launcher类源码。
上面介绍的是ClassLoader的静态类结构,在概念上,它们还有树形结构,java中的每个ClassLoader都有自己的父加载器(**注意区分,不是类关系上的 super**),可以通过ClassLoader.getParent() 获取到,当jvm启动完成后,默认情况下,他们的树形结构是这样的:
自定义的ClassLoader其父加载器为AppClassLoader,
AppClassLoader的父加载器为ExtClassLoader,
ExtClassLoader的父加载器为null,
null表示其父加载器为 BootstrapClassLoader(非java实现故显示为null)。
参考:http://blog.csdn.net/conquer0715/article/details/38229203