一个外部jar文件,有两个类:
/**
 * 
 */
package dynamic.test2;public class Personal extends Object{ private String name="";
private int age = 0;
private boolean isMale = true;
/**
 * 
 */
public String toString(){
return this.getClass().getName()+": "+name+"@"+age+"@"+isMale;
}
public Personal() {
// TODO Auto-generated constructor stub
}
public Personal(String _name,int _age,boolean _ismale){
this.name = _name;
this.age = _age;
this.isMale = _ismale;
}
public void setName(String value){
this.name = value;
}
public String getName(){
return this.name;
}

public void setAge(int value){
this.age = value;
}
public int getAge(){
return this.age;
}

public void setMale(boolean value){
this.isMale = value;
}
public boolean isMale(){
return this.isMale==true;
}}=====
/**
 * 
 */
package dynamic.test2;import java.util.ArrayList;
import java.util.List;public class Group { private List<Personal> peoples = new ArrayList<Personal>();
/**
 * 
 */
public Group() {
// TODO Auto-generated constructor stub
} public void add(){
Personal item = new Personal("auto",0,true);
peoples.add(item);
}
public void add(String name,int age,boolean ismale){
Personal item = new Personal(name,age,ismale);
peoples.add(item);
}

public void add(Personal item){
peoples.add(item);

}
public List getPersonals(){
return this.peoples;
}

}生成外部的test2.jar
写一个测试程序,采用反射原理,动态的加载了test2.jar文件 ,调用dynamic.test2.Group.add()后,再调用dynamic.test2.Group.getPersonals()来得到list. 出错代码如下:
...
fm.executeFunction("add", new Object[0],cinst);
List list = (List)fm.executeFunction("getPersonals", new Object[0],cinst);//正常
if(list==null){
System.out.println("result is null");
}
else{
System.out.println(list.size()); //正常,得到大小 =1

Iterator it = list.iterator(); //正常
while(it.hasNext()){
                              Object o = it.next();
System.out.println(o.getClass().getName()); //正常,输出就是 dynamic.test2.Personal 
Personal item = (Personal)o; //这句就出错了:java.lang.ClassCastException: dynamic.test2.Personal cannot be cast to dynamic.test2.Personal

System.out.println(item.getName()+" "+ item.getAge()+" "+item.isMale());
}
}
...这个问题不知怎样解决?

