以下代码正常工作但在某些情况下Class.forName
方法访问文件时会抛出ClassNotFoundException
,因为文件未完全写入,我通过增加睡眠时间解决了这些问题。
但是我想要一种强制线程休眠的方式,直到文件完全写入而不是静态sleep(5000)
?
public void run(String className, String code) {
String pkgname = "pkg" + (int) (Math.random() * 10000);
String sb = "";
sb += "package " + pkgname + ";\n";
sb += code;
File javaFile = new File(serverPath + pkgname + "/" + className + ".java");
if (javaFile.getParentFile()
.exists() || javaFile.getParentFile().mkdirs()) {
try {
FileWriter writer = new FileWriter(javaFile);
writer.write(sb);
writer.flush();
writer.close();
try {
Thread.sleep(5000);// here is the problem
} catch (InterruptedException ex) {
Logger.getLogger(InlineCompiler.class.getName()).log(Level.SEVERE, null, ex);
}
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int compilationResult = compiler.run(null, null, null, javaFile.getPath());
try {
String[] params = new String[0];
Method method = Class.forName(pkgname + "." + className).getMethod("main", String[].class);
method.invoke(null, (Object) params);
} catch (NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException | IllegalAccessException ex) {
Logger.getLogger(InlineCompiler.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (IOException | ClassNotFoundException exp) {
Logger.getLogger(InlineCompiler.class.getName()).log(Level.SEVERE, null, exp);
}
}}
再次:我的问题不是代码的逻辑,也不是动态编译和执行文件的逻辑,但它只与休眠时间有关。
当我将睡眠减少到2000时的例外
Jun 27, 2015 3:06:28 AM compile.InlineCompiler run
SEVERE: null
java.lang.ClassNotFoundException: pkg5958.test
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:259)
at compile.InlineCompiler.run(InlineCompiler.java:49)
答案 0 :(得分:0)
java.lang.ClassNotFoundException: pkg5958.test
表示运行时试图引用的名为test
的包中的某个名为pkg5989
的类不在类路径上。这与Thread.sleep()
无关。
.class
文件的目录在类路径上不是。我无法重现你的问题,我想不到。 这是有效的,并且没有一次调用
Thread.sleep()
!
import javax.annotation.Nonnull;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
public class Q31083880
{
public static int compile(@Nonnull final File file)
{
final JavaCompiler c = ToolProvider.getSystemJavaCompiler();
return c.run(null, null, null, file.getAbsolutePath());
}
public static void invoke(@Nonnull final String name)
{
try
{
final URLClassLoader cl = (URLClassLoader) ClassLoader.getSystemClassLoader();
final Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
method.setAccessible(true);
final File f = new File(System.getProperty("user.home"));
method.invoke(cl, f.toURI().toURL());
final Method m;
try
{
m = Class.forName(name).getMethod("main", String[].class);
}
catch (ClassNotFoundException e)
{
throw new RuntimeException(e);
}
final String[] args = new String[0];
m.invoke(null, new Object[]{args});
}
catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException | MalformedURLException e)
{
throw new RuntimeException(e);
}
}
public static void main(final String[] args)
{
final File f = new File(System.getProperty("user.home"), "Test.java");
try
{
final FileWriter fw = new FileWriter(f);
try
{
final String source = "public class Test { public static void main(String[] args) { System.out.println(\"Testing\"); } }";
fw.write(source);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
finally
{
try { fw.close(); } catch (final IOException e) { System.err.println(e.getMessage()); }
}
System.out.println(compile(f));
invoke("Test");
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
}
这会编译为System.getProperty("user.home");
作为示例。
读者改变这种行为是一种练习,应该很容易。