2012-12-24 68 views
3

我正在嘗試開發一個Java腳本,該腳本在指定的目錄中找到所有.jar文件,然後將它們移動到classpath,並在某些情況下調用它們的main()方法。這裏是我的Java信息:使用Java在類路徑中添加.jar文件

java version "1.6.0_24" 
OpenJDK Runtime Environment (IcedTea6 1.11.5) (6b24-1.11.5-0ubuntu1~12.04.1) 
OpenJDK Server VM (build 20.0-b12, mixed mode) 

這裏是當前工作目錄的ls

clojure.jar 
loader.class 
loader.java 

我這樣做,以增加clojure.jarclasspath並調用它的主要方法如下:

import java.io.File; 

import java.net.URL; 
import java.net.URLClassLoader; 
import java.net.MalformedURLException; 

import java.lang.reflect.Method; 

public final class loader { 

    public static void main (String[] args) { 
    try { 
     printClasspathString(); 
     System.out.println ("**********"); 
     URL[] classesRepo = { new File("clojure.jar").toURI().toURL(), 
          new File(System.getProperty("user.dir")).toURI().toURL()}; 
     ClassLoader currentThreadClassLoader = Thread.currentThread().getContextClassLoader(); 
     URLClassLoader urlClassLoader = new URLClassLoader(classesRepo, currentThreadClassLoader); 
     Thread.currentThread().setContextClassLoader(urlClassLoader); 
     printClasspathString(); 
    } catch (Exception ex) { 
     System.out.println(ex.getMessage()); 
    } 

    //Do I miss something here? 

    String mainClassName="clojure.main"; 

    Class<?> mainClass = null; 
    try { 
     mainClass = Class.forName(mainClassName); 
    } 
    catch (Exception ex) { 
     throw new IllegalArgumentException("class not found in your jar file " + mainClassName); 
    } 

    Method mainMethod = null; 
    try { 
     mainMethod = mainClass.getMethod("main", String[].class); 
    } 
    catch (Exception ex) { 
     throw new IllegalArgumentException("class to launch (" + mainClassName + ") does not have a public static void main(String[]) method"); 
    } 

    try { 
     mainMethod.invoke(null, (Object) args); 
    } catch (Exception ex) { 
     System.out.println(ex.getMessage()); 
    } 

    } 

    public static void printClasspathString() { 
    ClassLoader applicationClassLoader = Thread.currentThread().getContextClassLoader(); 
    if (applicationClassLoader == null) { 
     applicationClassLoader = ClassLoader.getSystemClassLoader(); 
    } 
    URL[] urls = ((URLClassLoader)applicationClassLoader).getURLs(); 
    for(int i=0; i < urls.length; i++) { 
     System.out.println (urls[i].getFile()); 
    } 
    } 

} 

不幸的是,裝載機沒有按預期工作:

$ java -cp . loader 
/home/proofit404/data/downloads/clojure-loader/ 
********** 
/home/proofit404/data/downloads/clojure-loader/clojure.jar 
/home/proofit404/data/downloads/clojure-loader/ 
Exception in thread "main" java.lang.IllegalArgumentException: class not found in your jar file clojure.main 
    at loader.main(loader.java:37) 

如果我使用-cp選擇,雖然,一切工作正常:

$ java -cp .:clojure.jar loader 
/home/proofit404/data/downloads/clojure-loader/ 
/home/proofit404/data/downloads/clojure-loader/clojure.jar 
********** 
/home/proofit404/data/downloads/clojure-loader/clojure.jar 
/home/proofit404/data/downloads/clojure-loader/ 
Clojure 1.4.0 
user=> (System/exit 0) 

所以 - 它是什麼,我需要在我的代碼修改,使其按預期工作?

+0

你需要一個自定義的類裝載器 - [鏈接](http://stackoverflow.com/questions/4095976/how -to-把定製類加載器使用的)。 –

回答

1

我認爲問題是,的Class.forName(String)方法不使用線程contextclassloader,但當前類的類加載器:

public static Class<?> forName(String className) 
        throws ClassNotFoundException 

Returns the Class object associated with the class or interface with the given string name. Invoking this method is equivalent to: 

    Class.forName(className, true, currentLoader) 

where currentLoader denotes the defining class loader of the current class. 

這意味着您的URLClassLoader不會被使用。會轉而通過使用Class.forName(字符串,布爾,類加載器)顯式傳遞的類加載器:

mainClass = Class.forName(mainClassName, true, urlClassLoader); 
+0

是的,它工作正常。非常感謝! – proofit404

0

試試這個代碼,並請參閱下面的註釋:

import java.net.URL; 
import java.io.IOException; 
import java.net.URLClassLoader; 
import java.net.MalformedURLException; 

public class JarLoader extends URLClassLoader { 
    public JarLoader(URL[] urls) { 
     super(urls); 
    } 

    public void addFile(String path) throws MalformedURLException { 
     String urlPath = "jar:file://" + path + "!/"; 
     addURL(new URL(urlPath)); 
    } 

    public static void main(String args[]) { 
     try { 
      System.out.println("First attempt..."); 
      Class.forName("org.gjt.mm.mysql.Driver"); 
      //specify your class name above 
     } catch (Exception ex) { 
      System.out.println("Failed."); 
     } 

     try { 
      URL urls[] = {}; 

      JarLoader cl = new JarLoader(urls); 
      cl 
        .addFile("/opt/mysql-connector-java-5.0.4/mysql-connector-java-5.0.4-bin.jar"); 
      // give your jar file above. 
      System.out.println("Second attempt..."); 
      cl.loadClass("org.gjt.mm.mysql.Driver"); 
      //specify your class name above 
      System.out.println("Success!"); 
     } catch (Exception ex) { 
      System.out.println("Failed."); 
      ex.printStackTrace(); 
     } 
    } 
}