文章引用1:classloader机制概述,引用自:
JVM在运行时会产生三个ClassLoader,Bootstrap ClassLoader、Extension ClassLoader和AppClassLoader.其中,Bootstrap是用C++编写的,我们在Java中看不到它,是null。它用来加载核心类库,在JVM源代码中这样写道: static const char classpathFormat[] = "%/lib/rt.jar: " "%/lib/i18n.jar: " "%/lib/sunrsasign.jar: " "%/lib/jsse.jar: " "%/lib/jce.jar: " "%/lib/charsets.jar: " "%/classes "; 知道为什么不需要在classpath中加载这些类了吧?人家在JVM启动的时候就自动加载了,并且在运行过程中根本不能修改Bootstrap加载路径。 Extension ClassLoader用来加载扩展类,即/lib/ext中的类。 最后AppClassLoader才是加载Classpath的。 ClassLoader加载类用的是委托模型。即先让Parent类(而不是Super,不是继承关系)寻找,Parent找不到才自己找。看来ClassLoader还是蛮孝顺的。三者的关系为:AppClassLoader的Parent是ExtClassLoader,而ExtClassLoader的Parent为Bootstrap ClassLoader。加载一个类时,首先BootStrap先进行寻找,找不到再由ExtClassLoader寻找,最后才是AppClassLoader。 为什么要设计的这么复杂呢?其中一个重要原因就是安全性。比如在Applet中,如果编写了一个java.lang.String类并具有破坏性。假如不采用这种委托机制,就会将这个具有破坏性的String加载到了用户机器上,导致破坏用户安全。但采用这种委托机制则不会出现这种情况。因为要加载java.lang.String类时,系统最终会由Bootstrap进行加载,这个具有破坏性的String永远没有机会加载。 我们来看这段代码: //A.java
public class A{ public static void main(String[] args){ A a=new A(); System.out.println(System.getProperty( "java.ext.dirs ")); System.out.println(a.getClass().getClassLoader()); B b=new B(); b.print(); } } //B.java
public class B{ public void print(){ System.out.println(this.getClass().getClassLoader()); } } 1、我们将它放在Classpath中,则打印出 sun.misc.Launcher$AppClassLoader@92e78c sun.misc.Launcher$AppClassLoader@92e78c 可见都是由AppClassLoader来加载的。 2、我们将其放在%jre%/lib/ext/classes(即ExtClassLoader的加载目录。其加载/lib/ext中的jar文件或者子目录classes中的class文件)中。则会打印出: sun.misc.Launcher$ExtClassLoader sun.misc.Launcher$ExtClassLoader 3、我们将A.class放到%jre%/lib/ext/classes中,而将B.class放到classpaht中又会怎么样呢?结果是: sun.misc.Launcher$ExtClassLoader Exception in thread "main " java.lang.NoClassDefFoundError:B at A.main(A.java:6) 怎么会这样呢?这其中有一个重要的问题:A类当然是由ExtClassLoader来加载的,B类要由哪个加载呢?B类要由调用它自己的类的类加载器(真拗口)。也就是说,A调用了B,所以B由A的类加载器ExtClassLoader来加载。ExtClassLoader根据委托机制,先拜托Bootstrap加载,Bootstrap没有找到。然后它再自己寻找B类,还是没找到,所以抛出异常。ExtClassLoader不会请求AppClassLoader来加载!你可能会想:这算什么问题,我把两个类放到一起不就行了? 呵呵,没这么简单。比如JDBC是核心类库,而各个数据库的JDBC驱动则是扩展类库或在classpath中定义的。所以JDBC由Bootstrap ClassLoader加载,而驱动要由AppClassLoader加载。等等,问题来了,Bootstrap不会请求AppClassLoader加载类啊。那么,他们怎么实现的呢?我就涉及到一个Context ClassLoader的问题,调用Thread.getContextClassLoader。具体我还没搞太明白,要知后事如何,请听下回分解!(啊!别拿砖
|
文章引用2: weblogic的classloader装载策略及部署应用的目录结构
weblogic的classloader装载策略及部署应用的目录结构1 目录结构 在weblogic上要发布一个web applicate必须有下面的目录结构: mywebapp |____WEB-INF |___lib //放这个web application所需要的jar包
|___classes //放class类
|___web.xml //对这个web application描述
发布一个application需要有下面的目录结构: myapplication |___APP-INF //放在这个目录下的lib和classes不能实例化webapp下的类
| |___lib //放ejb和webapp公用的jar包
| |___classes //放ejb和webapp公用的类
|___META-INF | |__application.xml |___mywebapp | |____WEB-INF | |___lib | |___classes //放class类
| |___web.xml |___ejb.jar //ejb的jar包
==================================================================================
2 classloader classloader是分层次的,它只能加载比它层次高的类及它自身的类,同层次的类及比它层次低的类都不能加载。在weblogic中的classloader有5个层次,从高到低排: a. jdk b. jdk ext c. system classpath d. (APP-INF/lib and APP-INF/classes) e. (WEB-INF/lib and WEB-INF/classes) f. ejb.jar 注意:e 和 f 的classloader是同级的。 所以APP-INF/lib和APP-INF/classes下类不能实例化webapp下的类,这点尤其要注意,否则会报类找不到的错误。
|
|
文件: |
WebLogic类加载过程简述.rar |
大小: |
177KB |
下载: |
下载 | |
阅读(1794) | 评论(0) | 转发(0) |