我试图在运行时在 eclipse 中编译和运行一个 java 类,它使用一个外部 jar 示例:在这种情况下是 JSON 库。
我已经成功编译了 java 代码,但是当我尝试调用该方法时,它给了我以下错误java.lang.reflect.InvocationTargetException
当我将所需的 jar 添加到 eclipse 的构建路径时,它工作正常。我不想将 jar 添加到 eclipse 的 buildPath,因为它需要从外部路径加载 jar 以及构建eclipse中提供的路径。
在运行时在 JAVACompiler 中调用包含外部 jar 的类时,有什么方法可以添加外部 jar 路径?
请在这个问题上帮助我。
这是要在运行时编译和运行的具有外部 jar 的类。
import org.json.JSONArray;
import org.json.JSONObject;
public class JSONPRINTERCLASS{
public void printJson() {
System.out.println("In the printJson method of JSONPRINTERCLASS class");
String json = "[{\"Name\":\"Prakhar Agrawal\",\"Email\":\"155@abc.com\"},{\"Name\":\"Rahul Dhakad\",\"Email\":\"RD@qwerty.com\"}]";
JSONArray array = new JSONArray(json);
for(Object obj : array) {
JSONObject jsonObj = (JSONObject)obj;
System.out.println("jsonObj = "+jsonObj);
System.out.println("============================================");
System.out.println("Name = "+jsonObj.get("Name"));
System.out.println("Email = "+jsonObj.get("Email"));
}
}
public static void main(String as[]) {
System.out.println("In the main method of JSONPRINTERCLASS class");
new JSONPRINTERCLASS().printJson();
}
}
这是我正在运行以编译 JSONPRINTERCLASS 的类
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Writer;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class StackInLineCompiler {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder(64);
StringBuilder stringbuff = new StringBuilder();
try {
InputStream is = new FileInputStream(
"/home/ist/Oxygen_workspace/NewProject/testcompile/JSONPRINTERCLASS.java");
BufferedReader buf = new BufferedReader(new InputStreamReader(is));
String line = buf.readLine();
while (line != null) {
stringbuff.append(line).append("\n");
line = buf.readLine();
}
} catch (Exception e) {
System.out.println();
e.printStackTrace();
}
String fileAsString = stringbuff.toString();
System.out.println("Contents : " + fileAsString);
// Read more:
// http://javarevisited.blogspot.com/2015/09/how-to-read-file-into-string-in-java-7.html#ixzz58OfOY4Rr
File helloWorldJava = new File("/home/ist/Oxygen_workspace/NewProject/testcompile/JSONPRINTERCLASS.java");
if (helloWorldJava.getParentFile().exists() || helloWorldJava.getParentFile().mkdirs()) {
try {
Writer writer = null;
try {
writer = new FileWriter(helloWorldJava);
writer.write(sb.toString());
writer.flush();
} finally {
try {
writer.close();
} catch (Exception e) {
}
}
/**
* Compilation Requirements
*********************************************************************************************/
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
// This sets up the class path that the compiler will use.
// I've added the .jar file that contains the DoStuff interface within in it...
List<String> optionList = new ArrayList<String>();
optionList.add("-classpath");
optionList.add(System.getProperty("java.class.path")
+ ":/home/ist/Downloads/jar_To_compile/jar/json-20160810.jar");
System.out.println("optionList = " + optionList);
Iterable<? extends JavaFileObject> compilationUnit = fileManager
.getJavaFileObjectsFromFiles(Arrays.asList(helloWorldJava));
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, optionList, null,
compilationUnit);
/*********************************************************************************************
* Compilation Requirements
**/
if (task.call()) {
/**
* Load and execute
*************************************************************************************************/
System.out.println("Yipe");
try {
// Create a new custom class loader, pointing to the directory that contains the
// compiled
// classes, this should point to the top of the package structure!
URLClassLoader classLoader = new URLClassLoader(new URL[] { new File("./").toURI().toURL() });
// Load the class from the classloader by name....
Class<?> loadedClass = classLoader.loadClass("JSONPRINTERCLASS");
// Create a new instance...
Method declaredMethod = loadedClass.getDeclaredMethod("printJson");
// Santity check
System.out.println(
"Object Loaded Successfully...Now to call the method = " + declaredMethod.getName());
declaredMethod.invoke(loadedClass.newInstance(), null);
System.out.println("after invoking the method...........");
} catch (Exception e) {
System.out.println("In the exception while calling the method = " + e);
}
//
// }
/*************************************************************************************************
* Load and execute
**/
} else {
System.out.println("In the error");
for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
System.out.format("Error on line %d in %s%n", diagnostic.getLineNumber(),
diagnostic.getSource().toUri());
}
}
fileManager.close();
} catch (IOException exp) {
exp.printStackTrace();
}
}
}
}
最后是@AL4建议的更改后的代码
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Writer;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class StackInLineCompiler {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder(64);
StringBuilder stringbuff = new StringBuilder();
try {
InputStream is = new FileInputStream(
"/home/ist/Oxygen_workspace/NewProject/testcompile/JSONPRINTERCLASS.java");
BufferedReader buf = new BufferedReader(new InputStreamReader(is));
String line = buf.readLine();
while (line != null) {
stringbuff.append(line).append("\n");
line = buf.readLine();
}
} catch (Exception e) {
System.out.println();
e.printStackTrace();
}
String fileAsString = stringbuff.toString();
System.out.println("Contents : " + fileAsString);
// Read more:
// http://javarevisited.blogspot.com/2015/09/how-to-read-file-into-string-in-java-7.html#ixzz58OfOY4Rr
File helloWorldJava = new File("/home/ist/Oxygen_workspace/NewProject/testcompile/JSONPRINTERCLASS.java");
File parentFile = helloWorldJava.getParentFile();
final File jsonJarFile = new File("/home/ist/Downloads/jar_To_compile/jar/json-20160810.jar");
try {
/**
* Compilation Requirements
*********************************************************************************************/
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
// This sets up the class path that the compiler will use.
// I've added the .jar file that contains the DoStuff interface within in it...
List<String> optionList = new ArrayList<String>();
// optionList.add("classpath");
//
// optionList.add(System.getProperty("classpath")
// + File.pathSeparator + jsonJarFile.getAbsolutePath());
System.out.println("jar file path = "+jsonJarFile.getAbsolutePath());
optionList.add("-classpath");
optionList.add(System.getProperty("java.class.path")
+ File.pathSeparator + jsonJarFile.getAbsolutePath());
for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
System.out.println(diagnostic.getCode());
System.out.println(diagnostic.getKind());
System.out.println(diagnostic.getPosition());
System.out.println(diagnostic.getStartPosition());
System.out.println(diagnostic.getEndPosition());
System.out.println(diagnostic.getSource());
System.out.println(diagnostic.getMessage(null));
}
System.out.println("Now loading the jars at runtime");
URLClassLoader classLoader = new URLClassLoader(Stream
.of(parentFile, jsonJarFile)
.filter(Objects::nonNull)
.map(StackInLineCompiler::toUrl)
.toArray(URL[]::new));
///////////////////////////////////////////////////////////////////////////////////////
//
System.out.println ("Success!");
//
System.out.println("Jars loaded succesfully....");
System.out.println("optionList = " + optionList);
Iterable<? extends JavaFileObject> compilationUnit = fileManager
.getJavaFileObjectsFromFiles(Arrays.asList(helloWorldJava));
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, optionList, null,
compilationUnit);
/*********************************************************************************************
* Compilation Requirements
**/
// if (task.call()) {
if (task.call()) {
/**
* Load and execute
*************************************************************************************************/
System.out.println("Yipe");
try {
// Create a new custom class loader, pointing to the directory that contains the
// compiled
// classes, this should point to the top of the package structure!
// URLClassLoader classLoader = new URLClassLoader(new URL[] { new File("./").toURI().toURL() });
Class<?> loadedClass = Class.forName("JSONPRINTERCLASS", true, classLoader);
Method declaredMethod = loadedClass.getDeclaredMethod("printJson");
// Santity check
System.out.println(
"Object Loaded Successfully...Now to call the method = " + declaredMethod.getName());
declaredMethod.invoke(loadedClass.newInstance(), null);
System.out.println("after invoking the method...........");
} catch (Exception e) {
System.out.println("In the exception while calling the method = " + e);
}
//
// }
/*************************************************************************************************
* Load and execute
**/
} else {
System.out.println("In the error");
for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
System.out.format("Error on line %d in %s%n", diagnostic.getLineNumber(),
diagnostic.getSource().toUri());
}
}
fileManager.close();
} catch (IOException exp) {
exp.printStackTrace();
}
// }
}
// helper method
static URL toUrl(File f) {
try {
return f.toURI().toURL();
} catch (Exception e) {
throw new RuntimeException(String.valueOf(f), e);
}
}
// private static final Class<?>[] parameters = new Class[] { URL.class };
/**
* Adds a file to the classpath.
*
* @param s
* a String pointing to the file
* @throws IOException
*/
/*public static void addFile(String s) throws IOException {
File f = new File(s);
addFile(f);
}*/
/**
* Adds a file to the classpath
*
* @param f
* the file to be added
* @throws IOException
*/
/*public static void addFile(File f) throws IOException {
addURL(f.toURI().toURL());
}*/
/**
* Adds the content pointed by the URL to the classpath.
*
* @param u
* the URL pointing to the content to be added
* @throws IOException
*/
/*public static void addURL(URL u) throws IOException {
URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class<?> sysclass = URLClassLoader.class;
try {
Method[] methodarray = sysclass.getDeclaredMethods();
for (Method method : methodarray) {
System.out.println("Method name = " + method.getName());
method.setAccessible(true);
}
} catch (Throwable t) {
t.printStackTrace();
throw new IOException("Error, could not add URL to system classloader");
}
}*/
}
但我仍然得到
java.lang.Error:未解决的编译问题:JSONArray 无法解析为类型 JSONArray 无法解析为类型 JSONObject 无法解析为类型 JSONObject 无法解析为 JSONPRINTERCLASS.printJson(JSONPRINTERCLASS.java:20) 处的类型JSONPRINTERCLASS.(JSONPRINTERCLASS.java:7) 在 sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 在 sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:423) 在 java.lang.Class.newInstance(Class.java:442) 在 StackInLineCompiler.main(StackInLineCompiler.java:137)
请帮忙