Downgraded Java to JDK 1.1 After 30 Years… (part 1)

 

Transcript:

Hey, welcome back. In the last episode, we explored evolution of Java and its legacy. But here's the kicker. What if we reverse engineer it and focus on dee evolution of Java? What if we take modern Java with all the nice features like sealed classes, text blocks, button matching, and try to force it back to the raw unfiltered world of Java 1.0. In this episode, I will show you what exactly breaks, when it breaks, and what I had to do to fix it. Spoiler, I had to fight Java on each and every step of this journey. So, grab your coffee and let's dive into this mess together.

Let's kick things off with Java 23. It's packed with cool features, but start stepping backwards and cracks starts growing fast. Let's start from our project. It contains only one class example. This class contains logo and this logo comes from Jav login package. We have this nice markdown comment with a snippet inside it giving an example of usage of our class and the class is called entity. It's an interface with one private and one public method. It has one record implementing it also with a nice Java  comment couple of fields. We also have this static sealed class named entity which implements entity and it permits only one subclass called sneakers. Let's also generate some Java docs and look at them. Here you can see that we have our nice formatting. We have snippets. We can copy snippets and so on. We have everything we need in our documentation like at least everything we wrote. Let's delete it for now. And now it's time for first downgrade. Let's downgrade our Java to version 22. Even at this level, we are losing our markdown Java do rendering. And we all like markdown and it's a little bit annoying, but it's only a hint of what's to come.

Now we can regenerate our Java docs and open newly generated Java docs and you can see that there are no more descriptions. All the documentation is lost because at this point we have lost our markdown comments. Now the code doesn't compile at all. The handy underscore convention for unused parameters is gone. I will use Liberica 21. As we can see there is only one thing broken. There are no more underscore arguments and there is no quick fix to fix it. So we will have to give it an explicit name of ignored. After that our application should work again. Let's launch it. And it works. Java 20. Boom. The button maring with switch just stops working. Suddenly we are back to good old ethos chains and we lose those nice compile time exhaustiveness checks.

Now we see quite a few things broken. First get first is not available. This is easy to fix. It's get zero. Now there are no more reverse collections. So we will have to somehow work it around. We can try to call collections reverse like this. But it won't work because reverse doesn't return a new collection. It returns void. So you will have to create a new collection something like entities equals new array list of entities but it won't work either because entities is already used in our class variable. So we'll call it local entities. Now we need to collection reverse this local entities and it still doesn't compile because switch doesn't work this way anymore in Java 20. We can try to remove arguments but even like this switch won't work. So we'll have to actually write our switch to if statement. Okay, seems to be working. Sequence collections, forget them.

No reverse collections, no get first, no get last. We are on our own. On the bright side, this is where your knowledge of how to reverse the linked list comes in handy. Now, for some versions, there were no significant changes. We see that when we downgrade to Java 19, nothing interesting happens. Nothing changes. Step back just a little bit and sealed classes vanish. Did you seal your class hierarchy? Now, it's unsealed like in good old times. So downgrading to Java 17, the code compiles, but we have this snippet tag and we see that it's not available anymore. So we will have to actually rewrite it to pre-tag. Now it's pure HTML, almost pure. The rest of the document looks okay. Let's change our Java 217. Oh no, now the naming is different too. I'll have to find the correct version of Java here. 17 or 15 like this. Now let's generate our Java docs. They are fine. They seem to be working. Downgrade to Java 16 should be pretty straightforward. I do not change JDK anymore. I just change the expected source language in my idea. What we see now is sealed do not work because sealed classes do not exist in Java 16. It also means we can remove this warning and this sealed class too. And now the application should hopefully work. I do not see any more errors. Yep. Works as expected. Oh, and say goodbye to records.

Now you have to write full-blown classes with equals hash code to string getters settles and all the other stuff. Remember how convenient were text blocks for multi-line strings? Not anymore. They were introduced in Java 15. So stretch those fingers for new line sequence. Downgrading to Java 15 should be a little bit more involved. Records do not exist anymore. What? Well, now it's just a static class and we should move all the arguments to an actual constructor, not a record constructor. Idea helps us a little bit to create fields. And now since there are no records, we actually have to replace our nice record deconstruction to an actual casting. Oops, it won't compile. B doesn't exist. We should use E, which stands for entity. Same for sneakers. Gosh, it's a lot of boiler plate. Same for named entity. I'm so much accustomed to this nice structuring, so I just can't wrap my head around the correct way to write it. Now, hopefully it should work. Let's launch it. Yep. It's funny how you don't realize how much you rely on these features until they're gone. It's like losing a comfy pair of shoes. You only notice when you start walking barefoot on Gredle. Huh?

