This page contains the information about the preview binary distribution of OCaml-Java 2.0.
This binary distribution is made available for testing purpose, and provides scripts for easy use under MacOS X, Linux, and Windows.
Once polished, OCaml-Java will be relased under the QPL/LGPL licences.
The objective of the OCaml-Java project is to allow seamless integration of OCaml and Java. Its ocamljava compiler can generate Java archives to be run on any Java virtual machine. This possibility will allow to leverage Java libraries from purely OCaml code. Moreover, the OCaml-Java runtime does not need to rely on a global runtime lock, meaning that concurrent programming is now possible in a single OCaml process.
OCaml-Java exhibits good compatibility with respect to the original OCaml implementation since its very first version. However, versions 1.x should be regarded as mere prototypes, due to terrible performance and huge memory consumption. The upcoming 2.0 version fixes a number of issues, and greatly improves both CPU usage and memory footprint. As it is currently under heavy development and involves a rather complex build system, only binary snapshots are available for the time being.
The installation of OCaml-Java is straightforward:
bin directory (unpacked from the archive) to the system PATH.
Once these three steps have been completed, it is possible to check that OCaml-Java is up and running by executing ocamljava -v from the command-line. It should result in the following output:
The OCaml Java-bytecode compiler, version 4.00.1 Standard library directory: /ocamljava-2.0-early-access5
The new ocamljava compiler is akin to the ocamlc/ocamlopt compilers from the original OCaml distribution. However, rather than producing OCaml bytecode, or native code, it will compile source files to Java classes. The following table presents the correspondence between the files manipulated by the various OCaml compilers.
| ocamlc | ocamlopt | ocamljava | |
|---|---|---|---|
| interface source | .mli | .mli | .mli |
| implementation source | .ml | .ml | .ml |
| compiled interface | .cmi | .cmi | .cmi |
| compiled implementation | .cmo | .cmx | .cmj |
| object binary | - | .o | .jo |
| compiled library | .cma | .cmxa | .cmja |
| library binary | - | .a, .so, ... | .ja |
| plugin | - | .cmxs | .cmjs |
Compiling source through the ocamljava compiler is not different from compiling through one of the original compilers. Compiling then linking a source.ml can be done in either two steps:
ocamljava -c source.ml ocamljava -o myprog.jar source.cmjor just one step:
ocamljava -o myprog.jar source.mlThen, the created archive can be executed by any Java virtual machine:
java -jar myprog.jar
The current version of OCaml-Java ships with the command-line tools listed in the following table.
| command name | description |
|---|---|
| camlp4* | the various camlp4 preprocessors |
| ocaml | the toplevel, as a terminal application |
| ocamlbuild | the compilation manager |
| ocamlc | the OCaml bytecode compiler |
| ocamldebug | the debugger (for ocamlc-compiled programs) |
| ocamldep | the dependency analyzer |
| ocamldoc | the documentation generator |
| ocamljar | the post-compilation optimizer |
| ocamljava | the Java bytecode compiler |
| ocamllex | the lexer generator |
| ocamlrun | the interpreter for ocamlc-compiled programs |
| ocamltop | the toplevel, as a windowed application |
In its current version, OCaml-Java is based on OCaml version 4.00.1, and requires a Java 1.7 virtual machine to run compiled programs. The whole OCaml language is supported, with some limitations:
ocamlc/ocamlopt (however, it should not be a major problem as evaluation order is not specified in the OCaml language);ocamljava may fail to compile some (very) large functions (Java set a hard limit on method length).
Regarding primitives/libraries, compatibility is high but not perfect. Indeed, some POSIX routines are not available from Java. The libraries shipped with the original OCaml implementation are available in OCaml-Java: str, num, dynlink, bigarray, systhreads, threads, and graph should behave roughly as their equivalents in the original distribution. The unix library is only partially supported, and support for labltk is experimental.
Since version 2.0-early-access5, the distribution features a post-compilation optimizer (namely ocamljar) that can be applied to a linked OCaml-Java program (that is, a jar file) in order to produce an optimized version of the program.
Indeed, the ocamljava compiler is quite conservative in order to compile and link programs in such a way that they can be used in very different settings. As an example, it is perfectly safe to have several ocamljava-compiled programs executing in the very same JVM, which can be useful when compiling to applets or servlets. However, this comes at a price, and the ocamljar tool allows to get rid of costly indirections when the user knows for example that there will be only one ocamljava-compiled program in the JVM.
The developer could specify optimization directives to the ocamljava compiler, but it would imply to recompile many files (including those from the standard library, and even from the runtime support). This explains why it has been decided to apply such optimization on linked programs.
The optimizer is invoked through a command line such as the following one:
ocamljava <options> input-file.jar output-file.jarwhere possible options are:
| command-line switch | default value | meaning |
|---|---|---|
-no-dynlink <bool> | true | whether to assume absence of dynamic linking |
-no-runtime-lock <bool> | true | whether to remove support for runtime lock |
-no-signals <bool> | true | whether to remove support for signals |
-one-context <bool> | true | whether to assume unique context (meaning that there should be only one OCaml-Java program executing in the JVM) |
-unsafe <bool> | false | whether to use unsafe containers (allowing to avoid array bound checks performed by the JVM for container classes representing OCaml values) |
java -Xbootclasspath/p:output-file.jar pack.ocamljavaMain (where the default pack may have been changed by using the -java-package command-line switch from ocamljava at link time).
Performance of ocamljava-generated code is regurlarly improved, but a reasonable rule of thumb for the current version is to consider that such code is on average 3 times slower than ocamlopt-generated code. On some numerical codes, ocamljava-compiled programs are on par with ocamlopt-compiled ones.
The current version of OCaml-Java ships with a draft version of the concurrent library which is a pack of several modules that are bare wrappers around Java classes. The doc directory contains the ocamldoc-generated documentation for these modules. An overview of the library is available here.
Since version 2.0-early-access5, scripting from a Java application is supported, by providing an OCaml script engine for the javax.script framework. In order to be able to use the script engine, it is sufficient to add the archive lib/ocamlrun-scripting.jar to the classpath. It is then possible to interpret OCaml phrases from a Java application as shown by the following code sample:
import javax.script.*;
import org.ocamljava.runtime.support.scripting.OCamlContext;
public final class SimpleInterpreted {
private static final String SCRIPT =
"external get_binding : string -> 'a = \"script_get_binding\";;\n" +
"let n = Int32.to_int (get_binding \"repetitions\");;\n" +
"let s : string = get_binding \"message\";;\n" +
"for i = 1 to n do print_endline s done;;\n";
public static void main(final String[] args) throws Throwable {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByName("OCaml");
final ScriptContext ctxt = new OCamlContext();
ctxt.getBindings(ScriptContext.ENGINE_SCOPE).put("repetitions", 3);
ctxt.getBindings(ScriptContext.ENGINE_SCOPE).put("message", "hello!!!");
engine.eval(SCRIPT, ctxt);
}
}
where the external get_binding function allows to access bindings registered on the Java side of the application. The mapping of Java types to OCaml types is given by the following table (notice that Java primitive types are necessarily promoted to their wrapper equivalents through the use of the binding API):
| Java type | OCaml type |
|---|---|
| java.lang.Boolean | bool |
| java.lang.Byte | int |
| java.lang.Character | int |
| java.lang.Double | float |
| java.lang.Float | float |
| java.lang.Integer | int32 |
| java.lang.Long | int64 |
| java.lang.Short | int |
| java.lang.String | string |
Besides interpretation, it is also possible to compile OCaml sources in order to benefit from better performance. To do so, the archive lib/ocamljava.jar has to be added to the classpath in addition to the archive lib/ocamlrun-scripting.jar. The following code shows how to compile and then run an OCaml snippet from a Java application.
import javax.script.*;
import org.ocamljava.runtime.support.scripting.OCamlContext;
public final class SimpleCompiled {
private static final String SCRIPT =
"external get_binding : string -> 'a = \"script_get_binding\"\n" +
"let () =\n" +
" let n = Int32.to_int (get_binding \"repetitions\") in\n" +
" let s : string = get_binding \"message\" in\n" +
" for i = 1 to n do print_endline s done\n";
public static void main(final String[] args) throws Throwable {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByName("OCaml");
final ScriptContext ctxt = new OCamlContext();
ctxt.getBindings(ScriptContext.ENGINE_SCOPE).put("repetitions", 3);
ctxt.getBindings(ScriptContext.ENGINE_SCOPE).put("message", "hello!!!");
final CompiledScript compiled = ((Compilable) engine).compile(SCRIPT);
compiled.eval(ctxt);
}
}
The following versions are available:
2.0-early-access5 46
2.0-early-access4 62
2.0-early-access3 66
2.0-early-access2 149
The following changes occurred:
| Version | Date | Changes |
|---|---|---|
| 2.0-early-access5 | 2013-04-24 |
|
| 2.0-early-access4 | 2013-03-28 | |
| 2.0-early-access3 | 2013-03-07 |
The developer of OCaml-Java can be reached either by mail (forum AT x9c.fr) or through the project bugtracker (available at http://bugs.x9c.fr).