我正在尝试使用Java开发一个脚本,该脚本查找指定目录中的所有.jar
文件,然后将它们发送到classpath
,并在某些条件下调用其main()
方法。这是我的Java信息:
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.jar
添加到classpath
并调用其主要方法:
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 :(得分: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(String,boolean,ClassLoader)显式传递类加载器:
mainClass = Class.forName(mainClassName, true, urlClassLoader);
答案 1 :(得分: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();
}
}
}