我正在尝试在eclipse中运行时编译并运行一个java类,它使用外部jar示例:在这种情况下为JSON库。
我已经成功编译了java代码,但是当我尝试调用该方法时,它给了我以下错误 java.lang.reflect.InvocationTargetException
当我将所需的jar添加到eclipse的构建路径时,它工作正常。我不想将jar添加到eclipse的buildPath中,因为它需要从外部加载jar路径以及日食中提供的构建路径。
在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) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 在java.lang.Class.newInstance(Class.java:442) 在StackInLineCompiler.main(StackInLineCompiler.java:137)
请帮助解决此问题
答案 0 :(得分:0)
您的代码存在一些缺陷:
:
来设置不可移植的编译类路径(在Windows上不起作用)。diagnostics
对象以查看是否有错误。URLClassload
不正确,设置运行时类路径中唯一的当前工作目录,您需要的是编译源{parent(1)}文件的位置(parentFile)和位置jar文件(jar文件本身)如何修复
只需获取父文件并保存以供日后使用,您将需要它来设置运行时类路径
.class
摆脱此代码
用户File.pathSeparator获取系统特定的路径分隔符,对于unix,它是File helloWorldJava = new File("java_sources/JSONPRINTERCLASS.java");
File parentFile = helloWorldJava.getParentFile();
,对于windows,它是:
;
设置你的编译类路径:
// define as constant
private final static File jsonJarFile = new File("3rdparty/json-20180130.jar");
检查诊断对象是否存在编译问题
optionList.add(System.getProperty("java.class.path")
+ File.pathSeparator + jsonJarFile.getAbsolutePath());
正确设置运行时类路径
在JAVACompiler中调用运行时包含外部jar的类时,有没有办法添加外部jar路径?
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));
}
加载并初始化类
URLClassLoader classLoader = new URLClassLoader(Stream
.of(parentFile, jsonJarFile)
.filter(Objects::nonNull)
.map(StackInLineCompiler::toUrl)
.toArray(URL[]::new));
// helper method
public static URL toUrl(File f) {
try {
return f.toURI().toURL();
} catch (Exception e) {
throw new RuntimeException(String.valueOf(f), e);
}
}
应用这些步骤后,您应该能够运行应输出的方法Class<?> loadedClass = Class.forName("JSONPRINTERCLASS", true, classLoader);
:
printJson