Now we are walking into the awkward teenage years of Java. Text blocks are not available now. Now let's go to Java 14. Text blocks are gone. Well, it should be easy to fix even though slightly annoying. Obviously now selection doesn't even work correctly because it's incorrect language level. ATS still helps us quite a bit. Launching it works now doing raising from Java 14 straight to Java 10. There were no many changes here. The only thing breaking is var as a lambda argument. And now it works. It's not the end of the world but everything became slightly uglier again. NPEs or not pointer exceptions became nested. Writing Java applications with just Java command. Nope. Gone too. Remember using var? Say goodbye to that. And now downgrading straight to Java 8. Changing the actual JDK at this point just to be sure. Let's see what breaks. Indexing takes some time. What? Nothing broke. It is interesting. Well, no. I actually see this one error. A list of off doesn't exist anymore. The only thing we can do, well, there are multiple things, but we probably want to call erase.slist. Its only downside, the list is not immutable anymore.

And now I see things breaking, right? B doesn't exist in Java 8. Well, we'll have to fix it. And I actually do not remember my types. This one is list of entities. That's for sure. Oh no, there are no private methods in interfaces anymore. I will have to hardcode the type function. Put everything from it inside the public method, the default method. Now, what else? Yeah, right. It takes some time to realize that get zero actually returns not list of strings but just string, right? It's kind of obvious. Let's launch it. Let's launch it. And it works. Now you have to write every single type probably twice. A list of and set off gone. Private methods in interfaces also gone. You'll have to either expose them publicly or stuff everything into default methods. And that's a wrap for now. In the next episode, I interviewed developers at Spring.io. Come join the community and be a part of the conversation.

And after that, stay tuned as we go all the way down to Jaw One exploring how it all started. Trust me, you don't want to miss what's ahead. If you made it this far, do me a quick favor. Smash that subscribe button and ring the bell so you don't miss what's next. See you next time, folks.

Summary

In this video, we reverse-engineer Java by downgrading a modern Java 23 project step by step down to Java 8. Along the way, we lose key features like sealed classes, records, pattern matching, text blocks, and even basic conveniences like var and List.of(). Each downgrade shows how much cleaner and more powerful modern Java has become—and how painful it is to go back. It’s a crash course in Java’s evolution, told through broken builds and growing boilerplate.

Social Media

Videos
card image
Jun 18, 2025
Java DTO Guide: Fix Your API Design with One Simple Pattern

This tutorial shows how to use the Data Transfer Object (DTO) pattern to transfer data between application layers. We use Java records to reduce boilerplate code and the MapStruct library that simplifies Java bean mapping.

Videos
card image
Apr 25, 2025
Java in 2025: Busting the Biggest Myths

Think Java is slow, outdated, or only for old-school enterprise apps? Think again. In this episode of Java Myth Busters, we debunk six common myths about Java, including performance issues, security concerns, and the myth that Java is dead. Discover how the JVM, Spring Boot, GraalVM, and modern JDK updates make Java one of the most powerful, scalable, and relevant languages in 2025.

Further watching

Videos
card image
Jul 15, 2025
Java Downgrade Challenge: From JDK 8 to 1.1 (Part 2)

In Part 2 of the Java Downgrade Challenge, we continue our journey — now from Java 8 all the way to Java 1.1. No streams, no lambdas, no generics, no collections — and at one point, we even boot up Windows 98. If you thought Part 1 was painful, this one unwinds Java history line by line. By the end, the familiar Java from today will be almost gone.

Videos
card image
Jun 27, 2025
5x Smaller Java Docker Images — 2025 Optimization Guide

In this video, I’ll show you how to make your Java Docker images 5 TIMES SMALLER. You’ll see the full process, from a heavy 587MB container to a lean 116MB image, ready for production.

Videos
card image
Jun 23, 2025
How to install Liberica Native Image Kit on Windows PC

Liberica Native Image Kit is a multilingual GraalVM-based set of utilities for creating native images. This guide will help you to install it on Windows PC.