重写ClassLoader,动态加载Class文件问题 重写ClassLoader,动态加载Class文件问题没有问题,但是在类型转换的时候出错,不知道该如何解决?请高手指点迷津! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 此回复为自动发出,仅用于显示而已,并无任何其他特殊作用楼主【ustbsjl】截止到2008-07-27 11:28:01的历史汇总数据(不包括此帖):发帖的总数量:5 发帖的总分数:210 每贴平均分数:42 回帖的总数量:97 得分贴总数量:61 回帖的得分率:62% 结贴的总数量:5 结贴的总分数:210 无满意结贴数:0 无满意结贴分:0 未结的帖子数:0 未结的总分数:0 结贴的百分比:100.00% 结分的百分比:100.00% 无满意结贴率:0.00 % 无满意结分率:0.00 % 敬礼! 估计你声明的类 和 生成对象的类 由不同的loader加载 package com.umpay.test;import java.io.*;public class CompilingClassLoader extends ClassLoader { // 读入文件,将它存为byte数组 private byte[] getBytes(String filename) throws IOException { File file = new File(filename); long len = file.length(); byte raw[] = new byte[(int) len]; FileInputStream fin = new FileInputStream(file); int r = fin.read(raw); if (r != len) throw new IOException("Can't read all, " + r + " != " + len); fin.close(); return raw; } // 以输入参数为文件名编译java文件,成功返回true,不成功返回false private boolean compile(String javaFile) throws IOException { System.out.println("CCL: Compiling " + javaFile + "..."); Process p = Runtime.getRuntime().exec("javac " + javaFile); try { p.waitFor(); } catch (InterruptedException ie) { System.out.println(ie); } // 取得编译是否成功的参数 int ret = p.exitValue(); // ret==0表示编译成功 return ret == 0; } // 核心程序,查找并载入java文件,看其是否需要编译 // 如需要,则编译后将其实例化,否则直接实例化 public Class loadClass(String name, boolean resolve) throws ClassNotFoundException { Class clas = findLoadedClass(name); // System.out.println( "findLoadedClass: "+clas ); // 生成文件路径 // 例如: java.lang.Object => java/lang/Object String fileStub = name.replace('.', '/'); String javaFilename = "src/" + fileStub + ".java"; String classFilename = "classes/" + fileStub + ".class"; File javaFile = new File(javaFilename); File classFile = new File(classFilename); System.out.println(javaFile.getAbsolutePath()); System.out.println(classFile.getAbsolutePath()); // System.out.println( "j "+javaFile.lastModified()+" c "+ // classFile.lastModified() ); // 根据文件日期,判断是否要重编译 if (javaFile.exists() && (!classFile.exists() || javaFile.lastModified() > classFile .lastModified())) { try { // 编译失败,或类文件不存在 if (!compile(javaFilename) || !classFile.exists()) { throw new ClassNotFoundException("Compile failed: " + javaFilename); } } catch (IOException ie) { throw new ClassNotFoundException(ie.toString()); } } // 在编译成功,或不需要编译的情况下,将class文件载入到byte数组 try { byte raw[] = getBytes(classFilename); // 将byte数组转化为Class类型实例 clas = defineClass(name, raw, 0, raw.length); } catch (IOException ie) { } // System.out.println( "defineClass: "+clas ); // 如果clas==null,按系统默认方式载入class if (clas == null) { clas = findSystemClass(name); } // System.out.println( "findSystemClass: "+clas ); if (resolve && clas != null) resolveClass(clas); // 如果仍然不能载入,则抛出错误 if (clas == null) throw new ClassNotFoundException(name); // 返回载入的class实例 return clas; }} /* * @(#)HelloWorld.java 2008-7-26 * * Copyright 2008 UMPay, Inc. All rights reserved. * Use is subject to license terms. */package com.umpay.test;/** * 描述: * * @version 1.0 * @author 沈建林 * @since 2008-7-26 */public class HelloWorld { /** * @param args */ public void sayHello() { // TODO Auto-generated method stub System.out.println("Hello, Java! Hello, Java!"); }} /* * @(#)Main.java 2008-7-26 * * Copyright 2008 UMPay, Inc. All rights reserved. * Use is subject to license terms. */package com.umpay.test;/** * 描述: * * @version 1.0 * @author 沈建林 * @since 2008-7-26 */public class Main { /** * @param args */ public static void main(String[] args) throws Exception { // TODO Auto-generated method stub while (true) { try { BytecodeClassLoader classLoader = new BytecodeClassLoader(); try { Object obj = classLoader.loadClass( "com.umpay.test.HelloWorld", true).newInstance(); System.out.println(obj); com.umpay.test.HelloWorld helloWorld = (com.umpay.test.HelloWorld) obj; helloWorld.sayHello(); } catch (InstantiationException inse) { // TODO Auto-generated catch block inse.printStackTrace(); } catch (IllegalAccessException illee) { // TODO Auto-generated catch block illee.printStackTrace(); } catch (ClassNotFoundException cnfe) { // TODO Auto-generated catch block cnfe.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } Thread.sleep(3 * 1000); if (false) { break; } } if (true) { return; } }} Object obj = classLoader.loadClass("com.umpay.test.HelloWorld", true).newInstance();//这段代码是使用classLoader对象//加载com.umpay.test.HelloWorld ,然后,再实例化一个对象.但是这个对象,是由classLoader对象加载的类来实例化的.com.umpay.test.HelloWorld helloWorld = (com.umpay.test.HelloWorld) obj;//这段代码,是要将obj对象进行强制类型转换.//但是,所要强之类型转换的类,并不是classLoader加载的,虽然,两个类都是com.umpay.test.HelloWorld,//但是,他们不是同一个ClassLoader加载到虚拟机的,所以,虚拟机会认为这是两个毫无关系的类,强制类型转换会出错./*解决这个问题,有两个方法:一种是使用反射调用sayHello方法,另一种是,声明一个接口类,让com.umpay.test.HelloWorld实现接口类的sayHello方法.这样,classLoader在加载com.umpay.test.HelloWorld类的时候,com.umpay.test.HelloWorld的父类(接口类)一般情况下,会被虚拟机的ClassLoad加载进来,这样,在做强制类型转换的时候,就是同一个接口类了.*/ com.umpay.test.HelloWorld helloWorld = (com.umpay.test.HelloWorld) obj; helloWorld.sayHello();改成 Method mm = obj .getClass().getMethod("sayHello", null); mm.invoke(obj , null); 楼上的.你这个应该不行把 这个是针对动态代理实现. 没有继承自InvocationHandler接口 却直接调用它的方法 我的代码就是一个简单的反射调用与动态代理没有任何关系 也不需要实现InvocationHandler接口 我用LZ写的程序是可以执行的而且我打印出他们俩的classLoader都是sun.misc.Launcher$AppClassLoader@82ba41sun.misc.Launcher$AppClassLoader@82ba41 如果BytecodeClassLoader classLoader = new BytecodeClassLoader();改为CompilingClassLoader classLoader = new CompilingClassLoader();的话不知道是不是LZ笔误还是另有BytecodeClassLoader 类? java 异常捕获问题,求教啊。。。 新手问问题之代码错在哪里 输入输出流 实现文件复制 关于static{} eclipse 卡死 正则表达式 关于repaint,paint,paintComponent...的问题 讨论一个有趣的问题,发明出可以比JAV,C++更先进的编程语言 那里可以下载java1.3 的API啊? 在Java有什么办法取得操作系统中进程的引用? JBuilder2007的问题!! gc
楼主【ustbsjl】截止到2008-07-27 11:28:01的历史汇总数据(不包括此帖):
发帖的总数量:5 发帖的总分数:210 每贴平均分数:42
回帖的总数量:97 得分贴总数量:61 回帖的得分率:62%
结贴的总数量:5 结贴的总分数:210
无满意结贴数:0 无满意结贴分:0
未结的帖子数:0 未结的总分数:0
结贴的百分比:100.00% 结分的百分比:100.00%
无满意结贴率:0.00 % 无满意结分率:0.00 %
敬礼!
package com.umpay.test;import java.io.*;public class CompilingClassLoader extends ClassLoader {
// 读入文件,将它存为byte数组
private byte[] getBytes(String filename) throws IOException { File file = new File(filename);
long len = file.length(); byte raw[] = new byte[(int) len]; FileInputStream fin = new FileInputStream(file); int r = fin.read(raw);
if (r != len)
throw new IOException("Can't read all, " + r + " != "
+ len); fin.close(); return raw;
} // 以输入参数为文件名编译java文件,成功返回true,不成功返回false
private boolean compile(String javaFile) throws IOException { System.out.println("CCL: Compiling " + javaFile + "..."); Process p = Runtime.getRuntime().exec("javac " + javaFile); try {
p.waitFor();
} catch (InterruptedException ie) {
System.out.println(ie);
} // 取得编译是否成功的参数
int ret = p.exitValue(); // ret==0表示编译成功
return ret == 0;
} // 核心程序,查找并载入java文件,看其是否需要编译
// 如需要,则编译后将其实例化,否则直接实例化
public Class loadClass(String name, boolean resolve)
throws ClassNotFoundException { Class clas = findLoadedClass(name); // System.out.println( "findLoadedClass: "+clas ); // 生成文件路径
// 例如: java.lang.Object => java/lang/Object String fileStub = name.replace('.', '/'); String javaFilename = "src/" + fileStub + ".java";
String classFilename = "classes/" + fileStub + ".class"; File javaFile = new File(javaFilename);
File classFile = new File(classFilename); System.out.println(javaFile.getAbsolutePath());
System.out.println(classFile.getAbsolutePath()); // System.out.println( "j "+javaFile.lastModified()+" c "+
// classFile.lastModified() ); // 根据文件日期,判断是否要重编译 if (javaFile.exists()
&& (!classFile.exists() || javaFile.lastModified() > classFile
.lastModified())) { try {
// 编译失败,或类文件不存在
if (!compile(javaFilename) || !classFile.exists()) {
throw new ClassNotFoundException("Compile failed: "
+ javaFilename);
}
} catch (IOException ie) { throw new ClassNotFoundException(ie.toString());
}
} // 在编译成功,或不需要编译的情况下,将class文件载入到byte数组
try { byte raw[] = getBytes(classFilename);
// 将byte数组转化为Class类型实例
clas = defineClass(name, raw, 0, raw.length);
} catch (IOException ie) {
} // System.out.println( "defineClass: "+clas );
// 如果clas==null,按系统默认方式载入class
if (clas == null) {
clas = findSystemClass(name);
} // System.out.println( "findSystemClass: "+clas ); if (resolve && clas != null)
resolveClass(clas); // 如果仍然不能载入,则抛出错误
if (clas == null)
throw new ClassNotFoundException(name); // 返回载入的class实例
return clas;
}
}
/*
* @(#)HelloWorld.java 2008-7-26
*
* Copyright 2008 UMPay, Inc. All rights reserved.
* Use is subject to license terms.
*/
package com.umpay.test;/**
* 描述:
*
* @version 1.0
* @author 沈建林
* @since 2008-7-26
*/
public class HelloWorld { /**
* @param args
*/
public void sayHello() {
// TODO Auto-generated method stub
System.out.println("Hello, Java! Hello, Java!");
}}
/*
* @(#)Main.java 2008-7-26
*
* Copyright 2008 UMPay, Inc. All rights reserved.
* Use is subject to license terms.
*/
package com.umpay.test;/**
* 描述:
*
* @version 1.0
* @author 沈建林
* @since 2008-7-26
*/
public class Main { /**
* @param args
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
while (true) {
try {
BytecodeClassLoader classLoader = new BytecodeClassLoader();
try {
Object obj = classLoader.loadClass(
"com.umpay.test.HelloWorld", true).newInstance();
System.out.println(obj); com.umpay.test.HelloWorld helloWorld = (com.umpay.test.HelloWorld) obj;
helloWorld.sayHello();
} catch (InstantiationException inse) {
// TODO Auto-generated catch block
inse.printStackTrace();
} catch (IllegalAccessException illee) {
// TODO Auto-generated catch block
illee.printStackTrace();
} catch (ClassNotFoundException cnfe) {
// TODO Auto-generated catch block
cnfe.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
} Thread.sleep(3 * 1000); if (false) {
break;
}
} if (true) {
return;
}
}
}
//加载com.umpay.test.HelloWorld ,然后,再实例化一个对象.但是这个对象,是由classLoader对象加载的类来实例化的.
com.umpay.test.HelloWorld helloWorld = (com.umpay.test.HelloWorld) obj;//这段代码,是要将obj对象进行强制类型转换.
//但是,所要强之类型转换的类,并不是classLoader加载的,虽然,两个类都是com.umpay.test.HelloWorld,
//但是,他们不是同一个ClassLoader加载到虚拟机的,所以,虚拟机会认为这是两个毫无关系的类,强制类型转换会出错.
/*
解决这个问题,有两个方法:一种是使用反射调用sayHello方法,另一种是,声明一个接口类,让com.umpay.test.HelloWorld实现接口类的sayHello方法.
这样,classLoader在加载com.umpay.test.HelloWorld类的时候,com.umpay.test.HelloWorld的父类(接口类)一般情况下,会被虚拟机的ClassLoad加载进来,这样,在做强制类型转换的时候,就是同一个接口类了.
*/
com.umpay.test.HelloWorld helloWorld = (com.umpay.test.HelloWorld) obj;
helloWorld.sayHello();
改成
Method mm = obj .getClass().getMethod("sayHello", null);
mm.invoke(obj , null);
却直接调用它的方法
而且我打印出他们俩的classLoader都是
sun.misc.Launcher$AppClassLoader@82ba41
sun.misc.Launcher$AppClassLoader@82ba41
BytecodeClassLoader classLoader = new BytecodeClassLoader();
改为
CompilingClassLoader classLoader = new CompilingClassLoader();
的话
不知道是不是LZ笔误
还是另有BytecodeClassLoader 类?