Question

I'm not an expert in Java and I'm pretty new to the whole concept of compiling and running dynamic generated code, which is so simple in other languages, expecially script languages like Javascript and PHP.

I'm following this snippet of code: http://www.java2s.com/Code/Java/JDK-6/CompilingfromMemory.htm and I made something like this:

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;}
}

Just imagine that the string code is something like

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

It works well until that Class.forName which throws a ClassNotFoundException. I'm puzzled since it doesn't seem I cut something important from the snippet: so, the class was compiled but where has it gone?

I read something about using a different class loader, but since, like I said, I'm pretty new to all this stuff I don't know where to head and how to use it, and how should I define my own extension of ClassLoader. The only thing I know is that everything seems quite complicated to me...

Using Eclipse Indigo in Windows 7 and JDK 1.7.

Was it helpful?

Solution

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.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top