Java 具有动态生成和编译的源代码的ClassNotFoundException

Java 具有动态生成和编译的源代码的ClassNotFoundException,java,file,Java,File,下面的代码工作正常,但在某些情况下,当Class.forName方法访问它抛出的文件ClassNotFoundException时,由于文件未完全写入,我通过增加睡眠时间来解决这些情况下的问题 但是我想要一种强制线程休眠直到文件完全写入的方法,而不是静态的sleep(5000) public void run(String className, String code) { String pkgname = "pkg" + (int) (Math.random() * 10000);

下面的代码工作正常,但在某些情况下,当
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)
写入文件不是问题:
java.lang.ClassNotFoundException:pkg5958.test
表示运行时试图引用的名为
pkg5989
的包中名为
test
的类不在类路径上。这与
Thread.sleep()
无关

生成
.class
文件的目录不在类路径上。 我无法重现你的问题,我认为我无法重现。 这是可行的,没有一个调用
Thread.sleep()

这将编译为
System.getProperty(“user.home”)作为示例


对读者来说,改变这种行为是一种练习,应该很容易。

如果调用writer.close()后尝试重新打开文件(使用新的文件句柄而不是javaFile),会发生什么情况?@Tabaqui什么也没有发生它会正确地打开它当你得到异常时,请发布完整的异常和堆栈跟踪?非常感谢。现在,我很难理解睡眠是如何起作用的。编译器有输出吗?您已将其配置为将输出发送到stdout和stderr。这与
线程无关。sleep()
我不知道您为什么要将其放在那里,或者您为什么认为它应该是代码的一部分。您运行过Jarrod的代码吗?您的回答引导我找到了问题的答案,谢谢:)
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);
        }
    }
}