开发过程中可能不需要了解类加载器,也能正常编写代码,但我们在处理一些代码问题时,就需要了解类加载器的知识,只有这样才能找到问题的本质;不管学习什么底层原理都是学习的重点。下面一起学习类加载器(ClassLoader)相关知识。
网络配图
首先,类加载器(ClassLoader)是什么,Java程序的运行与其他程序不同,Java程序(class文件)一开始并不是本地可执行文件;当运行Java程序时,先要运行JVM(Java虚拟机),然后再把Java class加载到JVM里头运行,负责加载Java class的这部分就叫做类加载器(ClassLoader)。
JVM本身包含了一个ClassLoader称为Bootstrap ClassLoader,和JVM一样,Bootstrap ClassLoader是用本地代码实现的,它负责加载核心Java Class(即所有java.*开头的类);另外JVM还会提供两个ClassLoader,它们都是用Java语言编写的,由Bootstrap ClassLoader加载;其中Extension ClassLoader负责加载扩展的Java class(例如所有javax.*开头的类和存放在JRE的ext目录下的类),Application ClassLoader负责加载应用程序自身的类。
其次,什么时候ClassLoader会加载类,当你使用java去执行一个类,JVM使用Application ClassLoader加载这个类;然后如果类A引用了类B,不管是直接引用还是用Class.forName()引用,JVM就会找到加载类A的ClassLoader,并用这个ClassLoader来加载类B。
网络配图
因为JVM自带的ClassLoader只会从本地文件系统加载标准的java class文件,如果我们编写自己的ClassLoader,就可以做到:
(1)、在执行非置信代码之前,自动验证数字签名;
(2)、动态地创建符合用户特定需要的定制化构建类;
(3)、从特定的场所取得java class,例如从数据库中;
目前的大部分应用服务器都使用了ClassLoader技术,即使我们不需要创建自己的ClassLoader,了解其原理也有助于更好地部署自己的应用到服务器。
如何创建一个ClassLoader?创建自己的ClassLoader时,需要继承java.lang.ClassLoader或者它的子类。在实例化每个ClassLoader对象时,需要指定一个父对象;如果没有指定的话,系统自动指定ClassLoader.getSystemClassLoader()为父对象。
Java Class的加载采用所谓的委托模式(Delegation Modle),当调用一个ClassLoader.loadClass()加载一个类的时候,将遵循以下的步骤:
检查这个类是否已经被加载进来了;
如果还没有加载,调用父对象加载该类;
如果父对象无法加载,调用本对象的findClass()取得这个类;
所以当创建自己的Class Loader时,只需要重载findClass()这个方法。
网络配图
通常程序发布后,部分功能有优化完善或修复Bug后如何更新已经被加载了的类进而更新应用的功能呢?JSP是一个非常典型的例子,如果一个JSP文件被更改了,应用服务器则需要把更改后的JSP重新编译,然后加载新生成的类来响应后继的请求;其实一个已经加载的类是无法被更新的,如果你试图用同一个ClassLoader再次加载同一个类,就会得到异常(java.lang.LinkageError: duplicate class definition),我们只能够重新创建一个新的ClassLoader实例来再次加载新类。
最后,学习一下类加载的形式;类加载无非就是以下三种方式:
class A{}
class B{}
class C{}
public class Loader{
public static void main(String[] args) throws Exception{
Class aa=A.class;
Class bb=Class.forName("B");
Class cc=ClassLoader.getSystemClassLoader().loadClass("C");
}
}
好了,今天先学习这么多,深层次的东西将在后续文章中学习!!!