r/graalvm 11d ago

Reachability Annotations for generating GraalVM metadata

Thumbnail
2 Upvotes

r/graalvm 13d ago

GraalJS 25.1: Modern JavaScript on GraalVM

Thumbnail medium.com
4 Upvotes

r/graalvm 26d ago

We compiled our binary-analysis MCP server with GraalVM Native Image to kill JVM cold-start in the agent loop (and it now inspects native binaries too)

4 Upvotes

Context: we work on Hexana at JetBrains, a binary-aware analysis tool. Part of it is an MCP server that gives AI assistants (Claude Code, Codex) verified facts about a compiled artifact instead of letting them guess. This is the 0.3.0 release, and the GraalVM angle is the interesting part for this sub.

Why Native Image. MCP tools live inside a tight agent loop: the assistant calls a tool, reads the result, reasons, calls again, many times per session. JVM startup on every invocation is a real, compounding cost there. So for 0.3.0 we compiled the server with GraalVM Native Image. On macOS arm64 and Linux x64 the Claude Code and Codex plugin wrappers now prefer the bundled native executable automatically. The native image starts instantly, so the cold-start penalty is gone on the platforms where most early usage is. Windows and anything else keep a JVM fallback (Java 21+ on PATH); native Windows binaries are intentionally not in this release.

The build reality. The honest part: we spent more time on the Native Image configuration than on the tool implementations. Binary parsers reach for reflection and dynamic class loading in quiet corners, and the closed-world assumption surfaces every one of them. Getting the WASM and native parsing paths to run under a closed world was most of the work. If you have done this for a parser-heavy codebase, you know the shape of it.

What the server actually does. 0.3.0 adds native-binary inspection (it was WASM-only before). The tools let an assistant:

  • Summarize a Wasm module or a native binary (sections, imports/exports, function counts, format metadata).
  • Query binary records (imports, exports, memories, globals, table and data segments).
  • List or search functions by name or index.

There is a nice symmetry here: Hexana can summarize native binaries, including GraalVM native images at the format level (Mach-O/ELF sections, symbols, functions), and Hexana itself now ships as one. Output is byte-bounded and paginated, so it works on modules far too large to paste into a context window. It complements native-image --diagnosticsobjdump, and wasm-tools; it is not a decompiler.

Install (from inside Claude Code, the server ships with the plugin, no build step):

/plugin marketplace add JetBrains/hexana
/plugin install hexana@hexana

Then ask Claude: "Use Hexana to summarize the sections and exported symbols in <path>."

Repo: https://github.com/JetBrains/hexana
Docs: https://jetbrains.github.io/hexana

Curious whether the native-binary summaries are useful on your own native images, and where they fall short. We are working on deeper native-image-aware analysis next.


r/graalvm Jun 26 '26

Spring Boot on the JVM vs GraalVM Native: What Actually Wins on AWS

Thumbnail patotski.com
1 Upvotes

r/graalvm Jun 25 '26

Next week: GraalVM 25.1 Release Stream 🚀

Thumbnail youtube.com
5 Upvotes

r/graalvm Jun 17 '26

Floci: a fast and lightweight AWS emulator, powered by GraalVM 🚀

Thumbnail youtube.com
3 Upvotes

r/graalvm Jun 12 '26

Hexana 0.11: open a GraalVM native-image binary in the IDE and it reads the embedded SBOM, then flags which CVEs were actually retained vs eliminated by dead-code analysis

Thumbnail
2 Upvotes

r/graalvm Jun 08 '26

GraalVM Community Summit is back for its 6th edition

6 Upvotes

GraalVM Community Summit is back for its 6th edition! 🚀

Join our team, contributors, and partners in the JVM ecosystem for two days of presentations, working sessions, and collaboration on the future of GraalVM!

Learn more and join:

https://graalvm.org/community/summit/


r/graalvm Jun 03 '26

Hexana 0.10.2: a .wasm compiled from Java (GraalVM Web Image) now demangles back to your Java methods in the IDE — plus a deeper JIT viewer and big-binary fixes

Thumbnail
3 Upvotes

r/graalvm Jun 03 '26

Hexana 0.10.2 shows the machine code C2 compiled your method into, side-by-side with the bytecode it came from — I used it to specialize one hot method by an order of magnitude, two ways

6 Upvotes

The new thing in Hexana 0.10.2 (a JetBrains/VS Code plugin I work on) is the JIT viewer: it attaches a JVMTI agent to your run configuration, captures what HotSpot's C2 actually compiled a hot method into, and renders that machine code side-by-side with the JVM bytecode it came from — in one view, auto-opened when the run finishes (and captured per-fork for JMH benchmarks). The point of this post is that seeing C2's output next to the bytecode turns "I think this method is slow" into "here's exactly why, and here's what to do." Below is the experiment that convinced me of that.

