- GraalVM for JDK 22 (Latest)
- GraalVM for JDK 23 (Early Access)
- GraalVM for JDK 21
- GraalVM for JDK 17
- Archives
- Dev Build
- Java on Truffle
- JavaScript and Node.js Reference
- LLVM Languages Reference
- Compiling Native Projects to LLVM Bitcode
- Interaction of GraalVM with Native Code
- Interoperability
- GraalVM LLVM Runtime Debugging
- LLI Command Options
- LLVM Compatibility
- Python Reference
- Ruby Reference
- GraalVM R Runtime
- GraalWasm
This documentation is for the unreleased GraalVM version.Download Early Access Builds from GitHub.
Interoperability
GraalVM supports several other programming languages including JavaScript, Python, Ruby, and R.
While GraalVM’s implementation of lli
is designed to run LLVM bitcode, it also provides the API for programming language interoperability that lets you execute code from any other GraalVM-supported language.
Dynamic languages like JavaScript usually access object members by name. Since normally names are not preserved in LLVM bitcode, it must be compiled with debug information enabled (the LLVM toolchain shipped with GraalVM will automatically enable debugging information).
The following example demonstrates how you can use the API for interoperability with other programming languages.
Define a C struct for points and implement allocation functions in a file named cpart.c:
// cpart.c
#include <graalvm/llvm/polyglot.h>
#include <stdlib.h>
#include <stdio.h>
struct Point {
double x;
double y;
};
POLYGLOT_DECLARE_STRUCT(Point)
void *allocNativePoint() {
struct Point *ret = malloc(sizeof(*ret));
return polyglot_from_Point(ret);
}
void *allocNativePointArray(int length) {
struct Point *ret = calloc(length, sizeof(*ret));
return polyglot_from_Point_array(ret, length);
}
void freeNativePoint(struct Point *p) {
free(p);
}
void printPoint(struct Point *p) {
printf("Point<%f,%f>\n", p->x, p->y);
}
Make sure LLVM_TOOLCHAIN
resolves to the GraalVM LLVM toolchain (lli --print-toolchain-path
), and then compile cpart.c (the graalvm-llvm library defines the Polyglot API functions used in the example):
$LLVM_TOOLCHAIN/clang -shared cpart.c -lgraalvm-llvm -o cpart.so
You can then access this C/C++ code from other languages. For example, save this JavaScript code in the jspart.js file:
// Load and parse the LLVM bitcode into GraalVM
var cpart = Polyglot.evalFile("llvm" ,"cpart.so");
// Allocate a light-weight C struct
var point = cpart.allocNativePoint();
// Access it as if it was a JS object
point.x = 5;
point.y = 7;
// Pass it back to a native function
cpart.printPoint(point);
// Allocate an array of structs
var pointArray = cpart.allocNativePointArray(15);
// Access this array like it was a JS array
for (var i = 0; i < pointArray.length; i++) {
var p = pointArray[i];
p.x = i;
p.y = 2*i;
}
cpart.printPoint(pointArray[3]);
// Additionally, pass a JS object to a native function
cpart.printPoint({x: 17, y: 42});
// Free the unmanaged data objects
cpart.freeNativePoint(point);
cpart.freeNativePoint(pointArray);
Finally, run this JavaScript file:
js --polyglot jspart.js
Point<5.000000,7.000000>
Point<3.000000,6.000000>
Point<17.000000,42.000000>
Polyglot C API #
There are also lower level API functions for directly accessing polyglot values from C.
See the Polyglot Programming reference and the comments in polyglot.h
for more details.
For example, this program allocates and accesses a Java array from C:
#include <stdio.h>
#include <graalvm/llvm/polyglot.h>
int main() {
void *arrayType = polyglot_java_type("int[]");
void *array = polyglot_new_instance(arrayType, 4);
polyglot_set_array_element(array, 2, 24);
int element = polyglot_as_i32(polyglot_get_array_element(array, 2));
printf("%d\n", element);
return element;
}
Compile it to LLVM bitcode:
$LLVM_TOOLCHAIN/clang polyglot.c -lgraalvm-llvm -o polyglot
Then run it:
lli polyglot
24
Embedding in Java #
You can embed LLVM bitcode in a Java host application.
For example, write a Java class Polyglot.java
that embeds LLVM bitcode to run the previous example:
import java.io.*;
import org.graalvm.polyglot.*;
class Polyglot {
public static void main(String[] args) throws IOException {
Context polyglot = Context.newBuilder().
allowAllAccess(true).build();
File file = new File("polyglot");
Source source = Source.newBuilder("llvm", file).build();
Value cpart = polyglot.eval(source);
cpart.execute();
}
}
Compile it and run:
javac Polyglot.java
java Polyglot
24
See the Embedding Languages reference for more information.