新人求教一个关于classloader动态加载类并实例化得问题的问题

dhcworldhy 2011-07-24 01:16:02
已经写好了一个自定义类加载器MyClassloader,其父加载器是默认的系统类加载器(也就是程序类加载器)
有一个类
class Father
{
public void execute()
{
System.out.println("Father");
}
}
其class文件 在当前的工程classpath下 C:\Documents and Settings\Administrator\workspace\ClassLoader\bin

还有一个类
class Child extends Father
{
public void execute()
{
System.out.println("Son");
}
}
其class文件在 C:\ 下

运行时 系统类加载器会加载Father 这个是成功的
Father obj=(Father)myClassLoader.loadclass("C:\Child.class").newInstance(); 是失败的!!!!!
异常
java.lang.IllegalAccessError:class Child cannot access its superclass Father
分析
由于 class Child extends Father 那么myClassLoader加载Child 首先要加载 Father
Father的类文件在classpath下 由于父委托机制 由myClassLoader的父加载器(即系统类加载器)成功加载Father
问题
1.问什么由 myClassLoader加载的Child 访问不到 由myClassLoader父加载器加载的Father 呢?
2.怎么把程序Father obj=(Father)myClassLoader.loadclass("C:\Child.class").newInstance(); 运行成功,
就要这样把Child的对象向上转型为Father。


import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

class MyClassLoader extends ClassLoader
{

protected Class<?> findClass(String filename) throws ClassNotFoundException
{
byte[] data=this.loadClassDate(filename);
//如果filename为 C:\Sample.class 恩classname为Sample
String classname=filename.substring(filename.lastIndexOf("\\")+1,filename.lastIndexOf("."));
return this.defineClass(classname,data, 0, data.length);
}

public byte[] loadClassDate(String filename) throws ClassNotFoundException
{
FileInputStream in=null;
ByteArrayOutputStream out=null;
try
{
in=new FileInputStream(new File(filename));
out=new ByteArrayOutputStream();
int i;
while((i=in.read())!=-1)
{
out.write(i);
}
return out.toByteArray();
}
catch(Exception e)
{
return null;
}
finally
{
try
{
in.close();
out.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}

}

想写这个程序是因为看了这篇文章,可是坑爹的是文章最后有问题,没有具体的例子,而且复制的时候把文章内容都搞的有问题。


那就是利用面向对象的基本特性之一的多形性。我们把我们动态载入的Class的实例造型成它的一个system classloader所能识别的父类就行了!这是为什么呢?我们还是要再来分析一次。当我们用我们自己的classloader来动态载入这我们只要把这个Class的时候,发现它有一个父类Class,在载入它之前JVM先会载入这个父类Class,这个父类Class是system classloader所能识别的,根据委托机制,它将由system classloader载入,然后我们的classloader再载入这个Class,创建一个实例,造型为这个父类Class,注意了,造型成这个父类 Class的时候(也就是上溯)是面向对象的java语言所允许的并且JVM也支持的,JVM就使用system classloader再次载入这个父类Class,然后将此实例造型为这个父类Class。大家可以从这个过程发现这个父类Class都是由 system classloader载入的,也就是同一个class loader载入的同一个Class,所以造型的时候不会出现任何异常。而根据多形性,调用这个父类的方法时,真正执行的是这个Class(非父类 Class)的覆盖了父类方法的方法。这些方法中也可以引用system classloader不能识别的Class,因为根据全盘负责原则,只要载入这个Class的classloader即我们自己定义的 classloader能够定位和载入这些Class就行了。

全文
http://www.sunxin.org/forum/thread/19764.html
...全文
269 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
dhcworldhy 2011-07-24
  • 打赏
  • 举报
回复
怎么木有人啊
dhcworldhy 2011-07-24
  • 打赏
  • 举报
回复
这个问题的价值在于

这样我们就可以事先定义好一组接口或者基类并放入CLASSPATH中,然后在执行的时候动态的载入实现或者继承了这些接口或基类的子类。还不明白吗?让我们来想一想Servlet吧,web application server能够载入任何继承了Servlet的Class并正确的执行它们,不管它实际的Class是什么,就是都把它们实例化成为一个Servlet Class,然后执行Servlet的init,doPost,doGet和destroy等方法的,而不管这个Servlet是从web- inf/lib和web-inf/classes下由system classloader的子classloader(即定制的classloader)动态载入。说了这么多希望大家都明白了。在applet,ejb等容器中,都是采用了这种机制.

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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