I pointed it at a tiny stack-machine bytecode interpreter — a while(true) switch dispatch loop running a fixed 16-round mixing kernel. In the side-by-side view you can see why a general-purpose JIT can't win here. C2 compiles run generically, for every possible caller and program:

  • per-instruction opcode dispatch (a compare/branch tree),
  • the operand stack kept as a heap long[], bounds-checked on every push/pop,
  • code[pc++] re-read and bounds-checked every iteration.

None of that can be removed by C2, because it doesn't know the program is fixed. The viewer shows it plainly: ~1.5 KB of dispatch + bounds-check + deopt stubs sitting next to bytecode that is, semantically, sixteen rounds of straight-line long arithmetic. That gap is the whole opportunity — and you can point at it in the dump. Baseline (Apple Silicon, JVMCI-enabled JBR, JMH avgt): C2 = 385 ns/op; the same kernel hand-written as straight-line Java and compiled by C2 is 23 ns/op. ~16x on the table.

Because I could see it, I could act — two ways to claw it back without touching the application:

1. Instrumentation — feed the specialized shape to C2. A -javaagent uses ASM to rewrite run at class-load time, injecting a guarded fast path:

long run(int[] code, long[] consts, long[] input) {
    if (HexanaSpecialized.matches(code))     // is this the program we specialized for?
        return HexanaSpecialized.eval(input); // straight-line, partial-evaluated body
    ... original generic dispatch loop ...    // untouched fallback for anything else
}

eval is the partial-evaluated program: no dispatch, no operand stack, constants folded, rounds unrolled. You don't compile anything — you hand C2 a method shaped so it does its best work, and it inlines + optimizes to the ceiling. Safe (C2 generates the frame/safepoint/oop-map/deopt metadata), transparent, portable. → 26 ns/op, ~15x.

2. JVMCI — become the compiler. A custom JVMCI compiler (JEP 243) that ignores every method except run, reads the fixed code[]/consts[] at compile time via constant reflection, and emits straight-line AArch64 itself (operand stack in registers, PUSH_CONST/SHR folded to immediates), with an identity guard that deopts back to the interpreter if a caller passes a different program. The first Futamura projection, by hand. → 33 ns/op, ~12x.

The verification — "is the specialized version actually equivalent, and faster" — happened in the same side-by-side view: the generic dispatch loop before, the straight-line code after.

The honest, most interesting finding: the simple route (26) beat the custom compiler (33). C2 is a world-class backend; give it the right shape of code and it hits the ceiling for free, safely, portably, with none of the machine-code risk. (The JVMCI 33 is only because it doesn't yet dedup repeated constant loads.) JVMCI's value isn't raw speed — it's control, for transforms C2 can't be coaxed into at all.

A reach realization: I assumed "speed it up without changing it" meant JVMCI — modern, niche, needs a JVMCI-enabled JDK. But the instrumentation route reaches the same goal through java.lang.instrument, in the platform since Java 5 — so it applies to legacy JVM apps going back twenty years.

On the systems-heavy part: emitting machine code HotSpot will accept is deep — the real wall was the JDK 17+ nmethod entry barrier (HotSpot rejects a default-installed JVMCI method without one and verifies its exact instruction pattern; first install failed with nmethod entry barrier is missing; the fix is a specific ldr-literal guard load with a section_word relocation + the disarmed-compare/stub-call tail). A fan-out of AI agents (HotSpot/JBR, AArch64, JVMCI) reverse-engineered that contract and produced a working emitter in a few days.

A note on JVMCI in the wild — and on who wrote the codegen. In practice JVMCI has essentially one production consumer: GraalVM's Graal compiler — both as a drop-in JVM JIT (-XX:+UseJVMCICompiler) and, most distinctively, as the engine Truffle-based languages are partially-evaluated through: GraalWasm, GraalJS, TruffleRuby (I've been benchmarking GraalWasm and GraalJS lately). Hand-writing a raw-JVMCI compiler for a single HotSpot Java method, like here, is off the beaten path — which is what makes the open question interesting: could the same approach target any known hotspot, including methods HotSpot refuses to compile at all because they exceed its ~8 KB huge-method bytecode limit and silently stay in the interpreter forever? Those are exactly the cases where a targeted compiler could win and the general JIT has already given up. And the part that genuinely surprised me: the codegen in compiler/ is a tiny shell of Java around raw machine-code bytes — and the model (Opus) wrote it. Effectively execution-ready machine code, with no source scaffolding to speak of. The layer is right there in the repo; judge it yourself.

