我想在程序找不到引用的类的位置时让用户手动指定类所在jar包(如jdbc驱动等)的具体位置,只加载一个jar包倒是可以,可我要同时加载多个jar,怎么弄都不对——我用sqlServer的jdbc包测试的,在实例化类的时候没错,可一到连接数据库时就出错了,但我按正常方式加载jar包(用IDE预设好)时程序又能正确运行!程序片段如下大侠们帮看一下:
//这里是重新写的ClassLoader的子类,加载多个jar不行
public class LazyClassLoader extends URLClassLoader {
  
  /**
    * 或者是构造函写得不对??那该怎么写呢?
    *
    * */
   public LazyClassLoader() {
      super(new URL[0], ClassLoader.getSystemClassLoader());
   }
   
   public void selectPath(String[] paths) {
     for(int i=0;i<paths.length;i++){
     if (paths[i] == null || paths[i].length() <= 0) {
        return;
     }     String separator = System.getProperty("path.separator");
     String[] pathToAdds = paths[i].split(separator);
     for (int j = 0; j < pathToAdds.length; j++) {
        if (pathToAdds[j] != null && pathToAdds[j].length() > 0) {
           try {
               File pathToAdd = new File(pathToAdds[j]).getCanonicalFile();
               System.out.println(pathToAdd.toURL());
               addURL(pathToAdd.toURL());
            } catch (IOException e) {
               e.printStackTrace();
             }
          }
       }
   }
 }
}
//直接用CloassLoader类也不行
  /**
   * @@@@@jdbc驱动加载及异常处理
   * */
  private Driver driverLoad(String driverStr){
    Driver driver = null;
    try{
      driver = (Driver)Class.forName(driverStr).newInstance();
  }catch(Exception ex){
    //如果加载出现异常,即找不到相关的驱动程序所在包,弹出窗口供用户选择具体包路径
    System.out.println("加载驱动出错,下面由用户手动加载:"+ex.fillInStackTrace());
   try{
     //这是用户自选得到的文件列表
     File[] fileList = getJarFileList();
     URL[] url = new URL[fileList.length] ;
     for(int i=0;i<fileList.length;i++){
        File myfile=fileList[i];
        //由于取得的字符串是“c:\adf\x.jar”的形式,所以进行转换以便符合URL规则
        String tFile = "file:"+myfile.getPath().replace('\\','/');
        URL u = new URL(tFile);
        url[i]=u;
     }
      URLClassLoader  classLoader = new URLClassLoader(url, Thread.currentThread().getContextClassLoader());
      driver = (Driver)Class.forName(driverStr,true,classLoader).newInstance();
      System.out.println(url);     }catch(Exception ioe){
        System.err.print("再次加载jdbc驱动时出错:");
        ioe.printStackTrace();
        //以后在此加一个弹出窗口,显示错误信息
    }  }
    return driver;
 }
//////////////////////////////////以下是出现的异常(两个片段都这样)
java.lang.NullPointerException
at com.lazy.face.db.DBConnection.setStatement(DBConnection.java:44)
at com.lazy.face.db.DBOperation.showTable(DBOperation.java:20)
at com.lazy.face.LazyFrame.refresh_mouseClicked(LazyFrame.java:331)
at com.lazy.face.LazyFrame_refresh_mouseAdapter.mouseClicked(LazyFrame.java:408)
at java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:208)
at java.awt.Component.processMouseEvent(Component.java:5137)
at java.awt.Component.processEvent(Component.java:4931)
at java.awt.Container.processEvent(Container.java:1566)
at java.awt.Component.dispatchEventImpl(Component.java:3639)
at java.awt.Container.dispatchEventImpl(Container.java:1623)
at java.awt.Component.dispatchEvent(Component.java:3480)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:3450)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3174)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3095)
at java.awt.Container.dispatchEventImpl(Container.java:1609)
at java.awt.Window.dispatchEventImpl(Window.java:1590)
at java.awt.Component.dispatchEvent(Component.java:3480)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:450)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:197)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:144)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:136)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:99)
连接数据库出错java.sql.SQLException: No suitable driver
////////////////////////////////已经正确加载jar包了,可是还jdbc的位置不对??所以很愈闷!高手路过一定要帮帮忙啊!谁帮忙解决了一定n分(n>=90)谢!!

