java类的装载(二)
来源:优易学  2009-12-4 10:19:14   【优易学:中国教育考试门户网】   资料下载   IT书店
文章页内部300*250广告位

 

 //查看被加载的TestBean类型是被那个类加载器加载的

  System.out.println(typeLoaded.getClassLoader());

  } catch (Exception e) {

  e.printStackTrace();

  }

  }

  }

  对应的输出如下:

  D:"DEMO"dev"Study"ClassLoaderTest"bin

  sun.misc.Launcher$AppClassLoader@197d257

  (说明:当前类路径默认的含有的一个条目就是工程的输出目录)

  测试二:

  将当前工程输出目录下的…/classloader/test/bean/TestBean.class打包进test.jar剪贴到< Java_Runtime_Home >/lib/ext目录下(现在工程输出目录下和JRE扩展目录下都有待加载类型的class文件)。再运行测试一测试代码,结果如下:

  D:"DEMO"dev"Study"ClassLoaderTest"bin

  sun.misc.Launcher$ExtClassLoader@7259da

  对比测试一和测试二,我们明显可以验证前面说的双亲委派机制,系统类加载器在接到加载classloader.test.bean.TestBean类型的请求时,首先将请求委派给父类加载器(标准扩展类加载器),标准扩展类加载器抢先完成了加载请求。

  测试三:

  将test.jar拷贝一份到< Java_Runtime_Home >/lib下,运行测试代码,输出如下:

  D:"DEMO"dev"Study"ClassLoaderTest"bin

  sun.misc.Launcher$ExtClassLoader@7259da

  测试三和测试二输出结果一致。那就是说,放置到< Java_Runtime_Home >/lib目录下的TestBean对应的class字节码并没有被加载,这其实和前面讲的双亲委派机制并不矛盾。虚拟机出于安全等因素考虑,不会加载< Java_Runtime_Home >/lib存在的陌生类,开发者通过将要加载的非JDK自身的类放置到此目录下期待启动类加载器加载是不可能的。做个进一步验证,删除< Java_Runtime_Home >/lib/ext目录下和工程输出目录下的TestBean对应的class文件,然后再运行测试代码,则将会有 ClassNotFoundException异常抛出。有关这个问题,大家可以在java.lang.ClassLoader中的 loadClass(String name, boolean resolve)方法中设置相应断点运行测试三进行调试,会发现findBootstrapClass0()会抛出异常,然后在下面的findClass 方法中被加载,当前运行的类加载器正是扩展类加载器(sun.misc.Launcher$ExtClassLoader),这一点可以通过JDT中变量视图查看验证。

  (5)被不同的ClassLoader加载的两个类之间有什么限制和不同?

  现在我们来看一下一个现象:

  在eclipse里面我是这样做的:

  OneCls.java

  package org.corey.one;

  import org.corey.two.TwoCls;

  public class OneCls {

  public OneCls() {

  System.out.println();

  TwoCls two = new TwoCls();

  two.say();

  }

  }

  TwoCls.java

  package org.corey.two;

  public class TwoCls {

  public void say() {

  System.out.println("i am two");

  }

  }

  Demo.java:

  package org.corey.Demo;

  import org.corey.one.OneCls;

  public class Demo {

  /**

  * @param args

  */

  public static void main(String[] args) {

  OneCls one=new OneCls();

  }

  }

  在这里,我们来仔细看下,one引用了two,demo引用了one,这是三个类都是由AppClassLoader加载的;运行正常;

  把OneCls打成jar包,放在lib/ext路径下面,然后在工程里面引入这个jar包;运行:异常,这是因为:

  Demo是由AppClassLoader载入,委托给双亲加载失败后,由AppClassLoader加载,而加载OneCls的时候,委托给双亲,被ExtClassLoader加载成功,但是在载入OneCls的时候,同时引用了TwoCls,但是ExtClassLoader引用 TwoCls失败,但是他只会委托给双亲,而不会委托给AppClassLoader这个儿子,所以会出现异常;

上一页  [1] [2] 

责任编辑:小草

收藏此页】【 】【打印】【回到顶部
等级考试课程列表页595*300
文章搜索:
 相关文章
计算机底部580*90广告
文章页右侧第一330*280广告
计算机文章页资讯推荐
热点资讯
文章页330尺寸谷歌广告位
资讯快报
热门课程培训