今天开始复习JAVA的相关知识,又碰到了ClassLoader问题,所以拿来好好回顾一番。
基本功能
ClassLoader的主要作用是对类的请求提供服务,当JVM需要某类时,它根据名称向ClassLoader要求这个类,然后由ClassLoader返回这个类的class对象。
几个相关概念
ClassLoader负责载入系统所有Resources(Class,文件,来自网络的字节流等),通过ClassLoader从而将资源载入JVM,每一个class都有一个reference,指向自己的ClassLoader(Class.getClassLoader())。
工作过程(委托模型)
自从JDK1.2以后,ClassLoader做了改进,使用了委托模型,所有系统中的ClassLoader组成一棵树,ClassLoader在载入类库时先让Parent寻找,Parent找不到才自己找。 JVM在运行时会产生三个ClassLoader,Bootstrap ClassLoader、Extension ClassLoader和App ClassLoader。其中,Bootstrap ClassLoader是用C++编写的,在Java中看不到它,是null。它用来加载核心类库,就是在lib下的类库,Extension ClassLoader加载lib/ext下的类库,App ClassLoader加载Classpath里的类库,三者的关为:App ClassLoader的Parent是Extension ClassLoader,而Extension ClassLoader的Parent为Bootstrap ClassLoader。加载一个类时,首先BootStrap进行寻找,找不到再由Extension ClassLoader寻找,最后才是App ClassLoader。
将ClassLoader设计成委托模型的一个重要原因是出于安全考虑,比如在Applet中,如果编写了一个java.lang.String类并具有破坏性。假如不采用这种委托机制,就会将这个具有破坏性的String加载到了用户机器上,导致破坏用户安全。但采用这种委托机制则不会出现这种情况。因为要加载java.lang.String类时,系统最终会由Bootstrap进行加载,这个具有破坏性的String永远没有机会加载。
ClassLoader源代码
protected synchronized Class loadClass(String name,boolean resolve) throws ClassNotFoundException{ //首先检查该name指定的class是否有被加载 Class c = findLoadedClass(name); if(c == null){ try{ if(parent != null){ //如果parent不为null,则调用parent的loadClass进行加载 c = parent.loadClass(name,false); }else{ //parent为null,则调用BoostrapClassLoader进行加载 c = findBootstrapClass0(name); } }catch(ClassNotFoundException e){ //如果仍然无法加载成功,则调用自身的findClass进行加载 c = findClass(name); } } if(resolve){ resolveClass(c); } return c; }