解决方案 »

  1.   

    但据你程序中报出来的错误语句,不是因为找不到class所造成的。DBConnection.java:44 这行代码是什么?
      

  2.   

    已经实例化要查找的类了,但是我用DriverManage找不到任何已经注册的驱动。而上面的程序中我明明是用"driver = (Driver)Class.forName(driverStr,true,classLoader).newInstance();"注册了驱动类(实例化)了啊,不会还差那一步吧!!??
      

  3.   

    的以DBConnection.java:44 这是连接无法找到注册的驱动所致!!
      

  4.   

    是不是因为你使用的 ClassLoader 实例没有保持住,造成由其加载的 class 也就都释放了?
      

  5.   

    不好意思,上面的说法好像不对  :(楼主说“一个 jar 包可以,多个 jar 包不行”,这好像有点说不通。你是怎么得出这个结论的?sqlServer的jdbc包是多个 jar 吗?如果是的话,你不妨自己把它们打到一个 jar 里再试试看。另外,我总觉得 ClassLoader.getSystemClassLoader() 和 Thread.currentThread().getContextClassLoader() 可疑,你不妨改成 DBConnection.class.getClassLoader() 试试。
      

  6.   

    File file = new File(jar文件全路径);
    URL url = file.toURL();
    URLClassLoader loader = new URLClassLoader(new URL[] { url });
    Class tidyClazz = loader.loadClass(所需class的含包名的全名);用这种方式加载jar包试试吧。
      

  7.   

    谢谢你们,今晚我试了你们以上的方法了,也都不对。在此特别感谢一下 terry_yip 半夜了还为这个问题发信息给我!
        
    -------------------------
    另外,我总觉得 ClassLoader.getSystemClassLoader() 和 Thread.currentThread().getContextClassLoader() 可疑,你不妨改成 DBConnection.class.getClassLoader() 试试。
    ================================
    改了,依然不对。Thread.currentThread().getContextClassLoader() 主要是为了在不同环境下,比如从纯界面的应用移值到web等环境时可用(有相关文档是这么说的)。但你这提法倒是让我想到,会不会是jdbc驱动包(可一个包又对...)的加载一定要指定哪一个父类加载器。或用改用别的构造函数?!
    -----------------------------------
    maquan('ma:kju) 
    是不是因为你使用的 ClassLoader 实例没有保持住,造成由其加载的 class 也就都释放了?
    ==========================================
    这也有可能,但要怎么样保持住它呢,让它自已调用自己??但是我用别的方法(比如设ide或直接放到相应位置)直接加载了这些包,用同样的方法实例化以后,接下来的应用却一点问题也没有(都能找到包,正确加载并正确实例化,区别就是手动加载并实例化以后,用DriverManager找不到任何已经注册的驱动)!!真晕!
      

  8.   

    有下面两个想法,供楼主参考:1. 楼主一开始说的一个 jar 包两个 jar 包的问题,我总觉得是不应该存在的,不知道楼主有没有试验过把 SQLServer 的多个 jar 包(?)自己重新打到一个 jar 包里?2. 看来看去,总觉得问题出在 ClassLoader 上。如果自己做一个 ClassLoader 总是不行的话,不妨试试把 ClassLoader.getSystemClassLoader() 或者 Thread.currentThread().getContextClassLoader() 或者 DBConnection.class.getClassLoader() 得到的对象强制转换成 URLClassLoader,然后通过 addURL() 把你需要的 jar 包加进去。
      

  9.   

    “ClassLoader 实例没有保持住”应该是多虑了,因为通过这个 ClassLoader 加载的对象(driver)还保持着,那么这个 ClassLoader 对象一定也被保持着。不好意思,是我误导了  ;P
      

  10.   

    刚才突然发现,楼主下面的几行程序也许有问题:
        File myfile=fileList[i];
        //由于取得的字符串是“c:\adf\x.jar”的形式,所以进行转换以便符合URL规则
        String tFile = "file:"+myfile.getPath().replace('\\','/');
        URL u = new URL(tFile);你这样得到的 tFile 可能并不一定是一个合法的 URL,应该改成下面的方法:
        File myfile=fileList[i];
        URL u = myfile.toURL();
      

  11.   

    for(int i=0;i<fileList.length;i++){
         url[i] = fileList[i].toURL() ;
     }
     
     用这个试一下
      

  12.   

    谢谢各位了,其实以上程序已经能正确实例化了,只是我用DriverManager取不到驱动而已,现在变通一下,在实例化驱动器类的时候直接取得Driver实例,然后用此Driver对象来取得connection实例就行了。下一步还得查一下资料看看DriverManager(或classforName)是怎样工作的,怎么由系统默认加载包然后实例化其中的类时它能找到相应的驱动(或者说实例化时JVM把此实例加到了驱动列表中),而手动加载包再实例化时JVM却没有把实例作为驱动加到jdbc驱动列表中。有谁知道这个原因不妨说一下,让咱们少走弯路,先谢过了!再等三天就结贴!!