手机站
网通分站
电信主站
密 码:
用户名:
当前位置 : 主页>程序设计>Java技术>列表

Class Loading ---(类装载机制,开发者不得不知道的故事) --下篇

来源:互联网 作者:west263.com 时间:2008-02-23
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!

如何构造使用自定义的ClassLoader

既然自定义的ClassLoader,能解决上述问题,那接下去看看,我们如何来使用自定义的ClassLoader。

结合本文种的原码---(在differentversionspush的目录里),有个FileSystemClassLoader,类图描述如下:


图9.

看看他的方法 findClassBytes(String className);

public byte[] findClassBytes(String className){

try{
String pathName = currentRoot
File.separatorChar className.
replace('.', File.separatorChar)
".class";
FileInputStream inFile = new
FileInputStream(pathName);
byte[] classBytes = new
byte[inFile.available()];
inFile.read(classBytes);
return classBytes;
}
catch (Java.io.IOException ioEx){
return null;
}
}

public Class findClass(String name)throws
ClassNotFoundException{

byte[] classBytes = findClassBytes(name);
if (classBytes==null){
throw new ClassNotFoundException();
}
else{
return defineClass(name, classBytes,
0, classBytes.length);
}
}

public Class findClass(String name, byte[]
classBytes)throws ClassNotFoundException{

if (classBytes==null){
throw new ClassNotFoundException(
"(classBytes==null)");
}
else{
return defineClass(name, classBytes,
0, classBytes.length);
}
}

public void execute(String codeName,
byte[] code){

Class klass = null;
try{
klass = findClass(codeName, code);
TaskIntf task = (TaskIntf)
klass.newInstance();
task.execute();
}
catch(Exception exception){
exception.printStackTrace();
}
}

这个类FileSystemClassLoader 被client使用了,用来定义class, 并且把它把client.TaskImpl(v1)转化为 byte[], 然后 byte[]发送到RMI Server执行。(上面讲了defineClass()能够执行任何字节码,来自编译后的文件,网络甚至是BCEL 字节码引擎库), 在Server端 ,又可以通过FileSystemClassLoader 以为byte[]的形式定义出 client.TaskImpl。

请看Client端的代码:

public class Client{

public static void main (String[] args){

try{
byte[] code = getClassDefinition
("client.TaskImpl");
serverIntf.execute("client.TaskImpl",
code);
}
catch(RemoteException remoteException){
remoteException.printStackTrace();
}
}

private static byte[] getClassDefinition
(String codeName){
String userDir = System.getProperties().
getProperty("BytePath");
FileSystemClassLoader fscl1 = null;

try{
fscl1 = new FileSystemClassLoader
(userDir);
}
catch(FileNotFoundException
fileNotFoundException){
fileNotFoundException.printStackTrace();
}
return fscl1.findClassBytes(codeName);
}
}

在RMI服务器端ServerImpl 程序里, 接受到来自client的字节码(byte[]),于是FileSystemClassLoader 会从byte[]构造出一个class, 实例话,并且执行。

有一点要注意:每次接收到一个client的请求,FileSystemClassLoader都会重新实例化(执行结果中可以看出来),这就意味着,client.Impl不在是在classpath中被找到的,而是通过FileSystemClassLoader 的findClass() 来执行deFineClass(),这样每次 FileSystemClassLoader 都是创建新的实例,,自然 deFine出来的class也是不同的。 这样,我们就能在RMI的执行中区分出 这两个class来。(client.TaskImpl != client.TaskImp 在上篇就已经得出结论了。 )

看看服务器端的执行代码:

public void execute(String codeName, byte[] code)throws RemoteException{

FileSystemClassLoader fileSystemClassLoader = null;

try{
fileSystemClassLoader = new FileSystemClassLoader();

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!