Skip to content

Commit 9cba51d

Browse files
authored
CJ4.1 post (#260)
1 parent 3b30931 commit 9cba51d

32 files changed

+326
-41
lines changed

content/blog/CJ-4-1.mdx

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
---
2+
title: "CheerpJ 4.1: Java in the browser, now supporting Java 17 (preview)"
3+
slug: cheerpj-4.1
4+
description: |
5+
The latest release of our state-of-the-art Java runtime that runs completely in the browser via WebAssembly, is now available. Supports up to Java 17.
6+
authors:
7+
- alessandro
8+
- stefano
9+
pubDate: "May 28 2025"
10+
heroImage: "./CJ4-1-hero.png"
11+
featured: true
12+
tags:
13+
- CheerpJ
14+
---
15+
16+
import Icon from "astro-icon";
17+
import LinkButton from "@leaningtech/astro-theme/components/LinkButton.astro";
18+
import { DISCORD_URL } from "@/consts.ts";
19+
20+
Around a month ago we announced [CheerpJ 4.0](https://labs.leaningtech.com/blog/cheerpj-4.0), the first release of our WebAssembly-based JVM with support for multiple versions of Java.
21+
22+
<div class="flex items-center gap-2 flex-wrap">
23+
<LinkButton
24+
type="primary"
25+
href="https://cheerpj.com/docs/getting-started"
26+
target="_blank"
27+
label="Get started"
28+
iconRight="mi:arrow-right"
29+
/>
30+
<LinkButton
31+
type="discord"
32+
href={DISCORD_URL}
33+
target="_blank"
34+
iconLeft="fa-brands:discord"
35+
label="Join us on Discord"
36+
/>
37+
</div>
38+
39+
The release of CheerpJ 4.0 was focused on getting the infrastructure right, maintaining our long standing Java 8 support while introducing Java 11, and allowing further versions of Java to be supported.
40+
41+
As stated in our [roadmap](https://cheerpj.com/our-roadmap-for-modern-java-in-the-browser/), our plan was to introduce Java 17 support only later in the year. Thanks to faster than expected progress, we are now releasing this feature today, much earlier than we expected, as part of **CheerpJ 4.1**. This is intended to be a preview of the stable support that is still scheduled for a future CheerpJ 5.0 release, expected before the end of 2025.
42+
43+
Moreover, the initial support for Java 11 in the previous release received extensive testing by the developer community on a big variety of applications and libraries. Thanks to the help of our users, several critical bugs in the original release were found and fixed. This new 4.1 release also serves as an opportunity to bring much more stability to Java 11 support.
44+
45+
## What is new?
46+
47+
<figure class="w-full">
48+
![Runeline screenshot](./Runelite.png)
49+
<figcaption class="text-center">
50+
RuneLite running in the browser via CheerpJ in Java 11 mode
51+
</figcaption>
52+
</figure>
53+
54+
Although not long has passed since the previous release, there are already many improvements in CheerpJ, across different subsystems.
55+
56+
CheerpJ 4.1 introduces:
57+
58+
- Support for SSL and Audio in Java 11
59+
- Performance optimizations
60+
- Improved networking stack
61+
- Improvements to mobile usability, for both Swing and AWT
62+
- Preview of Java 17 support
63+
64+
Feedback and testing from the community have been invaluable to help us improve the stability of CheerpJ. We expect that Java 17 will attract even more attention, resulting in a positive feedback loop that will bring CheerpJ ever closer to our vision of running modern Java in the browser.
65+
66+
## What can CheerpJ do?
67+
68+
CheerpJ is a full WebAssembly-based JVM for the browser, and comes with a complete OpenJDK runtime, as well as a powerful emulation layer to provide file system access, general networking support and other OS-level features. It works fully client-side, via WebAssembly, JavaScript and HTML5 technologies. It is, in essence, a JavaScript library, with no server-side or cloud-based component of any sort.
69+
70+
CheerpJ is a complete, flexible Java platform for modern browsers. It is an extremely powerful tool, designed and tested to work at the scale of real-world, large enterprise applications. Here is an overview of what CheerpJ can be used for.
71+
72+
### Running large-scale Swing / AWT applications
73+
74+
CheerpJ can run existing, full Java applications from unmodified JARs, with no recompilation or pre-processing, straight from bytecode. Obfuscated or encrypted JARs are supported irrespective of the obfuscator being used.
75+
76+
<figure class="w-full aspect-square">
77+
<div id="demodiv" class="w-full aspect-square relative">
78+
<iframe
79+
class="absolute w-full h-full focus:outline-none"
80+
src="https://cheerpj-example-swingset3.leaningtech.com/"
81+
></iframe>
82+
<div id="demofullscreen">
83+
<Icon
84+
class="absolute right-0 bottom-0 w-8 h-8 m-1 text-stone-900 cursor-pointer"
85+
name="fa-solid:expand"
86+
/>
87+
<Icon
88+
class="absolute right-0 bottom-0 w-8 h-8 m-1 text-stone-900 cursor-pointer animate-ping opacity-50"
89+
style="animation-duration: 3s; "
90+
name="fa-solid:expand"
91+
/>
92+
</div>
93+
<div id="demonormal" class="hidden">
94+
<Icon
95+
class="absolute right-0 bottom-0 w-8 h-8 m-1 text-stone-900 cursor-pointer"
96+
name="fa-solid:compress-arrows-alt"
97+
/>
98+
</div>
99+
</div>
100+
<figcaption class="text-center">
101+
A complex Swing application running live. Use the bottom-right control
102+
button to try it fullscreen.
103+
</figcaption>
104+
</figure>
105+
106+
<script>{`
107+
var demoDiv = document.getElementById("demodiv");
108+
var demoFullscreen = document.getElementById("demofullscreen");
109+
var demoNormal = document.getElementById("demonormal");
110+
demoFullscreen.onclick = function()
111+
{
112+
demoDiv.requestFullscreen();
113+
};
114+
demoNormal.onclick = function()
115+
{
116+
document.exitFullscreen();
117+
};
118+
demoDiv.onfullscreenchange = function()
119+
{
120+
if(document.fullscreenElement)
121+
{
122+
demoNormal.classList.remove("hidden");
123+
demoFullscreen.classList.add("hidden");
124+
}
125+
else
126+
{
127+
demoFullscreen.classList.remove("hidden");
128+
demoNormal.classList.add("hidden");
129+
}
130+
};
131+
`}</script>
132+
133+
Both AWT- and Swing-based applications are supported, including third-party Swing Look&Feels. Multiple applications, each with multiple windows, can run at the same time on the same page.
134+
135+
CheerpJ 4.1 introduces an unprecedented level of support for mobile devices, enabling for the first time to make complex Java applications available to users across phones and, especially, tablets.
136+
137+
Running a Java application is straightforward, requiring just three calls to the CheerpJ APIs (see our [Getting Started](https://cheerpj.com/docs/getting-started/Java-app) guide for a fully worked example).
138+
139+
```js
140+
await cheerpjInit();
141+
cheerpjCreateDisplay(800, 600);
142+
await cheerpjRunJar("/app/my_application_archive.jar");
143+
```
144+
145+
CheerpJ is built to run Java bytecode at scale, and is robust to very large applications. As a point of reference, our internal stress test is IntelliJ IDEA, an application comprising around 400MB of JAR files.
146+
147+
<video controls autoplay loop muted playsinline>
148+
<source src="./CJ_idea19_2025.mp4" type="video/mp4" />
149+
</video>
150+
151+
### Using Java libraries as part of Web Applications
152+
153+
CheerpJ makes it possible to use Java libraries from JavaScript using a natural and expressive `async`/`await` based approach, we call this feature _Library Mode_.
154+
155+
The following snippet of code should give an idea about this capability, by using the popular `iText` library to generate a PDF completely client-side in the browser.
156+
157+
```js
158+
async function iTextExample() {
159+
await cheerpjInit();
160+
const lib = await cheerpjRunLibrary("/app/itextpdf-5.5.13.3.jar");
161+
try {
162+
const Document = await lib.com.itextpdf.text.Document;
163+
const Paragraph = await lib.com.itextpdf.text.Paragraph;
164+
const PdfWriter = await lib.com.itextpdf.text.pdf.PdfWriter;
165+
const FileOutputStream = await lib.java.io.FileOutputStream;
166+
const document = await new Document();
167+
const writer = await PdfWriter.getInstance(
168+
document,
169+
await new FileOutputStream("/files/HelloIText.pdf")
170+
);
171+
await document.open();
172+
await document.add(await new Paragraph("Hello World!"));
173+
await document.close();
174+
await writer.close();
175+
const blob = await cjFileBlob("/files/HelloIText.pdf");
176+
const url = URL.createObjectURL(blob);
177+
pdfDisplay.data = url;
178+
} catch (e) {
179+
const IOException = await lib.java.io.IOException;
180+
if (e instanceof IOException) console.log("I/O error");
181+
else console.log("Unknown error: " + (await e.getMessage()));
182+
}
183+
}
184+
```
185+
186+
_Library Mode_ provides extensive access to Java, with these main features:
187+
188+
- Creating new objects
189+
- Calling static and instance methods. Overloading is supported and the correct method is resolved taking into account the argument types.
190+
- Accessing static and instance fields, both for reading and for writing.
191+
- Handling Java exceptions from JavaScript (via regular `try`/`catch` blocks)
192+
193+
_Library Mode_ is a unique feature, which makes it possible to build a new generation of fully client-side Web applications that combine Web-native components with Java libraries to implement complex functionalities.
194+
195+
In more enterprise scenarios, this approach can be used to progressively migrate large-scale Java applications to native Web apps, by rewriting the UI while keeping all or part of the original business logic in Java. This can provide significant reduction of risk, costs, and timeline to large modernisation projects.
196+
197+
Check out our dedicated documentation for more information on [Library Mode](https://cheerpj.com/docs/getting-started/Java-library)
198+
199+
## Demo: Unmodified Minecraft in the browser
200+
201+
<video controls autoplay loop muted playsinline>
202+
<source src="./browsercraft4.mp4" type="video/mp4" />
203+
</video>
204+
205+
To showcase the capabilities of CheerpJ, we created a side project named [Browsercraft](https://browsercraft.cheerpj.com/), a web-based “embedding” of a historical Java version of Minecraft.
206+
207+
Contrary to other approaches you might have seen, Browsercraft is not based on decompilation or reverse engineering attempts. The original `client.jar` is fetched directly from Mojang servers on the end-user browser and runs unmodified. The LWJGL dependency, available from Maven, is also unmodified.
208+
209+
How LWJGL works in CheerpJ is particularly interesting, since it is only _superficially_ Java. Most of its value comes from JNI methods which provide direct access to each and every method exposed by OpenGL. These methods are written in C and automatically generated by the LWJGL build system from a declarative representation of the OpenGL API.
210+
211+
CheerpJ 4.1 introduces support for these scenarios via JNI WebAssembly modules, which are loaded and executed dynamically, similarly to what happens on native platforms via shared libraries. Browsercraft takes advantage of this capability for LWJGL native code and also for the [gl4es](https://github.com/ptitSeb/gl4es/) library. This latter component provides a compatibility layer between OpenGL, used by Minecraft, and GLES as provided by WebGL.
212+
213+
By combining these WebAssembly modules and the unmodified JARs, CheerpJ can now correctly render Minecraft in the browser. It should be noted that Minecraft is a notoriously inefficient and resource intensive application, so we consider it to be a _stress test_ for CheerpJ. Nevertheless, thanks to recent improvements in our JIT compiler, the demo can now run with satisfactory performance on most mid range machines. The situation will further improve in the future thanks to more advanced optimizations currently planned, stay tuned.
214+
215+
## What’s next?
216+
217+
Development of CheerpJ is moving fast. The CheerpJ 5.0 release is still scheduled for later in the year as originally announced in our [roadmap](https://cheerpj.com/our-roadmap-for-modern-java-in-the-browser/).
218+
219+
There is a long list of improvements that we plan to ship, here are as few highlights:
220+
221+
- **Stable Java 17 support**: With CheerpJ 4.1 we have released a preview of what Java 17 support will look like in the not so distant future, we plan to gather feedback from users to achieve a high level of stability by the time CheerpJ 5.0 is released.
222+
- **NPM support**: CheerpJ has been historically used primarily to run legacy Java applications, most usually in environments that pre-date the npm ecosystem. Now that CheerpJ can run modern Java we want to provide a npm-native CheerpJ version, to streamline integration into modern projects.
223+
- **Extend native JNI modules support**: This will allow us to support JavaFX, SWT and eventually allow users to build their own Wasm JNI module for any Java library.
224+
225+
## Licensing
226+
227+
CheerpJ is commercial software, but it’s free to use for FOSS projects, personal projects and one-person companies. Affordable and transparent licensing apply to small businesses.
228+
229+
Enterprise licensing and support are available, with significant discounts for non-profit and educational institutions. For more information see [Licensing](https://cheerpj.com/cheerpj-core/#compare-plans).
230+
231+
## Try it out and join the community
232+
233+
You can find a lot of beginner-friendly resources in our developer documentation, as well as tutorials and a full API reference.
234+
235+
<div class="flex items-center gap-2 flex-wrap">
236+
<LinkButton
237+
type="primary"
238+
href="https://cheerpj.com/docs/getting-started"
239+
target="_blank"
240+
label="Get started"
241+
iconRight="mi:arrow-right"
242+
/>
243+
</div>
244+
245+
For questions, discussion, and support, join our [Discord](https://discord.leaningtech.com). It’s an active community where both Leaning Technologies developers and experienced users can provide help.
246+
247+
Following the success of the second edition of the [WebVM Hackathon](https://cheerpx.io/hackathon) earlier this year, we have decided to host the first [CheerpJ Hackathon](https://cheerpj-the-hackathon.devpost.com). The event theme and precise dates are still being determined, but it will be a week-long competition to be held between September and October 2025, with a £500 prize awaiting the winning team. [Sign up now](https://cheerpj-the-hackathon.devpost.com) to stay updated.
248+
249+
---
250+
251+
CheerpJ is a product built with passion and a lot of coffee by Leaning Technologies, an international team of WebAssembly hackers based in Amsterdam (NL) and Leeds (UK). We hope you’ll love it as much as we do.
252+
253+
<LinkButton
254+
href="https://github.com/leaningtech/cheerpj-meta"
255+
target="_blank"
256+
type="secondary"
257+
label="Star CheerpJ on GitHub"
258+
iconLeft="fa:star"
259+
/>

content/blog/CJ4-1-hero.png

856 KB
Loading

content/blog/Runelite.png

417 KB
Loading

packages/astro-theme/components/ProductVersionSwitcher.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const { product } = Astro.props;
1414
class="px-2 py-1 rounded bg-transparent text-stone-400 font-medium"
1515
id="version-switcher"
1616
>
17-
<option value="cheerpj3" selected={product.id === "cheerpj3"}>v4.0</option>
17+
<option value="cheerpj3" selected={product.id === "cheerpj3"}>v4.1</option>
1818
<option value="cheerpj2" selected={product.id === "cheerpj2"}>v2.3</option>
1919
</select>
2020
</div>

sites/cheerpj/src/content/docs/00-overview.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ import AppletRunnerButton from "@leaningtech/astro-theme/components/AppletRunner
4444
</div>
4545

4646
```html
47-
<script src="https://cjrtnc.leaningtech.com/4.0/loader.js"></script>
47+
<script src="https://cjrtnc.leaningtech.com/4.1/loader.js"></script>
4848
```
4949

5050
<div class="mx-24">![](./explanation-diagram.png)</div>

sites/cheerpj/src/content/docs/10-getting-started/00-Java-app.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Let's create a basic HTML file like the following example. Please notice the Che
3333
<head>
3434
<meta charset="utf-8" />
3535
<title>CheerpJ test</title>
36-
<script src="https://cjrtnc.leaningtech.com/4.0/loader.js"></script>
36+
<script src="https://cjrtnc.leaningtech.com/4.1/loader.js"></script>
3737
</head>
3838
<body>
3939
<script>

sites/cheerpj/src/content/docs/10-getting-started/01-Java-applet.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ In order to integrate CheerpJ, you just need to add:
3838
1. A simple `<script>` within the `<head>` of your page with the CheerpJ runtime loader.
3939

4040
```html
41-
<script src="https://cjrtnc.leaningtech.com/4.0/loader.js"></script>
41+
<script src="https://cjrtnc.leaningtech.com/4.1/loader.js"></script>
4242
```
4343

4444
2. A second script calling [`cheerpjInit()`] to initialize CheerpJ's runtime environment.
@@ -57,7 +57,7 @@ For example:
5757
<head>
5858
<meta charset="utf-8" />
5959
<title>CheerpJ applet test</title>
60-
<script src="https://cjrtnc.leaningtech.com/4.0/loader.js"></script>
60+
<script src="https://cjrtnc.leaningtech.com/4.1/loader.js"></script>
6161
</head>
6262
<body>
6363
<applet

sites/cheerpj/src/content/docs/10-getting-started/02-Java-library.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ description: Use Java classes in JavaScript
66
## 1. Include CheerpJ on your page
77

88
```html
9-
<script src="https://cjrtnc.leaningtech.com/4.0/loader.js"></script>
9+
<script src="https://cjrtnc.leaningtech.com/4.1/loader.js"></script>
1010
```
1111

1212
## 2. Initialize CheerpJ and load your Java library

sites/cheerpj/src/content/docs/10-getting-started/03-JNLP.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ Example of an HTML file for an app where the class name is included in the manif
118118
<head>
119119
<meta charset="utf-8" />
120120
<title>CheerpJ test</title>
121-
<script src="https://cjrtnc.leaningtech.com/4.0/loader.js"></script>
121+
<script src="https://cjrtnc.leaningtech.com/4.1/loader.js"></script>
122122
</head>
123123
<body>
124124
<script>
@@ -164,7 +164,7 @@ The HTML for an applet would look like this:
164164
<head>
165165
<meta charset="utf-8" />
166166
<title>CheerpJ applet test</title>
167-
<script src="https://cjrtnc.leaningtech.com/4.0/loader.js"></script>
167+
<script src="https://cjrtnc.leaningtech.com/4.1/loader.js"></script>
168168
</head>
169169
<body>
170170
<applet

sites/cheerpj/src/content/docs/11-guides/cheerpj-debug.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ The reason your application isn't working could be quite simple. Try these check
1414
- You integrated CheerpJ into your web page by adding a `<script>` tag like this:
1515

1616
```html
17-
<script src="https://cjrtnc.leaningtech.com/4.0/loader.js"></script>
17+
<script src="https://cjrtnc.leaningtech.com/4.1/loader.js"></script>
1818
```
1919

2020
- The location of your JARs is correct and the prefix `/app/` is added when passing it to [`cheerpjRunJar`] or [`cheerpjRunMain`]. For more information visit the [virtual filesystem] guide.

sites/cheerpj/src/content/docs/11-guides/implementing-native-libraries.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ export default {
117117
<html>
118118
<head>
119119
<title>Native Method Example</title>
120-
<script src="https://cjrtnc.leaningtech.com/4.0/loader.js"></script>
120+
<script src="https://cjrtnc.leaningtech.com/4.1/loader.js"></script>
121121
</head>
122122
<body>
123123
<script>

sites/cheerpj/src/content/docs/11-guides/implementing-native-methods.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ Here, we provide an implementation for the `nativeAlert` method in the `Example`
145145
<html>
146146
<head>
147147
<title>Native Method Example</title>
148-
<script src="https://cjrtnc.leaningtech.com/4.0/loader.js"></script>
148+
<script src="https://cjrtnc.leaningtech.com/4.1/loader.js"></script>
149149
</head>
150150
<body>
151151
<script>

sites/cheerpj/src/content/docs/13-tutorials/00-swingset3.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Visit the URL shown in the terminal and you should see a blank page. Leave Vite
4747
Let's add CheerpJ to the page by adding this script tag to the `<head>`:
4848

4949
```html title="index.html"
50-
<script src="https://cjrtnc.leaningtech.com/4.0/loader.js"></script>
50+
<script src="https://cjrtnc.leaningtech.com/4.1/loader.js"></script>
5151
```
5252

5353
## 3. Initialise CheerpJ and run the jar

sites/cheerpj/src/content/docs/13-tutorials/01-applet.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ Your document will look like this:
129129
<head>
130130
<meta charset="utf-8" />
131131
<title>FoilSim applet (CheerpJ)</title>
132-
<script src="https://cjrtnc.leaningtech.com/4.0/loader.js"></script>
132+
<script src="https://cjrtnc.leaningtech.com/4.1/loader.js"></script>
133133
</head>
134134
<style>
135135
div {

0 commit comments

Comments
 (0)