posts - 14,  comments - 37,  trackbacks - 0
      JavaClassLoaderPackage机制介绍了ClassLoader的委派机制,它是把装载的任务传递给上级的装载器的,依次类推,直到启动类装载器(没有上级类装载器)。如果启动类装载器能够装载这个类,那么它会首先装载。如果不能,则往下传递。其实这引出一个运行时包的概念。不同装载器装载的类,即使包名相同也不能互相访问。这样保证了核心类库不被破坏。(by juxtapose)

      本文将讲述如何扩展ClassLoader类实现一个自己的类装载器,每个Class对象都有一个引用指向装载他的ClassLoader,你可以通过public ClassLoader getClassLoader()方法得到它。为了创建自己的类装载器我们应该扩展ClassLoader类,这是一个抽象类。我们目的是从本地文件系统使用我们实现的类装载器装载一个类。我们创建一个FileClassLoader extends ClassLoader。我们需要覆盖ClassLoader中的
findClass(String name)
方法,这个方法通过类的名字而得到一个Class对象。

public Class findClass(String name)
{
byte[] data = loadClassData(name);
return defineClass(name, data, 0, data.length);
}

 

我们还应该提供一个方法loadClassData(String name),通过类的名称返回class文件的字节数组。然后使用ClassLoader提供的defineClass()方法我们就可以返回Class对象了。

public byte[] loadClassData(String name)
{
FileInputStream fis 
= null;
byte[] data = null;
try
{
fis 
= new FileInputStream(new File(drive + name + fileType));
ByteArrayOutputStream baos 
= new ByteArrayOutputStream();
int ch = 0;
while ((ch = fis.read()) != -1)
{
baos.write(ch);

}

data 
= baos.toByteArray();
}
 catch (IOException e)
{
e.printStackTrace();
}


return data;
}


这里我们是从D盘装载一个类。

下面我们提供一个类public class MyApp{},类中没有定义任何方法和变量,下面我们编译MyApp.java得到MyApp.class,然后把文件放在D盘的根目录。为了证明MyApp.class是被我们定义的classloader装载的,我们在FileClassLoadermain()方法中打印出装载MyApp.class的类装载器的名称。
 

public static void main(String[] args) throws Exception
{
FileClassLoader loader 
= new FileClassLoader();
Class objClass 
= loader.loadClass("MyApp"true);
Object obj 
= objClass.newInstance();
System.out.println(objClass.getName());
System.out.println(objClass.getClassLoader());


}

编译FileClassLoader
javac FileClassLoader.java
然后运行java FileClassLoader 可以看到输出结果为

MyApp
FileClassLoader@1a5ab41

如果你把MyApp.class放入到你程序的所在目录会出现什么情况呢?读者自己实践一下吧!

结果为:MyApp

sun.misc.Launcher$AppClassLoader@92e78c

下面给出FileClassLoader的源代码。/*

 

* Created on 2005-7-27

*

* To change the template for this generated file go to

* Window>Preferences>Java>Code Generation>Code and Comments

*/


/**

@author liuxiang

*

* To change the template for this generated type comment go to

* Window>Preferences>Java>Code Generation>Code and Comments

*/


import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

public class FileClassLoader extends ClassLoader

{

public static final String drive = "d:/";

public static final String fileType = ".class";


public FileClassLoader() {

super();


}



public FileClassLoader(ClassLoader arg0) {

super(arg0);

}



public Class findClass(String name)

{

byte[] data = loadClassData(name);

/*

* Converts an array of bytes into an instance of class Class. 

* Before the Class can be used it must be resolved. 



* This method assigns a default ProtectionDomain to the newly 

* defined class. The ProtectionDomain contains the set of 

* permissions granted when a call to Policy.getPolicy().getPermissions() 

* is made with a code source of null,null. The default domain 

* is created on the first invocation of defineClass, and re-used 

* on subsequent calls. 

* To assign a specific ProtectionDomain to the class, use the 

* defineClass method that takes a ProtectionDomain as one of 

* its arguments. 

*/


/*

* 该方法接受由原始字节组成的数组并把它转化成class对象

* 原始字节包含从文件系统或网络装入的data

* defineClass管理JVM中许多复杂、神秘和依赖于实现的方面————

* ————它把字节码分析成运行时数据结构、校验有效性等。

*/


return defineClass(name, data, 0, data.length);

}



/*

* 将对应的Class文件读为byte[]

*/


public byte[] loadClassData(String name)

{

FileInputStream fis 
= null;

byte[] data = null;

try

{

//装载d:根目录下面的.class文件到data中

fis 
= new FileInputStream(new File(drive + name + fileType));

ByteArrayOutputStream baos 
= new ByteArrayOutputStream();

int ch = 0;

while ((ch = fis.read()) != -1)

{

baos.write(ch);


}


data 
= baos.toByteArray();

}
 catch (IOException e)

{

e.printStackTrace();

}



return data;

}
 


public static void main(String[] args) throws Exception

{

FileClassLoader loader 
= new FileClassLoader();

//装载类MyApp

Class objClass 
= loader.loadClass("MyApp"true);

//生成MyApp的一个实例

Object obj 
= objClass.newInstance();

//获得类的名称

System.out.println(objClass.getName());

//获得类的装载器的名称

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

}


}

 

posted on 2007-07-11 13:10 冰封的爱 阅读(103) 评论(0)  编辑  收藏 所属分类: J2EE

只有注册用户登录后才能发表评论。


网站导航:
 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

常用链接

留言簿(3)

随笔档案

文章分类

文章档案

相册

搜索

  •  

最新评论

阅读排行榜

评论排行榜