All Java templates

GraalVM Polyglot Programming

Embedding JavaScript, Python, and Ruby with GraalVM Polyglot APIs.

DevZone Tools580 copiesUpdated Apr 22, 2026GraalVMJava
# CLAUDE.md — GraalVM Polyglot Programming

## What polyglot is

- GraalVM can run JavaScript, Python, Ruby, R, and LLVM-based languages from inside a Java program.
- Languages share a single VM, GC, and compiler. Calls between languages are zero-copy where possible.
- Use cases: embedding a scripting language, running user-supplied snippets, mixing ML libraries with a Java service.

## Setup

- Add the polyglot SDK and the language you want:
  ```xml
  <dependency>
      <groupId>org.graalvm.polyglot</groupId>
      <artifactId>polyglot</artifactId>
      <version>23.1.0</version>
  </dependency>
  <dependency>
      <groupId>org.graalvm.polyglot</groupId>
      <artifactId>js</artifactId>
      <version>23.1.0</version>
      <type>pom</type>
  </dependency>
  ```
- For Python, use `python-community`. Each language is a separate dependency.

## Basic API

```java
try (Context ctx = Context.newBuilder("js")
        .allowAllAccess(true)
        .build()) {
    Value result = ctx.eval("js", "1 + 2 * 3");
    System.out.println(result.asInt()); // 7
}
```

- `Context` is the runtime. Reuse it for many evaluations — creation is expensive.
- `Value` is the polyglot representation of any JS/Python/Ruby value. Convert with `asInt`, `asString`, `as(T.class)`.
- `Source.create("js", code)` lets you name the source for stack traces.

## Calling Java from a guest language

```java
ctx.getBindings("js").putMember("repo", userRepository);
ctx.eval("js", "repo.findById('123').getEmail()");
```

- `allowHostAccess(HostAccess.ALL)` to expose Java methods. Use `HostAccess.EXPLICIT` and `@HostAccess.Export` to allow only annotated methods — safer for user-supplied code.

## Calling guest from Java

```java
Value func = ctx.eval("js", "(x) => x * 2");
int result = func.execute(21).asInt();
```

- Treat `Value` as a function with `.execute(...)`.
- For complex types, define a Java interface and `Value.as(MyInterface.class)` to bridge.

## Sandboxing

- For executing **untrusted** code (user scripts, plugins):
  ```java
  Context ctx = Context.newBuilder("js")
      .allowHostAccess(HostAccess.NONE)
      .allowIO(false)
      .allowCreateThread(false)
      .resourceLimits(ResourceLimits.newBuilder().statementLimit(10_000).build())
      .build();
  ```
- Set CPU and statement limits — otherwise an infinite loop hangs the host.
- Don't allow `allowAllAccess(true)` for untrusted input.

## Performance

- First execution warms up the compiler. Reuse `Context` and pre-parsed `Source` objects.
- For hot loops, write the kernel in Java and call it from the guest.
- Polyglot has overhead — don't use it for things you could do in a single language.

## Native image

- Polyglot **does** work with native image, but each language adds significantly to image size.
- Build with `--language:js` (and similar) flags.
- Test in native mode early — some language features may not be supported in native.

## Don't

- Don't reach for polyglot to "use a Python library" without measuring. JNI to a native lib or shelling out is sometimes simpler.
- Don't eval user input without sandboxing. JS can do everything Java can if you give it `HostAccess.ALL`.
- Don't create a new `Context` per request. The boot cost is real.
- Don't ship polyglot to production without resource limits — one runaway script will hang the JVM.

Other Java templates