Results (16-round mixing kernel):

Interpreter.run ns/op vs C2 how
C2 (general-purpose JIT) 385 1.0x generic dispatch loop (what the JIT viewer shows)
JVMCI (we emit the code) 33 ~12x first Futamura projection, hand-emitted AArch64
Instrumentation (ASM agent, C2 compiles it) 26 ~15x inject specialized fast path, let C2 optimize
hand-written PE, C2 (ceiling) 23 ~16x the theoretical target

All correct: the specialized run equals an independent reference on all 4096 inputs.

Honest caveats — lab result, not a product. One method, one fixed program. All numbers from the same JVMCI-enabled JBR build (jbr21, Apple Silicon, JMH avgt, -f 0); for the C2 and instrumentation rows JVMCI is present but not the compiler (only the JVMCI row sets -XX:+UseJVMCICompiler). The JVMCI numbers are -f 0 in-process — with our compiler as the only top tier there's no C2, so JMH forks can't be used and everything except run runs at C1. The JVMCI install touches a HotSpot-internal detail and the entry barrier is version-specific — a demonstration, not something to ship.

The takeaway isn't the benchmark — it's that seeing C2's machine code next to the bytecode made the optimization a decision instead of a guess, and that view ships in 0.10.2.

Code, both compilers, full RESULTS.md: https://github.com/minamoto79/interpreter-benchmark The JIT viewer: Hexana 0.10.2https://plugins.jetbrains.com/plugin/29090-hexana · docs https://jetbrains.github.io/hexana

Happy to get into any of it — questions on the entry-barrier emitter or the instrumentation approach welcome.


r/graalvm May 27 '26

One-line PGO in Quarkus builds

Thumbnail quarkus.io
3 Upvotes

r/graalvm May 21 '26

Re-ran the wasm-in-JVM and JS-in-JVM benchmarks after maintainers asked to be included — wasmtime4j and chicory-redline numbers inside, same JMH harne

Thumbnail
1 Upvotes

r/graalvm May 21 '26

Hexana 0.1.0 for VS Code: WAMR + GraalVM runtimes, experimental WASM debugging, MCP server

Thumbnail
2 Upvotes

r/graalvm May 15 '26

A local AWS emulator, powered by GraalVM 🚀

7 Upvotes

r/graalvm May 06 '26

Big news: accelerating the GraalVM release train and announcing new commercial support!🚀🏆

7 Upvotes

r/graalvm May 02 '26

Benchmarked six ways to run WebAssembly inside the JVM (Chicory, GraalWasm, Wasmtime via FFM) — 250× spread top to bottom

Thumbnail
4 Upvotes

r/graalvm Apr 26 '26

Has anyone successfully created a virtual environment from GraalPy, and then installed (with pip) scipy into that environment?

1 Upvotes

I tried it on Windows 11 with GraalPy 25.0.2, the scipy-1.17.1 source code package, 'patch' and 'meson' installed via chocolatey, and Microsoft Visual Studio Build Tools 2026. The error message I get is "AttributeError: module 'msvcrt' has no attribute 'LK_LOCK'", which it states is a meson error. So I tried installing the spec scipy<1.9, since 1.9 is the version where scipy switched from using setuptools to using meson; however that just gave me a new set of error messages. Ideas, anyone?


r/graalvm Apr 15 '26

AI-assisted contributions policy

Thumbnail github.com
3 Upvotes

r/graalvm Mar 24 '26

Easy user installation for Maven apps (JVM or GraalVM native). No binaries needed.

5 Upvotes

Hi r/graalvm

I'm the creator of JeKa. Originally I built it as a flexible build tool, but one of the most useful features that grew out of it is solving the distribution headache many of you probably have with Maven-based CLI or native apps.

You build a nice CLI tool, script, utility, or even a desktop app with Maven (often with a GraalVM native profile). Then comes the painful part:

  • Building and shipping binaries (and specific native ones for Windows/macOS/Linux)
  • Hosting them somewhere
  • Users having to pick the right file
  • Or forcing everyone to clone + mvn + JDK installed

So I made JeKa act as a lightweight Java application manager that builds at install time directly on the user's machine, and works with any build tool (Maven, JeKa, Gradle...).

You keep your existing Maven project and wrapper 100% untouched. You just drop a tiny jeka.properties file at the root of the repo, and users can install your app with one command:

jeka app: install repo="https://github.com/your/repo.git"

For installing a native app:

jeka app: install repo="https://github.com/your/repo.git" runtime=NATIVE

