Architecture
How does CheerpJ work?
CheerpJ is a Java Virtual Machine and a full build of OpenJDK for the browser, implemented in WebAssembly and JavaScript. It runs Java applications in the browser tab, with no Java installation, plug-in or server-side component. This page explains how.
Overview
CheerpJ runs in any modern browser using standard web technologies: WebAssembly, JavaScript and HTML. A page loads it like any JavaScript library, with one <script> tag.
CheerpJ has a JavaScript API to run standalone Java applications, applets, Java Web Start applications and Java libraries in the browser. It works on compiled Java bytecode, so it needs the application’s JARs, not its source code, and runs them unmodified.
CheerpJ is a set of static files. Load it from the CheerpJ CDN, which the free Community licence covers, or serve it from your own web server or CDN, with no connection to any external server. See licensing for when self-hosting needs a licence.
CheerpJ components
CheerpJ provides a Java runtime and the operating-system services a Java application expects, built on browser APIs:
- A Java runtime: a JVM, with an interpreter and a JIT compiler, and the full OpenJDK class library of each supported Java version
- A window manager, which draws AWT and Swing windows in the page
- Virtual file systems, on your web server, in browser storage and in memory
- Networking, over the browser’s own HTTP stack, and over Tailscale for TCP and UDP

The Java runtime
The CheerpJ JVM is written in C++ and compiled to WebAssembly and JavaScript with Cheerp, Leaning Technologies’ C++ compiler for the web. Each supported Java version ships with its own full build of OpenJDK: Java 8, 11, 17 and 21, with Java 25 in preview. OpenJDK’s own native code is compiled to WebAssembly, so the Java class library behaves as it does on the desktop. You choose the version with the
version option when CheerpJ starts.
The JVM runs bytecode in two tiers:
- Bytecode starts in an interpreter, which also counts how often each part of the code runs.
- Code that runs often is compiled to JavaScript by a JIT compiler while the application runs. The browser’s JavaScript engine then runs the result.
The JIT inlines and devirtualises calls, which matters for a language such as Java, where most calls are virtual. Bytecode is not compiled ahead of time, and no part of CheerpJ runs on a server.

A few properties of the runtime follow from running in the browser:
- Memory: Java objects are ordinary JavaScript objects, garbage-collected by the browser. Weak references and finalizers use the browser’s own mechanisms. CheerpJ 5.0 also has an experimental engine based on WebAssembly garbage collection, enabled with the
wasmGCoption. - Threads: Java threads are scheduled by CheerpJ and take turns on one browser thread: the page’s own, or a Web Worker’s when CheerpJ is started in one.
- Native code: the application’s native methods can be implemented in JavaScript or compiled to WebAssembly, and grouped in native libraries loaded with
System.loadLibrary. Pre-built binaries, such as.dlland.sofiles, cannot run in a browser.
The runtime also connects Java and JavaScript in both directions. Java code reaches JavaScript and the DOM through native methods implemented in JavaScript. JavaScript uses Java classes, objects and arrays directly in library mode, started with cheerpjRunLibrary.
The window manager
CheerpJ’s window manager draws AWT and Swing interfaces in the page. Each window is an HTML element with its own canvas, and frames and dialogs get an HTML title bar. cheerpjCreateDisplay places the display inside any element of the page.
Swing applications render as they do on the desktop, including with third-party look and feels. Multiple windows and keyboard focus work as on the desktop. The clipboard is internal to the application by default, and can be shared with the system clipboard with the clipboardMode option.
The virtual file systems
The browser does not let web pages read or write the user’s files directly, so CheerpJ gives the application virtual file systems instead: /app/ for files on your web server, read over HTTP; /files/ for persistent storage in the browser; and /str/ for data passed in from JavaScript. Local files enter the application as uploads and leave it as downloads.

Networking
Java’s HTTP and HTTPS connections are made with the browser’s fetch, so the same-origin policy and CORS apply. Services on another domain must allow cross-origin requests from the page.
Browsers do not give web pages TCP or UDP sockets. CheerpJ provides them through Tailscale, a VPN based on WireGuard that carries traffic over WebSockets. Tailscale supports many networking scenarios, including access to services on a private network, peer-to-peer connections between users, and access to the internet through an exit node that the user or the application provides. The Tailscale control server can be self-hosted, with Headscale.

Learn more
- How CheerpJ works
on cheerpj.com, for an overview of the runtime and its deployment
- Compatibility
, for what is supported in detail
- Security
, for the security model of CheerpJ deployments