Java Foreign Function Interface
This page describes the API known as the Java FFI offered by ABCL to call arbitrary Java code. Unless otherwise noted, all the symbols are exported from the JAVA package, which is used by CL-USER.
The basics
The core API is based on Java reflection. Some operators come in two flavors: a concise one that leaves some things to be computed by ABCL at runtime, and a more efficient and verbose one, which is mostly a direct translation of the Java reflection API. All the operators that pass arguments to Java code can receive arbitrary Lisp objects, that will be automatically translated to appropriate Java objects when applicable (technically, by calling javaInstance() on them). For example, Lisp strings are translated to instances of java.lang.String.
Definitions
- Java object: within ABCL, a Java object is an object of type JAVA-OBJECT. From the Java point of view, it is an instance of the class JavaObject wrapping a native Java object. In this page, the expressions "an instance of the (Java) class X" or "an object of (Java) class X" should be read as "a JAVA-OBJECT wrapping an instance of/an object of...". Java objects are understood by DESCRIBE and INSPECT.
- Java class designator: either a string denoting the fully qualified name of a Java class, such as "java.lang.String", or a Java class metaobject, that is, an instance of java.lang.Class, for example as returned by the function
jclass
. - Java method designator: in the context of Java method invocations, either a Java method metaobject (an instance of java.lang.reflect.Method), or a string representing the name of the method, for example "toString".
- Java constructor designator: in the context of Java object instantiations, either a Java constructor metaobject, or a Java class designator.
Function JCALL, JCALL-RAW
Syntax:
jcall method instance &rest args => object
jcall-raw method instance &rest args => JAVA-OBJECT
Arguments and Values:
method
-- a Java method designator, that is, either a Java method metaobject (an instance of java.lang.reflect.Method), or a string representing the name of the method, for example "toString".
instance
-- the receiver object target of the method call. If the method is static, this argument is ignored and can be NIL.
args
-- the arguments passed to the method.
Description:
Reflectively calls a method and returns the result of the call. If method
is a string, ABCL dynamically examines the class of instance
to search for the most specific applicable method with that name, following Java overload resolution rules. If method
is a Java method metaobject, it is called directly.
jcall
translates the result to a Lisp object if possible. jcall-raw
performs no translation and always returns the original Java object.
Note: jcall
and other primitives that perform automatic method resolution are only capable of finding accessible (i.e., in general, public) methods.
Examples:
(jcall "toString" T) => "COMMON-LISP:T" (jcall-raw "toString" T) => #<java.lang.String COMMON-LISP:T {21B42F}> (jcall "compareTo" 12 24) => -1 ;;Resolves the method at runtime: inefficient but concise (jcall (jmethod "java.lang.Comparable" "compareTo" "java.lang.Object") 12 24) => -1 ;;Same as above, but avoiding dynamic method resolution
Function JSTATIC, JSTATIC-RAW
Syntax:
jstatic method class &rest args => object
jstatic-raw method class &rest args => JAVA-OBJECT
Arguments and Values:
method
-- a Java method designator.
class
-- a Java class designator.
args
-- the arguments passed to the method.
Description:
Reflectively calls a static method and returns the result of the call. (jstatic method class args)
is equivalent to (jcall (jmethod class method) nil args)
when method
is a string, and to (jcall method nil args)
when method
is a Java method metaobject (class is thus ignored in that case). Similarly for the -raw
variants.
jstatic
translates the result to a Lisp object if possible. jstatic-raw
performs no translation and always returns the original Java object.
Examples:
(jstatic "getRuntime" "java.lang.Runtime") => #<java.lang.Runtime java.lang.Runtime@1ef3212 {C07527}> (jstatic-raw "getRuntime" "java.lang.Runtime") => #<java.lang.Runtime java.lang.Runtime@1ef3212 {156D7C8}> (jstatic "getRuntime" (jclass "java.lang.Runtime")) => #<java.lang.Runtime java.lang.Runtime@1ef3212 {C8E4DE}> (jstatic (jmethod "java.lang.Runtime" "getRuntime") nil) => #<java.lang.Runtime java.lang.Runtime@1ef3212 {129DF8A}>
Function JFIELD, JFIELD-RAW, (SETF JFIELD)
Syntax:
jfield class-ref-or-field field-or-instance &optional instance value => object
jfield-raw class-ref-or-field field-or-instance &optional instance value => JAVA-OBJECT
(setf (jfield class-ref-or-field field-or-instance &optional (instance nil instance-supplied-p) unused-value) newvalue)
Arguments and Values:
class-ref-or-field
-- depending on the usage pattern, a Java class designator or a string naming a field in a Java object.
field-or-instance
-- depending on the usage pattern, a Java object or a string naming a field in a Java object.
instance
-- a Java object.
value
-- an object; the new value of the field.
unused-value
-- ignored, present only to make (setf jfield)
accept the same parameter patterns as jfield
.
Description:
jfield
is a complex operator supporting several usage patterns for reading the value of a Java field. For historical reasons, jfield
can also be used to set the value of a field, but the more idiomatic form (setf jfield)
should be preferred. These are the possible usages of jfield
:
For reading values:
(jfield
class-ref field)
: Retrieves the value of the static fieldfield
from classclass-ref
.(jfield
field instance)
: Retrieves the value of the fieldfield
from the Java objectinstance
. The class to which the field belongs is taken to be the class ofinstance
.(jfield
class-ref field instance)
: Retrieves the value of the fieldfield
of the classclass-ref
from the Java objectinstance
.
For storing values:
(jfield
class-ref field primitive-value)
: Storesprimitive-value
as the value of the static fieldfield
of classclass-ref
.(jfield
field instance value)
: Storesvalue
as the value of the fieldfield
in the Java objectinstance
. The class to which the field belongs is taken to be the class ofinstance
.(jfield
class-ref field instance value)
: Storesvalue
as the value of the fieldfield
of the classclass-ref
in the Java objectinstance
.(jfield
class-ref fieldNIL
value)
: Storesvalue
as the value of the static fieldfield
of classclass-ref
, whenvalue
could be confused with an instance (case 3).
(setf jfield)
can be used with patterns 1, 2 and 3 to store a value where jfield
would have read it from.
jfield
translates the value of the field to a Lisp object when possible. jfield-raw
performs no such translation.
Examples:
(jfield "java.lang.System" "out") => #<java.io.PrintStream java.io.PrintStream@198a1f4 {1B0D990}> (jfield "width" (jnew "java.awt.Dimension")) => 0 (let ((d (jnew "java.awt.Dimension"))) (setf (jfield "width" d) 42) (jcall "toString" d)) => "java.awt.Dimension[width=42,height=0]"
Function JNEW
Syntax:
jnew constructor &rest args => JAVA-OBJECT
Arguments and Values:
constructor
-- a Java constructor designator (see Definitions).
args
-- the arguments passed to the constructor.
Description:
Returns a new Java object created calling the specified constructor with the specified arguments. If constructor
is a Java constructor metaobject, it will be called directly. If it is a Java class designator, the most specific constructor with respect to args
will be searched in that class.
Examples:
(jnew "java.lang.String" "foo") => #<java.lang.String foo {1E5BA24}> (jnew (jclass "java.lang.String") "foo") => #<java.lang.String foo {1E5BA24}> (jnew (jconstructor "java.lang.String" "java.lang.String") "foo") => #<java.lang.String foo {1E5BA24}>
Function JCLASS
Syntax:
jclass name-or-class-ref &optional class-loader => a Java class metaobject
Arguments and Values:
name-or-class-ref
-- a Java class designator (see Definitions).
class-loader
-- the classloader to use to resolve the class. Refer to the section Class resolution and loading.
Description:
Returns a reference to the Java class designated by name-or-class-ref
. If the class-loader
parameter is passed, the class is resolved with respect to the given ClassLoader.
Examples:
(jclass "java.util.LinkedList") => #<java.lang.Class class java.util.LinkedList {11B50A1}>
Function JMETHOD
Syntax:
jmethod class-ref method-name &rest parameter-class-refs => a Java method metaobject
Arguments and Values:
class-ref
-- a Java class designator.
method-name
-- a string, the name of the method.
parameter-class-refs
-- Java class designators representing the types of the method's arguments, in order.
Description:
Returns a reference to the public Java method named method-name
in class class-ref
, with the signature represented by parameter-class-refs
.
Examples:
(jmethod "java.util.LinkedList" "equals" "java.lang.Object") => #<java.lang.reflect.Method public boolean java.util.Abstrac... {600A08}>
Function JCONSTRUCTOR
Syntax:
jconstructor class-ref &rest parameter-class-refs => a Java constructor metaobject
Arguments and Values:
class-ref
-- a Java class designator.
parameter-class-refs
-- Java class designators representing the types of the constructor's arguments, in order.
Description:
Returns a reference to the public Java constructor in the class class-ref
, with the signature represented by parameter-class-refs
.
Examples:
(jconstructor "java.util.LinkedList" "java.util.Collection") => #<java.lang.reflect.Constructor public java.util.LinkedList(java... {35EE49}>
Function JCOERCE
Syntax:
jcoerce value intended-class
Arguments and Values:
value
-- an arbitrary Common Lisp data item
intended-class
-- string naming a kind of java-object
Description:
Returns java-object
of the appropriate type, if it can. Otherwise raises a TYPE-ERROR
. A primary purpose of this function is to translate lisp data items into Java primitives so that Java methods with primitive type arguments can be used.
Examples:
(jcoerce 1.0d0 "double") => #<java.lang.Double 1.0 {13424219}>
(multiple-value-list (ignore-errors (jcoerce 1.0d0 "int"))) => (NIL #<TYPE-ERROR {236312F7}>)
Class resolution and loading
TODO
High-level constructs
TODO
CLOS integration
TODO
Implementing Java interfaces in Lisp
TODO
Defining Java classes in Lisp
See the runtime-class page for details.
A quick "cheat sheet":
(This is a very rough draft thrown together from an email by Alessio Stalla to the mailing list. It will be gradually superseded by the documentation above.)
(jclass <class name>)
- gives you a Java class
(jmethod <java class> <method names> <&rest argument types>)
- gives you a method
(jconstructor <java class> <&rest argument types>)
- a constructor
(jnew <constructor> <&rest arguments>)
- instantiates a new Java object
(jcall <method> <object> <&rest arguments>)
- calls a method
jstatic
- to access static fields and methods.
jfield
- to access fields.
jproperty-value
and(setf jproperty-value)
- access "properties" following the Java Bean convention (setXXX and getXXX).
That's almost all; there is some more advanced stuff (e.g. manipulating Java arrays).
You can find most or all of this stuff inside Java.java. It's not documented but quite readable.
For example code that uses the Java FFI API, see the examples.
(The rest of the page is taken from the symbols and comments in Java.java. Still needs a lot of work, obviously.)
register-java-exception
exception-name condition-symbol => T
or NIL
Registers the Java Throwable exception-name as the condition designated by condition-symbol.
unregister-java-exception
exception-name => T
or NIL
Unregisters the Java Throwable exception-name previously registered by register-java-exception
.
jfield` class-ref-or-field field-or-instance &optional instance value
jfield-raw
class-ref-or-field field-or-instance &optional instance value
Retrieve or modify a field in a Java class or instance.
Supported argument patterns:
- class-ref field-name
- Retrieve the value of a static field.
- class-ref field-name instance-ref
- Retrieve the value of a class field of the instance.
- class-ref field-name primitive-value
- Store primitive-value in a static field.
- class-ref field-name instance-ref value
- Store value in a class field of the instance.
- class-ref field-name nil value
- Store value in a static field (when value may be confused with an instance-ref).
- field-name instance
- Retrieve the value of a field of instance. The class is derived from instance.
- field-name instance value
- Store value in a field of instance. The class is derived from instance.
jconstructor
class-ref &rest parameter-class-refs => constructor-ref
Returns a reference to the Java constructor of class-ref with the given parameter-class-refs.
jmethod
class-ref method-name &rest parameter-class-refs => method-ref
Returns a reference to the Java method method-name of class-ref with the given parameter-class-refs.
jstatic
method-ref class-ref &rest args => result
jstatic-raw
method-ref class-ref &rest args result
jnew
constructor &rest args => object
Invokes the Java constructor constructor with the arguments args
jnew-array
element-type &rest dimensions => array-object
Creates a new Java array of type element-type, with the given dimensions.
jarray-ref
java-array &rest indices => object
Dereference the Java array java-array using the given indices, coercing the result into a Lisp type, if possible.
jarray-ref-raw
java-array &rest indices => object
Dereference the Java array java-array using the given indices. Does not attempt to coerce the result into a Lisp type.
jarray-set
java-array new-value &rest indices => new-value
jcall
method-ref instance &rest args => result
jcall-raw
method-ref instance &rest args => result
jcall
calls makeLispObject() to convert the result to an appropriate Lisp type. jcall-raw
does no type conversion. The result of the call is simply wrapped in a JavaObject?. (This is true for all the -raw
variants.)
make-immediate-object
object &optional type => object
java-object-p
object => T
or NIL
Returns T
if object is an instance of JavaObject? (as opposed to a Lisp object).
jobject-lisp-value
java-object => lisp-object
Returns the Lisp object corresponding to (wrapping?) the JavaObject?. I.e. return JavaObject.getInstance(arg.javaInstance(), true);
jcoerce
object intended-class => java-object
Attempts to coerce object into a JavaObject? of class intended-class. Raises a type-error
if no conversion is possible.
%jget-property-value
java-object property-name
Use jproperty-value
instead.
%jset-property-value
java-object property-name value
Use (setf jproperty-value)
instead.
jrun-exception-protected
closure