Module Java

module Java: sig .. end
Manipulation of Java references.

The ocamljava compiler allows to manipulate Java references through typer extensions triggered by the -java-extensions command-line switch. The Java types can then be manipulated through two types, namely cn java_instance and cn java_extends. The former is used to designate instances of exactly the given class cn, while the latter is used to designate instances of either the class cn or any of its subclasses. In both cases, the type parameter cn is used to specify the class, and uses the fully-qualified name of the class where dots are replaced with single quotes. As a consequence, the type of Java strings is thus written java'lang'String java_instance.

This module contains the functions needed to create new instances, call methods, and access fields. Such functions use descriptors to determine the constructor/method/field to use. These descriptors are written as string ltterals; for example, parsing a string into an integer can be done by writing:
  let i = call "java.lang.Integer.parseInt(java.lang.String):int" s
However, it is possible to use simple names rather than qualified names for classes if their packages have been opened. Initially, only the java.lang package is opened. A package can be opened though a modified open Package'packname directive; for example, the javax.awt package can be opened by writing:
  open Package'java'awt
It is also possible to take advantage of opened packages in types, by replacing the package name with an underscore. The type of Java strings can thus be written _'String java_instance.

Moreover, types of fields and return types of methods can be elided as long as there is no ambiguity. Types of method and constructor parameters can also be replaced with single underscores, leading to the shorter code to parse an integer:
  let i = call "Integer.parseInt(_)" s
Furthermore, it is possible to use dashes to denote any number of parameters, leading to the lightest code to rotate an integer value:
  let j = call "Integer.rotateLeft(-)" i nbits
The compiler will issue an error if there is an ambiguity.

Besides the cn java_instance and cn java_extends types that are used to map Java reference types, the compiler maps Java primitive type to newly-introduced OCaml types that are synonym of OCaml predefined types. The complete mapping is given by the following table.
Mapping of Java primitive types.
Java type OCaml type Synonym
boolean java_boolean bool
byte java_byte int
char java_char int
double java_double float
float java_float float
int java_int int32
long java_long int64
short java_short int
void java_void unit


A similar scheme is used for Java array types, with a dedicated type for each primitive array type, and an additionnal type for arrays of references. However, contrary to primitive types, array types are not synonyms of existing OCaml types, and a module is associated to each type in order to provide usual operations. The complete mapping from Java array types to OCaml types is given by the following table.
Mapping of Java array types.
Java type OCaml type OCaml module
boolean[] java_boolean java_boolean_array JavaBooleanArray
byte[] java_byte java_byte_array JavaByteArray
char[] java_char java_char_array JavaCharArray
double[] java_double java_double_array JavaDoubleArray
float[] java_float java_float_array JavaFloatArray
int[] java_int java_int_array JavaIntArray
long[] java_long java_long_array JavaLongArray
short[] java_short java_short_array JavaShortArray
reference[] 'a java_reference_array JavaReferenceArray
Each primitive type is parametrized by the type of its elements, allowing a generic treatment of all array types through the JavaArray module.

When calling a method with a variable number of arguments, two variants are accepted for the descriptor, impacting the way arguments should be passed: The following code illustrates the alternative:
  let l1 =
    Java.call "Arrays.asList(Object[])"
      (Java.make_array "Object[]" 5l)
  let l2 =
    Java.call "Arrays.asList(Object...)"
      [| Java.null ; Java.make "Object()" () |]


Finally, two exceptions are defined to wrap Java exceptions on the OCaml side:
  exception Java_exception of java'lang'Exception java_instance
  exception Java_error of java'lang'Error java_instance
The former is used for exceptions whose instances inherit from java.lang.Exception (i.e. checked exceptions), while the latter is used for exceptions whose instances inherit from java.lang.Error (i.e. unchecked exceptions).


Instance creation

 
val make : 'a java_constructor -> 'a
make desc param1 ... paramn calls the constructor whose descriptor is desc with parameters param1 ... paramn, and returns the created instance.

desc is composed of the following elements:
  • a class name;
  • an opening parenthesis (i.e. ();
  • a comma-separated list of types;
  • a closing parenthesis (i.e. )).
For example, the following code creates an object instance:
  let inst = make "java.lang.Object()" ()

Raises
  • Java_exception if the constructor throws an exception
  • Java_error if the constructor throws an error
 
val make_array : 'a java_array_shape -> 'a
make_array desc dim1 ... dimn builds and returns an array, whose number of dimensions and type of elements are determined by desc. Each element is initialized to the default value for the type (that is false for booleans, zero for other primitive types, and null for reference types).

desc is composed of the following elements:
  • a type;
  • a non-empty list of [] characters.
For example, the following code creates a 2x3 matrix of byte values:
  let arr = make_array "byte[][]" 2l 3l

Raises Java_exception if a dimension is negative
 
val make_array_dims : 'a java_array_shape_dims -> 'a
make_array_dims desc dim1 ... dimn is similar to Java.make_array, except that the array descriptor is made of two kinds of dimension specifiers, allowing to initialize only the first dimensions of the array.

desc is composed of the following elements:
  • a type;
  • a non-empty list of dimension specifiers; where a dimension specifiers can be one of:
  • [_] that indicates that the dimension will be allocated;
  • [] that indicates that the dimension will not be allocated.
For example, the following code creates a two-dimensional array, but only the first dimension of the array is allocated and initialized:
  let arr = make_array_dims "byte[_][]" 2l

Raises Java_exception if a dimension is negative
 

