神奇的Weblogic的ClassLoader?

dickmi 2003-04-03 12:38:19
工作原因要把一个版本从weblogic移到tomcat
代码中有prop.getClass().getResourceAsStream(str),发生问题

环境:
在Weblogic的大多数板本5.1,6.1,7.1。tomcat 4.1
使用getClass().getResourceAsStream(str),而且这个str是在WEB_INF下的Classes目录下.

在tomcat 下
这么使用:
getClass().getResourceAsStream(str) 能够加载这个文件
如果我这么使用:
Properties prop = new Properties();
prop.getClass().getResourceAsStream(str) 加载不到这个文件
这是ClassLoader的机制所决定的,所以非常正确

但是在Weblogic下两种方式都能加载,这就是神奇的Weblogic,
有谁能有解释一下?
...全文
446 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
dickmi 2003-07-31
  • 打赏
  • 举报
回复
恒久以前的贴子了,赫赫,我来自我回答一下吧,原因是JDK为了支持资源的安全性访问而采取了这种机制,但是如果服务器支持认证证书,就可以绕开访问,weblogic有证书机制,而tomcat没有,所以....
ji_jian24 2003-07-30
  • 打赏
  • 举报
回复
mymoto

厉害

pf
whohu 2003-07-30
  • 打赏
  • 举报
回复
各位都好高呀,PF PF !
pengji 2003-07-30
  • 打赏
  • 举报
回复
你分别在weblogic和tomcat中调用下面这句话看看:
System.out.println(prop.getClass().getClassLoader());
看看他们到底是什么东西!!
flowercat 2003-07-30
  • 打赏
  • 举报
回复
study
subscribe 2003-07-30
  • 打赏
  • 举报
回复
gz
armorking2003 2003-06-10
  • 打赏
  • 举报
回复
gz
mymoto 2003-06-10
  • 打赏
  • 举报
回复
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。具体我还没搞太明白,要知后事如何,请听下回分解!(啊!别拿砖头砸我...)

67,511

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