解决方案 »

  1.   

    fm.executeFunction("add", new Object[0],cinst); fm是啥?怀疑是classloader的问题。
      

  2.   

    fm是自己写的一个加载类,负责把外部的jar加载到当前loader中,
    classloader是这样的: 
    URLClassLoader loader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    Class cls = loader.loadClass("test2.jar");
    ...
      

  3.   

    /**
     * 
     */
    package dynamic.functions;import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;public class FunctionItem implements Comparable{ private String name="";
    private String excutePoint="";
    private boolean isAllow=true;
    private int priority=0;
    private String className="";
    private String url="";
    private String description="";
    private List paramsType = new ArrayList();
    private String resultType=null;


    private Class instance=null;
    private ClassLoader loader = null; private Map<String,Object> attributes = new HashMap<String,Object>();





    /**
     * 
     */
    public FunctionItem() {
    // TODO Auto-generated constructor stub
    }
    public void attributeValue(String key,Object value){
    this.attributes.put(key, value);
    }
    public Object attribute(String key){
    return this.attributes.get(key);
    }
    public void setClass1(Class object){
    this.instance = object;
    }

    public Class getClass1(){
    return this.instance;
    }
    @SuppressWarnings("finally")
    public Object newInstance(){
    Object rlt = null;
    try {
    rlt=this.loader.loadClass(this.className).newInstance();
    } catch (InstantiationException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (ClassNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    finally{
    return rlt;
    }
    }
    public void setClassLoader(ClassLoader object){
    this.loader = object;
    }
    public ClassLoader getClassLoader(){
    return this.loader;
    }
    public void setResultType(String value){
    this.resultType = value;
    }
    public String getResultType(){
    return this.resultType;
    }
    public void addParamType(String type){
    this.paramsType.add(type);
    }
    public List getParamType(){
    return this.paramsType;
    }
    public Iterator iteratorParams(){
    return this.paramsType.iterator();
    }
    public int sizeParams(){
    return this.paramsType.size();
    }
    public void clearParamsType(){
    this.paramsType.clear();
    }


    public void setClassName(String value){
    this.className = value;
    }
    public String getClassName(){
    return this.className;
    }

    public void allow(boolean value){
    this.isAllow = value;
    }
    public boolean isAllow(){
    return this.isAllow==true;
    }

    public void setName(String value){
    this.name = value;
    }
    public String getName(){
    return this.name;
    }

    public void setExcutePoint(String value){
    this.excutePoint = value;
    }
    public String getExcutePoint(){
    return this.excutePoint;
    }


    public String getURL(){
    return this.url;
    }

    public void setURL(String value){
    this.url = value;
    }

    public void setDescription(String value){
    this.description = value;
    }
    public String getDescription(){
    return this.description;
    }

    public int getPriority(){
    return this.priority;
    }
    public void setPriority(int value){
    this.priority = value;
    } public String toString(){
    return this.getClass().getName()+":name="+this.getName()+"@"
    +"url="+this.getURL()+"@"
    +"priority="+this.getPriority()+"@"
    +"allow="+this.isAllow+"@"
    +"classname="+this.getClassName()+"@"
    +"description="+this.getDescription();
    }

    @Override
    public int compareTo(Object obj) {
    // TODO Auto-generated method stub
    if(obj instanceof FunctionItem){
    FunctionItem other = (FunctionItem)obj;
    if(getPriority()>other.getPriority()){
    return 1;
    }
    else if(getPriority()<other.getPriority()){
    return -1;
    }
    return 0;
    }
    else if(obj instanceof Comparable){
    return   -((Comparable)obj).compareTo(this); 
    }
    else{
    throw   new   java.lang.IllegalArgumentException();  
    } }}
      

  4.   

    package dynamic.functions;import dynamic.DynamicClassLoad;
    import dynamic.DynamicClassLoadEventListener;
    import dynamic.DynamicClassLoadHandler;
    import dynamic.MethodUtil;
    /**
     *
     * 1. set configFile;
     * 2. run;
     */
    public class FunctionManager { private String configFile = "file://"+System.getProperty("user.dir")+"/dynamic/dynamic.config";
    private java.util.Timer timer=null;
    private int checkPeriod = 6000;

    private List<FunctionItem> functions = new LinkedList<FunctionItem>();

    private DynamicClassLoadHandler dynamicHandler ;
    private DynamicClassLoad dynamicLoad ;

    private DynamicClassLoadEventListener dynamicListener ;

    private long flength=0;
    private long fmodified = 0;
    /**
     * 
     */
    public FunctionManager() {
    // TODO Auto-generated constructor stub
    dynamicHandler = new LoadHandler();
    dynamicLoad = new DynamicClassLoad(dynamicHandler);
    dynamicLoad.setRelationParentLoader(true);
    dynamicLoad.setLoader(this.getClass().getClassLoader());
    dynamicListener = new LoadEventListener(dynamicLoad,this);
    dynamicLoad.addListener(dynamicListener);

    }
    public void setConfigURL(String url){
    this.configFile = url;

    }
    public String getConfigFile(){
    return this.configFile;
    }
    public void setCheckPeriod(int msecond){
    this.checkPeriod = msecond;
    }
    public int getCheckPeriod(){
    return this.checkPeriod;
    }
    private void addFunctionItem(FunctionItem item){
    this.functions.add(item);
    }
    public int size(){
    return this.functions.size();
    }
    public Iterator iteratorFunctions(){
    return this.functions.iterator();
    }

    private void clearFunctions(){
    this.functions.clear();
    } public void checkAll() {
    // TODO Auto-generated method stub
    URL url;
    InputStream in;
    URLConnection uc;
    try {
    url = new URL(this.configFile);
    in = url.openStream();
    uc = url.openConnection();
    } catch (MalformedURLException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
    return ;
    } catch(IOException e){
    e.printStackTrace();
    return;
    }


    long size = uc.getContentLength();
    long lastmodify = uc.getLastModified();
    if(flength==size && fmodified == lastmodify) return;
    flength=size;
    fmodified = lastmodify;


    SAXReader rdr = new SAXReader();
    Document document=null;
    try {
    document = rdr.read(in);
    } catch (DocumentException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    return;
    }

    clearFunctions();

    Node node = document.selectSingleNode("/functions");

    if(node==null){
    return;
    }

    List list = node.selectNodes("functionItem");
    for(Object o : list){
    Element e = (Element)o;
    FunctionItem fitem = new FunctionItem();
    fitem.setName(e.attributeValue("name") );
    fitem.setExcutePoint(e.attributeValue("excutepoint"));
    fitem.setClassName(e.attributeValue("classname"));
    fitem.setDescription(e.attributeValue("description"));
    fitem.setURL(e.attributeValue("url"));
    String v = e.attributeValue("allow");
    boolean bv = false;
    if(v==null){
    bv=false;
    }
    else{
    if(v.toLowerCase().equals("true") || Integer.valueOf(v).intValue()==1){
    bv=true;
    }
    }
    fitem.allow(bv);
    v=e.attributeValue("priority");
    int iv = 0;
    if(v==null){
    iv=0;
    }
    else{
    iv = Integer.valueOf(v).intValue();
    }
    fitem.setPriority(iv);

    List plist=  e.selectNodes("paramsType/param");

    for(Object op:plist){
    Element ep =(Element)op;

    fitem.addParamType(ep.attributeValue("type"));
    } Element eer = (Element) e.selectSingleNode("resultType");
    fitem.setResultType(eer.attributeValue("type"));


    addFunctionItem(fitem);
    }
    try {
    in.close();
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

    Collections.sort(this.functions);

    Iterator it = this.iteratorFunctions();
    while(it.hasNext()){
    FunctionItem item = (FunctionItem)it.next();
    dynamicLoad.addURL(item.getURL());
    dynamicLoad.addClass(item.getURL(), item.getClassName());
    }

    dynamicLoad.reload();

    }


      

  5.   

    public void run(){
    this.timer = new Timer(true);
    this.timer.schedule(new CheckDynamic(this), 0,this.checkPeriod);

    } public FunctionItem getFunctionItem(String name){
    if(name==null || name.trim().length()<=0) return null;

    Iterator it = this.iteratorFunctions();
    while(it.hasNext()){
    FunctionItem item = (FunctionItem)it.next();
    if(item.getName().toLowerCase().equals(name.toLowerCase())){
    return item;
    }
    }
    return null;
    } public FunctionItem getFunctionItem(String name,Object[] params){
    if(name==null || name.trim().length()<=0) return null;
    if(params.length<=0) return getFunctionItem(name);

    Iterator it = this.iteratorFunctions();
    while(it.hasNext()){
    FunctionItem item = (FunctionItem)it.next();
    if(item.getName().toLowerCase().equals(name.toLowerCase())){
    List lstParam = item.getParamType();
    boolean bMatched = true;
    //System.out.println(item.getName()+":"+params.length+" : "+lstParam.size());
    if(params.length== lstParam.size()){
    for(int i = 0 ; i < params.length; i++){
    Class c = params[i].getClass();

    boolean bM = false;
    if(!lstParam.contains(c.getName())){
    Class nc = c.getSuperclass();
    while(nc!=Object.class){
    if(lstParam.contains(nc.getName())){
    bM=true;
    break;
    }
    nc=nc.getSuperclass();
    }

    if(bM){
    bMatched=true;
    break;
    }
    }
    else{
    bMatched = true;
    break;
    }
    }
    //System.out.println("name isMatched:"+bMatched);
    if (bMatched){
    return item;
    }
    }
    }
    }
    return null;

    }

    public FunctionItem getFunctionItem(String name,String[] paramTypes){

    if(name==null || name.trim().length()<=0) return null;
    if(paramTypes.length<=0) return getFunctionItem(name);

    Iterator it = this.iteratorFunctions();
    while(it.hasNext()){
    FunctionItem item = (FunctionItem)it.next();
    if(item.getName().toLowerCase().equals(name.toLowerCase())){
    List lstParam = item.getParamType();
    boolean bMatched = true;
    if(paramTypes.length== lstParam.size()){
    for(int i = 0 ; i < paramTypes.length; i++){
    String clsn = paramTypes[i];
    if(!lstParam.contains(clsn)){
    bMatched = false;
    break;
    }
    }
    if (bMatched){
    return item;
    }
    }
    }
    }
    return null;
    }


    @SuppressWarnings("finally")
    public Object executeFunction(String name,Object[] params,Object classInstance){
    FunctionItem function = this.getFunctionItem(name, params);
    if(function==null) return null;

    MethodUtil mu = new MethodUtil();

    Iterator it = function.iteratorParams();
    Class[] ppp =new Class[function.sizeParams()];
    try {
    int index=0;
    while(it.hasNext()){

    String clsname = (String)it.next();
    ppp[index++] = function.getClassLoader().loadClass(clsname); }
    } catch (ClassNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    return null;
    }

    Method method = mu.getMethod(function.getClass1(), function.getExcutePoint(), ppp );

    if (method==null) return null;

    Object result=null;
    try {
    method.setAccessible(true);

    Object instance = classInstance;
    if(instance==null){
    instance = function.getClassLoader().loadClass(function.getClassName()).newInstance();

    }
    result = method.invoke(instance, params);
     
    } catch (IllegalArgumentException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (InvocationTargetException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (InstantiationException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    finally{
    return result;
    } }
    }
      

  6.   

    对于通过不同 ClassLoader 加载进来的 Class,即使它们的 full-qualified name 相同,JVM 仍然知道它们是两个不同的 Class,不能强制转换。
      

  7.   

    晕哦。能不能加个\[code=Java\]\[/code\]啊,代码太难看了。
    另外,你的FunctionManager代码里也没有fm.executeFunction()方法啊。
      

  8.   

    package dynamic;import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.PrintStream;
    import java.lang.reflect.Field;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.net.URLClassLoader;
    import java.util.ArrayList;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.Vector;import sun.misc.Launcher;/**
     * @author wq7x
     * Title: 使用事件的类
     * Description: 该类实现了监听器的添加和监听器方法的执行,并且实现了由于属性的改变而执行事件
     * Description: 在添加、删除、执行监听器的时候都要注意同步问题
     */
    public class DynamicClassLoad {
    private static List<String> paths;

    private static Map<String,Set> classes;

    private static Field packages;

    private static URLClassLoader loader ;

    private DynamicClassLoadHandler reloadHandler ;

    private ClassLoader parentLoader;

    private boolean relationParentLoader=true;

    private Map attributes = new HashMap();

    private Vector repository = new Vector();    private DynamicClassLoadEventListener listener;
    /**
     * 
     */
    public DynamicClassLoad() {
    // TODO Auto-generated constructor stub
    paths = new ArrayList<String>();
    classes = new HashMap<String,Set>();
    loader = (URLClassLoader) ClassLoader.getSystemClassLoader();

    parentLoader = this.getLoader().getParent();

    }
    public DynamicClassLoad(DynamicClassLoadHandler handler){
    paths = new ArrayList<String>();
    classes = new HashMap<String,Set>();
    loader = (URLClassLoader) ClassLoader.getSystemClassLoader();

    parentLoader = this.getLoader().getParent();

    reloadHandler = handler;
    } public void setLoader(ClassLoader clsl){
    this.loader = (URLClassLoader)clsl;
    if(parentLoader==null) parentLoader = this.getLoader().getParent();
    }

    public void setParentLoader(ClassLoader parent){
    parentLoader = parent;
    }
    public void setRelationParentLoader(boolean value){
    this.relationParentLoader = value;
    }

    /**
     * 注册监听器,如果这里没有使用Vector而是使用ArrayList那么要注意同步问题
     * @param dl
     */
        public void addListener(DynamicClassLoadEventListener listener) {
            repository.addElement(listener);//这步要注意同步问题
        }
        
        /**
         * 如果这里没有使用Vector而是使用ArrayList那么要注意同步问题
         * @param event
         */
        public void notifyEvent(DynamicClassLoadEvent event) {
            Enumeration enu = repository.elements();//这步要注意同步问题
            while (enu.hasMoreElements()) {
                listener = (DynamicClassLoadEventListener) enu.nextElement();
                listener.doEvent(event);
            }
        }
        
        /**
         * 删除监听器,如果这里没有使用Vector而是使用ArrayList那么要注意同步问题
         * @param listener
         */
        public void removeDemoListener(DynamicClassLoadEventListener listener) {
            repository.remove(listener);//这步要注意同步问题
        }
        
        
        
        public static ClassLoader getLoader(){
        
    return loader;
    }

    public static List<String> getPaths(){
    return paths;
    }

    /**
     * Map<文件,类名集合Set>
     * @return
     */
    public static Map<String,Set> getClasses(){
    return classes;
    }
    public Set classesByKey(String key){
    if(classes.containsKey(key)){
    return (Set)classes.get(key);
    }
    return null;
    }
    public DynamicClassLoadHandler getReloadHandler(){
    return reloadHandler;
    }
    public void setPaths(List<String> list){
    paths = list;
    }

    public void setDynamicClassLoadHandler(DynamicClassLoadHandler handler){
    this.reloadHandler = handler;
    }

    public void addURL(String value){
    if(!paths.contains(value)){
    paths.add(value);
    }
    }

    public void setClasses(Map<String,Set> map){
    classes = map;
    }
    public void addClass(String keyPathFile,String valueClass){
    Set set;
    if(classes.containsKey(keyPathFile)){
    set = (Set)classes.get(keyPathFile);
    }
    else{
    set = new HashSet();
    }
    if(!set.contains(valueClass)){
    set.add(valueClass);
    }
    classes.put(keyPathFile, set);
    }
    public void attributeValue(String key,Object value){
    this.attributes.put(key,value);
    }
    public Object attribute(String key){
    return this.attribute(key);
    }
    public URL[] getBootstrapURLs() {
        return Launcher.getBootstrapClassPath().getURLs();
        }    public URL[] getSystemURLs() {
            return ((URLClassLoader)ClassLoader.getSystemClassLoader()).getURLs();
        }    public URL[] getExtURLs() {
            return ((URLClassLoader)ClassLoader.getSystemClassLoader().getParent()).getURLs();
        }
        
        private void list(PrintStream ps, URL[] classPath) {
            for (int i = 0; i < classPath.length; i++) {
                ps.println(classPath[i]);
            }
        }
        
        public void listBootstrapClassPath() {
            listBootstrapClassPath(System.out);
        }    public void listBootstrapClassPath(PrintStream ps) {
            ps.println("BootstrapClassPath:");
            list(ps, getBootstrapClassPath());
        }    public void listSystemClassPath() {
            listSystemClassPath(System.out);
        }    public void listSystemClassPath(PrintStream ps) {
            ps.println("SystemClassPath:");
            list(ps, getSystemClassPath());
        }    public void listExtClassPath() {
            listExtClassPath(System.out);
        }    public void listExtClassPath(PrintStream ps) {
            ps.println("ExtClassPath:");
            list(ps, getExtClassPath());
        }
        
        public URL[] getBootstrapClassPath() {
            return getBootstrapURLs();
        }    public URL[] getSystemClassPath() {
            return getSystemURLs();
        }    public URL[] getExtClassPath() {
            return getExtURLs();
        }    public void reload(){
         Iterator it = paths.iterator();
         URL url;
         File file ;
         List<String> filenames= new ArrayList<String>();
        
         while(it.hasNext()){
         String path = (String)it.next();
         InputStream in;
         boolean bfile=true;
         try {
         System.out.println(path);
    url = new URL(path);
    in = url.openStream();

    } catch (MalformedURLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    bfile=false;
    } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    bfile=false;
    }
        
    if(bfile)
    filenames.add(path);
         }
        
         it = filenames.iterator();
         String pathfile;
         Set clss;
        
         while(it.hasNext()){
         pathfile = (String)it.next();
        
         if(reloadHandler.beforeReload(pathfile)){
        
         try {
    url = new URL(pathfile);
    if(relationParentLoader)
    loader = new URLClassLoader(new URL[]{url},parentLoader);
    else
    loader = new URLClassLoader(new URL[]{url});

    clss=classesByKey(pathfile);

    if(clss!=null){

    for(Iterator iii = clss.iterator(); iii.hasNext();){
    String clsname = (String)iii.next();
    Class nCls = loader.loadClass(clsname);
    DynamicClassLoadEvent event = new DynamicClassLoadEvent(loader,pathfile,nCls);
    event.attributeValue("className", clsname);
    notifyEvent(event);
    }
    }

    reloadHandler.afterReload(pathfile);
    //激活重新装入后的事件




    } catch (MalformedURLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (ClassNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
         }
         }
        }}
      

  9.   

    对于通过不同 ClassLoader 加载进来的 Class,即使它们的 full-qualified name 相同,JVM 仍然知道它们是两个不同的 Class,不能强制转换。
    ----
    7楼已经说了要点了。我也是怀疑你的fm代码里有这个问题。
      

  10.   

    根据上面两位的提示,看了下资料,把要装入的库文件加入到系统ClassLoader.getSystemClassLoader()中,用的是它的addURL方法,问题就解决了。