Method call

 
val call : 'a java_method_call -> 'a
call desc param1 ... paramn calls and returns the result of method desc called with parameters param1 ... paramn, where param1 is the instance to call method upon if the method is not static.

desc is composed of the following elements:
  • a class name;
  • a dot (i.e. .);
  • a method name;
  • an opening parenthesis (i.e. ();
  • a comma-separated list of types;
  • a closing parenthesis (i.e. ));
  • optionally, a colon (i.e. :) followed by a type.
For example, the following code compares two strings s1 and s2:
  call "java.lang.String.compareTo(java.lang.String):int" s1 s2

Raises
  • Java_exception if the method throws an exception
  • Java_error if the method throws an error
 
val exec : 'a java_method_exec -> 'a
Similar to Java.call, but ignores the result if any.
 
val chain : 'a java_method_chain -> 'a
Similar to Java.call, returns the instance the method was called upon.
 

Field access

 
val get : 'a java_field_get -> 'a
get desc obj retrieves the value of field desc for instance obj. The obj value should be replaced by () if desc designates a static field.

desc is composed of the following elements:
  • a class name;
  • a dot (i.e. .);
  • optionally, a colon (i.e. :) followed by a type.
For example, the following code gets the maximum value of a integer:
  let max_int = get "java.lang.Integer.MAX_VALUE:int" ()

Raises Java_exception if obj is null
 
val set : 'a java_field_set -> 'a
set desc obj x changes the value of field desc for instance obj to x. The obj value should not be provided if desc designates a static field.

desc is composed of the following elements:
  • a class name;
  • a dot (i.e. .);
  • optionally, a colon (i.e. :) followed by a type.
For example, the following code sets the height of dimension dim to zero:
  let () = set "java.awt.Dimension.height:int" dim 0l

Raises Java_exception if obj is null
 

Iteration

 
val iter : 'a java_reference_type ->
('a -> unit) -> java'util'Iterator java_extends -> unit
iter desc f it applies f to every element returned by it, after casting them to desc.

desc is either a class name, or an array descriptor.
Raises Java_exception if it is null
 
val fold : 'a java_reference_type ->
('b -> 'a -> 'b) -> 'b -> java'util'Iterator java_extends -> 'b
fold desc f z it computes (f ... ((f z it0) it1) ... itn) where iti values are successively returned by it, and casted to desc before they are passed to f.

desc is either a class name, or an array descriptor.
Raises Java_exception if it is null
 

Null value

 
val null : 'a java_instance
The null value.
 
val is_null : 'a java_instance -> bool
is_null x returns true iff x is equal to null.
 
val is_not_null : 'a java_instance -> bool
is_not_null x returns false iff x is equal to null.
 

Equality test

 
val equal : 'a java_instance -> 'b java_instance -> bool
equal x y returns true if x and y designate the very same reference.
 
val not_equal : 'a java_instance -> 'b java_instance -> bool
not_equal x y returns false if x and y designate the very same reference.
 

Class test

 
val instanceof : 'a java_reference_type -> 'b java_instance -> bool
instanceof desc x returns true if x is an instance of desc.

desc is either a class name, or an array descriptor.
 
val cast : 'a java_reference_type -> 'b java_instance -> 'a
cast desc x casts x, so that it can be used as an instance of desc.

desc is either a class name, or an array descriptor.
Raises Java_exception if the cast fails
 

Class retrieval

 
val get_class : 'a java_any_type -> java'lang'Class java_instance
get_class desc returns the instance of java.lang.Class representing the passed type descriptor.

desc can designate any Java type (primitive, array, reference).
 

Exception throw

 
val throw : java'lang'Throwable java_extends -> 'a
throw x raises the instance x, that will be wrapped into either a Java_exception, or a Java_error on the OCaml side.
Raises
 

Synchronization

 
val synchronized : 'a java_instance -> (unit -> unit) -> unit
synchronized obj (fun () -> ...) is equivalent to the Java code synchronized (obj) { ... }.
Raises Java_exception if the obj is null
 

Interface implementation

 
val proxy_loader : 'a java_proxy -> java'lang'ClassLoader java_extends -> 'a
proxy_loader desc cl impl returns an instance that implements the interfaces specified by desc, using the methods provided by impl. The class is defined in the class loader cl.

desc is basically a comma-separated list of interface names.

For example, an instance of java.lang.Runnable can be built using the following code:
  proxy "java.lang.Runnable" (object
    method run = ...
  end)
When only one interface is provided, the instance returned has this type, otherwise it has type java.lang.Object.

It is also possible to override methods from the java.lang.Object class (independently of their presence or absence in any of the interfaces), by using .methodName notation in desc. As of Java 1.7, only three methods can be overridden:
  • toString;
  • equals;
  • hashCode.
For example, an instance of java.lang.Runnable overriding toString can be built using the following code:
  proxy_loader "java.lang.Runnable, .toString" loader (object
    method run = ...
    method toString = ...
  end)

 
val proxy_system : 'a java_proxy -> 'a
Similar to Java.proxy_loader, but uses the system class loader.
 
val proxy_runtime : 'a java_proxy -> 'a
Similar to Java.proxy_loader, but uses the class loader that was used to load the OCaml-Java runtime.
 
val proxy : 'a java_proxy -> 'a
Synonym for Java.proxy_system.
 

Miscellaneous

 
val wrap : 'a java_instance -> 'a java_instance option
wrap x wraps the reference x into an option type:
  • Some x if x is not null;
  • None if x is null.

 
val unwrap : 'a java_instance option -> 'a java_instance
unwrap x unwraps the option x into a bare reference:
  • Some x is mapped to x;
  • None is mapped to null.