1

私は Java の専門家ではありません。また、動的に生成されたコードをコンパイルして実行するという概念全体にまったく慣れていません。これは、他の言語、特に Javascript や PHP などのスクリプト言語では非常に単純です。

私はこのコードのスニペットに従っています: http://www.java2s.com/Code/Java/JDK-6/CompilingfromMemory.htm そして私はこのようなものを作りました:

private final String = "GeneratedClass_" + Long.toHexString(random.nextLong());
private Method compileCode(String code) {
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    if (compiler == null) return null;

    DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();

    JavaFileObject source = new JavaSource(className, code);
    Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(source);
    CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);

    if (!task.call()) return null;
    try {
        return Class.forName(className).getDeclaredMethods()[0];
    } catch (ClassNotFoundException e) {}
    return null;
}

private class JavaSource extends SimpleJavaFileObject {
    final String code;
    JavaSource(String name, String code) {
        super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension),Kind.SOURCE);
        this.code = code;
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) {return code;}
}

文字列コードが次のようなものだと想像してみてください

"public class GeneratedClass_65ce701239c32ce0 {
    public String hello() {
        return "Hello, world!";
    }
}"

ClassNotFoundException をスローする Class.forName まではうまく機能します。スニペットから何か重要なものを切り取ったように見えないので、私は困惑しています: それで、クラスはコンパイルされましたが、どこに行ったのですか?

私は別のクラスローダーの使用について何かを読みましたが、私が言ったように、私はこれらすべてのものにかなり慣れていないので、どこに向かうべきか、どのように使用するべきか、そしてClassLoaderの独自の拡張をどのように定義すればよいかわかりません. 私が知っている唯一のことは、私にはすべてが非常に複雑に見えるということです...

Windows 7 および JDK 1.7 での Eclipse Indigo の使用。

4

1 に答える 1

2

One important thing you cut was all the error output and diagnostic information. You'd never know if something went wrong. However, everything looks correct. Your problem is most likely just that you didn't send any options to the compiler, so it'll write the class file out to wherever it feels like (current working directory is the default, I believe), and that's probably not on your classpath, especially in an IDE. Try running it from the command line to prove to yourself it works. This should work:

mkdir tmp
javac -d tmp <path your main class .java file>
java -cp .;tmp <your main class name>

If you're not familiar with the command-line tools, the argument to javac has to be a file system path to the .java file, and the argument to java needs to be the .-separated, fully-qualifed class name, like com.foo.Main. Doing that should:

  1. Compile your class to the tmp directory.
  2. Write your dynamically-generated class to the current directory.
  3. Successfully load the newly compiled class from the current directory because it's on the classpath.
于 2011-10-16T00:36:38.790 に答える