重写ClassLoader,动态加载Class文件问题没有问题,但是在类型转换的时候出错,不知道该如何解决?请高手指点迷津!

解决方案 »

  1.   

    此回复为自动发出,仅用于显示而已,并无任何其他特殊作用
    楼主【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  %                  
    敬礼!
      

  2.   

    估计你声明的类 和 生成对象的类 由不同的loader加载
      

  3.   


    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;
    }
    }
      

  4.   


    /*
     * @(#)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!");
    }}
      

  5.   


    /*
     * @(#)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;
    }
    }
    }
      

  6.   

    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加载进来,这样,在做强制类型转换的时候,就是同一个接口类了.
    */
      

  7.   

                     
                        com.umpay.test.HelloWorld helloWorld = (com.umpay.test.HelloWorld) obj;
                        helloWorld.sayHello();
    改成
                   
    Method mm = obj .getClass().getMethod("sayHello", null);
    mm.invoke(obj , null);
      

  8.   

    楼上的.你这个应该不行把 这个是针对动态代理实现.  没有继承自InvocationHandler接口
       却直接调用它的方法
      

  9.   

    我的代码就是一个简单的反射调用与动态代理没有任何关系 也不需要实现InvocationHandler接口
      

  10.   

    我用LZ写的程序是可以执行的
    而且我打印出他们俩的classLoader都是
    sun.misc.Launcher$AppClassLoader@82ba41
    sun.misc.Launcher$AppClassLoader@82ba41
      

  11.   

    如果
    BytecodeClassLoader classLoader = new BytecodeClassLoader();
    改为
    CompilingClassLoader classLoader = new CompilingClassLoader();
    的话
    不知道是不是LZ笔误
    还是另有BytecodeClassLoader 类?