Previously, I described an unsuccessful first attempt to compile the popular cheminformatics C/C++ library Open Babel to pure Java bytecode using NestedVM. This article follows that topic one step further, and shows how to obtain a runnable Java classfile. Although major functionality is missing, the principle of compiling arbitrary C/C++ code to both Java source code and Java bytecode is illustrated.
This articles assumes that you've installed NestedVM and downloaded Open Babel on your system. You'll then need to set up your environment (from the nestedvm installation directory):
Run the Configure Script
The configure script we used last time didn't attempt to statically compile the binary utilities in the tools directory. This time, we'll add flags to allow this:
./configure --disable-dynamic-modules --enable-static=yes --enable-shared=no --enable-inchi --host=mips-unknown-elf make
Note: leaving out the static compile directives does not produce a fully-functioning classfile either.
Next, we'll attempt to directly create the
babel binary in Java classfile format, as we did last time:
cd tools java org.ibex.nestedvm.Compiler -outfile Babel.class Babel babel Exception in thread "main" java.lang.IllegalStateException: unresolved phantom target at org.ibex.classgen.MethodGen.resolveTarget(MethodGen.java:555) at org.ibex.classgen.MethodGen._generateCode(MethodGen.java:664) at org.ibex.classgen.MethodGen.generateCode(MethodGen.java:618) at org.ibex.classgen.MethodGen.dump(MethodGen.java:888) at org.ibex.classgen.ClassFile._dump(ClassFile.java:193) at org.ibex.classgen.ClassFile.dump(ClassFile.java:160) at org.ibex.nestedvm.ClassFileCompiler.__go(ClassFileCompiler.java:380) at org.ibex.nestedvm.ClassFileCompiler._go(ClassFileCompiler.java:72) at org.ibex.nestedvm.Compiler.go(Compiler.java:259) at org.ibex.nestedvm.Compiler.main(Compiler.java:183)
We're getting the same error as before. Although, an announcement of a bugfix was posted to the NestedVM list, in my hands the new version of NestedVM caused the same error.
As a workaround, we can compile to Java sourcecode first:
java org.ibex.nestedvm.Compiler -outformat java -outfile Babel.java Babel babel
We now have a Java source file encoding the babel program. Does it compile?
javac Babel.java The system is out of resources. Consult the following stack trace for details. java.lang.OutOfMemoryError: Java heap space at com.sun.tools.javac.util.Position$LineMapImpl.build(Position.java:139) at com.sun.tools.javac.util.Position.makeLineMap(Position.java:63) at com.sun.tools.javac.parser.Scanner.getLineMap(Scanner.java:1105) at com.sun.tools.javac.main.JavaCompiler.parse(JavaCompiler.java:512) at com.sun.tools.javac.main.JavaCompiler.parse(JavaCompiler.java:550) at com.sun.tools.javac.main.JavaCompiler.parseFiles(JavaCompiler.java:801) at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:727) at com.sun.tools.javac.main.Main.compile(Main.java:353) at com.sun.tools.javac.main.Main.compile(Main.java:279) at com.sun.tools.javac.main.Main.compile(Main.java:270) at com.sun.tools.javac.Main.compile(Main.java:69) at com.sun.tools.javac.Main.main(Main.java:54)
Not exactly. But this is a massive source file, so we'll need to increase the Java compiler's memory allowance:
javac Babel.java -J-Xms256m -J-Xmx256m Note: Babel.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details.
This seems to have worked. Can we run the classfile?
java Babel -H Open Babel converts chemical structures from one file format to another Usage: Babel <input spe> <output spec> [Options] Each spec can be a file whose extension decides the format. Optionally the format can be specified by preceding the file by -i<format-type> e.g. -icml, for input and -o<format-type> for output --truncated--
Success! But before we get too excited, let's make sure Open Babel's file formats are recognized by testing for "SMILES":
java Babel -Hsmi Format type: smi was not recognized
As you can see, we have successfully converted the
babel program to an executable classfile, but this classfile is missing most of the features of the native binary.
This may seem hopeless, but consider that natively compiling Open Babel using the above
configure flags also produces a binary that doesn't know about SMILES or any other format.
So, it's very likely that if we can produce a native, statically compiled, self contained
babel executable, then we will have solved the problem of running Open Babel entirely on a JVM.
This doesn't seem like a difficult problem, but apparently it is.