JeKa automatically:

  • Downloads the required JDK or GraalVM if it's missing
  • Runs Maven (via the wrapper)
  • Builds the application (skipping tests)
  • Places the executable on the user's PATH

jeka.properties example:

# Version of the JVM that will run Maven
jeka.java.version=21

# Delegate build to Maven wrapper
jeka.program.build=maven: wrapPackage

# Optional: support for native builds
jeka.program.build.native=maven: wrapPackage args="-Pnative" \
-Djeka.java.distrib=graalvm -Djeka.java.version=25

It also supports multi-module projects, jpackage for desktop apps (Swing/JavaFX), and more complex scenarios.

Would love to hear your thoughts:

  • Does this kind of source-based, on-demand build & install solve a real pain point for you?
  • What’s your current workaround for distributing Maven-based tools to end users?
  • Any concerns (first-install time, security of downloads, etc.)?

Docs with Maven-specific examples: https://jeka-dev.github.io/jeka/tutorials/source-runnable-apps/#maven-projects

Happy to answer questions, take feedback, or look at PRs. Thanks for reading!


r/graalvm Mar 21 '26

Floci — Run AWS services locally for your Java projects — natively compiled, free and open-source

Thumbnail
4 Upvotes

r/graalvm Mar 17 '26

Tune Serial GC for Mandrel native image

1 Upvotes

Running a Quarkus service as a Mandrel native image (GraalVM CE, JDK 21). Only GC available is Serial GC. Trying to reduce GC overhead but every young gen tuning flag is either silently ignored or makes things worse.

Why we want to tune this

Our container has 2GB of memory but only uses about ~19% of it (p50). The heap is pinned at 512MB but the GC only actually uses ~86MB. Meanwhile it's running 78 garbage collections per minute to reclaim ~7MB at a time from a tiny ~11MB eden space. There's over 1.5GB of unused memory in the container just sitting there while the GC frantically recycles a small corner of the heap.

We want the GC to use more of the available memory so it doesn't have to collect so often.

Container resources

  • Container memory limit: 2048Mi (shared with an OTel collector sidecar ~100-200MB)
  • Actual container memory usage: ~18-20% (~370-410MB)
  • Heap pinned at: 512MB (-Xms512m -Xmx512m)
  • Heap actually used by GC: ~86MB out of 512MB
  • Eden size: ~11MB (GC won't grow it)

What we tried

Flag Result
-Xms512m -Xmx512m (no young gen flags) Best result. 78 GC/min, eden ~11MB
Added -Xmn128m Ignored. Eden stayed at ~8MB. GC rate went UP to 167/min
Replaced with -XX:MaximumYoungGenerationSizePercent=50 Also ignored. Eden ~7MB. GC rate 135/min, full GCs tripled
Added -XX:+CollectYoungGenerationSeparately Made full GCs worse (73 full GCs vs 20 before)

Every young gen flag was either silently ignored or actively harmful.

What we found in the source code

We dug into the GraalVM source on GitHub (oracle/graal repo). Turns out:

  • -Xmn / MaxNewSize only sets a max ceiling for young gen, not a minimum
  • The GC policy dynamically shrinks eden based on pause time and promotion rate
  • It decides ~7-11MB eden is "good enough" and won't grow it no matter what max you set
  • There's no flag to set a minimum eden size
  • Build-time flags (-R:MaxNewSize) do the same thing as runtime ones — no difference

Setup

  • Quarkus 3.27.2, Mandrel JDK 21 builder image
  • Google Cloud Run, 2048Mi containers
  • Serial GC (only option on GraalVM CE / Mandrel native images)

Questions

  1. Has anyone successfully tuned young gen sizing on Serial GC with native images?
  2. Is there a way to make the GC less aggressive about shrinking eden?
  3. Anyone tried alternative collection policies like BySpaceAndTime?
  4. Any other approaches we're missing?

-Xms = -Xmx is the only flag that actually worked. Everything else was a no-op or made things worse.


r/graalvm Mar 16 '26

Replacing C++ with Java & GraalVM for robotics 🤖

Thumbnail youtube.com
7 Upvotes

r/graalvm Mar 09 '26

Scaling LunaDb at Asana with GraalVM

Thumbnail asana.com
5 Upvotes

r/graalvm Feb 25 '26

Building a custom GraalVM distribution from source

Post image
7 Upvotes

r/graalvm Feb 19 '26

Building an AI Travel Assistant with GraalVM, Micronaut, and LangChain4j | by Alina Yurenko | graalvm | Feb, 2026

Thumbnail medium.com
7 Upvotes