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:

  1. download the archive available below on this page;
  2. unpack the archive;
  3. add the 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-access11

Warning! Except under MacOS X, it is necessary to have the JAVA_HOME environment variable set to the appropriate path in order to be able to compile sources through the ocamljava compiler.

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.

ocamlcocamloptocamljava
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.cmj
or just one step:
ocamljava -o myprog.jar source.ml
Then, 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 namedescription
camlp4*the various camlp4 preprocessors
ocamlthe toplevel, as a terminal application
ocamlbuildthe compilation manager
ocamlcthe OCaml bytecode compiler
ocamldebugthe debugger (for ocamlc-compiled programs)
ocamldepthe dependency analyzer
ocamldocthe documentation generator
ocamljarthe post-compilation optimizer
ocamljavathe Java bytecode compiler
ocamllexthe lexer generator
ocamlrunthe interpreter for ocamlc-compiled programs
ocamltopthe toplevel, as a windowed application
ocamlwrapthe Java wrapper

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:

  • tail calls are optimized only for direct self-recursion;
  • evaluation order is not guaranteed to be the same as in ocamlc/ocamlopt (however, it should not be a major problem as evaluation order is not specified in the OCaml language);
  • stack overflow as well as memory shortage are not diagnosed by the OCaml-Java runtime;
  • backtrace support is rudimentary;
  • 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:

ocamljar <options> input-file.jar output-file.jar
where possible options are:
command-line switchdefault valuemeaning
-no-dynlink <bool>truewhether to assume absence of dynamic linking
-no-runtime-lock <bool>truewhether to remove support for runtime lock
-no-signals <bool>truewhether to remove support for signals
-one-context <bool>truewhether to assume unique context (meaning that there should be only one OCaml-Java program executing in the JVM)
-unsafe <bool>falsewhether to use unsafe containers (allowing to avoid array bound checks performed by the JVM for container classes representing OCaml values)

Warning! when using the unsafe containers, it is necessary to run the code with enhanced privileges, through 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.

Warning! OCaml-Java is much slower than the original OCaml in the handling of exceptions.

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.

Warning! by default, OCaml-Java favors compatibility with the original OCaml implementation, meaning that it is based on a global runtime lock. In order to leverage the power of the concurrent library, it is necessary to disable the runtime lock by linking the program with the -runtime-parameter runtime-lock=off command-line option.

Since version 2.0-early-access8, the distribution includes a new extension to the OCaml typer that allows to create and manipulate Java instances using OCaml code. An overview of these extensions is available here.

Since version 2.0-early-access9, the distribution allows to write applets. Applets can be based on the Java AWT toolkit, the Java Swing toolkit, or the OCaml Graphics module. More information on how to develop and deploy applet 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 typeOCaml 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);
    }

}

Since version 2.0-early-access6, the distribution features a tool named ocamlwrap that can be used to generate Java class definitions for easy access to ocamljava-compiled code from the Java language. An overview of the tool is available here.

The following versions are available:
2.0-early-access11 88 downloads
2.0-early-access10 82 downloads
2.0-early-access9 275 downloads
2.0-early-access8 187 downloads
2.0-early-access7 214 downloads
2.0-early-access6 222 downloads
2.0-early-access5 256 downloads
2.0-early-access4 237 downloads
2.0-early-access3 263 downloads
2.0-early-access2 352 downloads

2176 downloads

The following changes occurred:

VersionDateChanges
2.0-early-access11 2014-02-24
  • fixed bug in method cache (resulting in a runtime error)
2.0-early-access10 2014-01-27
  • ocamlwrap: new -library-xyz options to control initialization of wrapped library
  • fixed bug in proxies (incorrect method name when overloaded)
  • fixed bug in proxies (NullPointerException when return type is boolean)
  • fixed bug in proxies (when passed interface extends another one)
  • fixed bug in typer extension (when using values of type byte/char/short)
  • fixed bug#125 (ocamlwrap now issues a proper error when a type cannot be found)
  • fixed bug#126 (ocamlwrap can now generate wrapper for functions with arity up to 10)
  • fixed bug#127 (ocamlwrap now properly escapes Java keywords)
2.0-early-access9 2013-08-27
  • proxies now support multiple interfaces
  • proxies now allow to override methods from java.lang.Object
  • Java.instanceof and Java.cast now accept array types
  • a new warning (with number 1000) has been introduced, to be issued when a deprecated Java element is used
  • the Java.make_array1 function has been replaced by the more flexible Java.make_array_dims whose string descriptor allows to choose the number of dimentions to instantiate
  • a new JavaStreams module has been added to allow conversion between Java streams and OCaml channels
  • utility functions have been added to the JavaString module
  • support for applets is back
  • fixed bug in Unix.localtime (incorrect hour value when PM)
  • fixed bug in interface method calls (incorrect argument count when long or double value)
  • fixed bug in proxies (Java primitives values incorrectly passed)
  • fixed bug in proxies (values incorrectly returned)
  • fixed bug in proxies (when methods from java.lang.Object are called)
2.0-early-access8 2013-07-31
  • typer extension and associated library for manipulation of Java entities
  • ocamlbuild updated to support typer extension
  • ocamldoc updated to support typer extension
2.0-early-access7 2013-06-30
  • parameter and return values to/from primitives can now be unboxed
  • parameter and return values to/from functions can now be unboxed
  • values with type int array now benefit from an optimized representation
  • improved handling of exceptions
  • improved handling of module constants
  • improved handling of module globals
  • improved startup time
  • slightly improved code generation for pattern matching
  • fixed bug in compilation of for loops with known bounds
  • fixed bug in compilation of never-returning functions
2.0-early-access6 2013-05-31
  • new ocamlwrap tool
  • slightly improved code generation
  • new -linkall command-line option for ocamljava, also meaning that the default is no more to link all modules
  • STM.run and STM.run_read_only now ensure that accessors are called from the thread that created the transaction
  • [Scheduled]Future.get[_time] now raise Runtime.Raised if the future raises an exception
  • parallel operations of ParallelArray now raise Runtime.Raised if a passed function raises an exception
  • MapReduce.S.compute now raises Runtime.Raised if a passed function raises an exception
  • ForkJoin functions now raise Runtime.Raised if a passed function raises an exception
2.0-early-access5 2013-04-24
  • ParallelArray.init is now a parallel operation
  • ParallelArray now provides more parallel operations (mem, memq, exists, for_all, find, find_index, and find_all)
  • STM.run and STM.run_read_only now return the value computed by the transaction
  • Thread.interrupted now returns a boolean
  • better handling of exceptions in Concurrent library
  • new tool: ocamljar, a post-compilation optimizer
  • support for ocamldebug is back
  • support for scripting is back
  • fixed bug#82 (dependency of scripting support)
2.0-early-access4 2013-03-28
  • enhanced Concurrent library
  • fixed bug#102 (Sys.os_type is always "Unix")
  • fixed bug#117 (ocamlbuild is not provided)
  • fixed bug#118 (Sys.command should call a shell)
  • reduced startup time
2.0-early-access3 2013-03-07
  • fixed bug#103 (Unix.descr_of_in_channel is broken)
  • fixed bug#113 (comparison fails on large int values)
  • fixed bug#114 (cannot use with bare JRE)
  • fixed bug#114 (read_int is broken)
  • fixed bug#115 (ocaml cannot execute file)
  • minor performance improvements (compiler and runtime)

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).