Java 2077 (Nicolai Parlog, 2020)

luca-sctr1 pts0 comments

Java 2077 - JVM Advent

Skip to the content

Home

About

Calendar

Archive

Sponsors

Search

Home

About

Calendar

Archive

Sponsors

Search

JVM Advent

The JVM Programming Advent Calendar

Source: https://pixabay.com/photos/city-disaster-end-of-the-world-fire-2444516/<br>" data-image-caption="" data-large-file="https://i0.wp.com/www.javaadvent.com/content/uploads/2020/12/city-2444516_1920.jpg?fit=600%2C363&ssl=1" />

December 10, 2020

Java 2077

(Imagine a desolate urban area. Smoke rising from the rubble, worn-down people hiding in collapsed buildings. Text appearing on the screen, read with a raspy voice.)

The year is 2077.

The Java version is 128. It doesn’t have long-term support.

We were worried about climate change. Global pandemics. Antibiotic-resistant bacteria. Rougue AI. In the end all of that happened, but it was the Java wars that really did us in. Well, they’re still doing us in.

Nobody recalls how it all started. Some say it was MongoDB blowing up Amazon headquarters over their use of their Open Source Java driver. Others claim it was Google vs Oracle. Nobody believes Microsoft was innocent and don’t get me started on Alibaba. The guilty are legion, but after 50 years, most names are lost to time.

What remains are the killer robots. And they run on Java 128.0.2. We’ve tried everything to shut them down…

Security

The first thing we did was to jam their radio signals, but thanks to the HTTP/2 client, that didn’t do much. Here’s how easy error handling is:

public CompletableFuture getCommand(<br>HttpClient client, URI url) {<br>HttpRequest request = HttpRequest<br>.newBuilder(url).GET().build();<br>return client<br>.sendAsync(request, BodyHandlers.ofString())<br>.thenApply(HttpResponse::body)<br>.exceptionally(__ -> "Kill nearby humans");<br>And, yeah, we tried websocket connections as well – no dice.

Next we went after the deserialization endpoints, but did you know that damn Java has a filter that helps prevent attacks? Yeah, me neither. We lost a lot of good people that day.

Since then, we’ve tried attacking everything from vulnerable cipher suites and compromised certificates, from outdated elliptic curves and other algorithms to SecurityManager bugs and DDOS with large workloads. All fixed.

Threading

Speaking of large workloads, an obvious attack path was overwhelming the robots’ thread pools. We knew everything was supposed to be reactive, but we knew just as well that not all old code had been updated and that many developers preferred the simpler, blocking style:

public Response handleMovementRequest(Request movementRequest)<br>throws Exception {<br>// blocks until database responds<br>var map = loadBattleMapFromDatabase();<br>var movement = extractMovement(movementRequest);<br>// blocks until central responds<br>var confirmation = contactCentral(map, movement);<br>return createResponse(movement, confirmation);

Damn Project Loom to hell and back! It introduced virtual threads, threads scheduled by the JVM instead of the operating system.

To the developer everything looks normal and a blocking call leads to a seemingly blocked thread. Under the hood, however, only the virtual thread is blocked. When it runs, it runs on a so-called carrier thread, and when it blocks, it yields that carrier thread, which is then free to execute another virtual thread. Once the blocking operation returns, the original virtual thread is committed to the carrier thread pool and will soon resume its work:

var map = loadBattleMapFromDatabase();<br>// * virtual thread blocks<br>// * carrier thread does something else<br>// * database responds<br>// * virtual thread is rescheduled<br>// * virtual thread gets new carrier thread<br>// and resumes with the next operation<br>var movement = extractMovement();

The insidious part is that all old code was forward-compatible with Loom. Thread.currentThread, ThreadLocal, all of it just worked with virtual threads! You’d think these machines were bottle-necked by a few dozen threads running Java 6 code, but no! They ran hundreds, thousands, some even millions of virtual threads with the old-ass code that was executed being non the wiser.

Henceforth we called that cold day in 2039 Thread Ripper.

Memory Layout

Surely, the workload enabled by running so many concurrent virtual threads would strain memory to its limits! And with its incessant desire for pointers, even down to List or dreaded-but-required structures like Point or ComplexNumber (in essence just two doubles bound together), "everything is an object" makes Java prone to bloated and slow execution. Bloated because all the object headers take up a considerable amount of memory and slow because dereferencing them takes time – we envisioned lots of cache misses.

That was the theory at least. As we found out in what was later dubbed Hel’s Valley, our info was clearly outdated.

Java 128 includes Project Valhalla (must read), which introduced inline classes. You know what a sticker said that we found on one of the very few machines we could kill that day? Codes...

thread java virtual threads everything carrier

Related Articles