Java Downgrade Challenge: From JDK 8 to 1.1 (Part 2)

 

Transcript:

What's up everyone? Welcome back to the series. We are continuing the experiment we started and this time I'm dropping from Java 8 to all the way down to Java 1. It's part history lesson, it's part chaos, but it's all about how Java has evolved over the years. If you're into dev experiments, old school code, or just watching me struggle with ancient compilers, you're in the right place. Let's get started.

Going down to Java 7. I don't want to download new Java. I will just switch the language level in idea. And we can see quite a few errors here. First, there are no more default methods in interfaces. Second, there is no more files read on lines. So I'll have to read my format with scanner and drive resources. And the most important, there are no more stream API and no more lambdas. So I'll have to replace the whole stream with a boring for loop. First I will do it for a person and for sneakers then for named entity then I should handle an exception just in case because there is no more seal classes and also I have to add this login but before there was a lambda and there are no more lambdas in Java. So I will just print a value which is slightly less effective. Now let's run it. Obviously doesn't compile I forgot my semicolons. And now it should run. Yes, executed as expected.

No more lambdas, no more streams. And we are back to anonymous classes and endless loops. No default implementation in interfaces. It's like trying to refactor the ancient codebase where every method is thousand lines long and has no comments. Painful, but technically doable. Well, at least we have a diamond operator. Let's go down to Java 1.6. Surprisingly, there are not so many errors, but we don't have try with resources anymore. We enjoyed it only for one release. Well, now we'll have to rewrite it to do usual try and finally write. And also, there is no more diamond operator. Let's launch it. Works as it was expected.

Forget the diamond decorator. Now you'll need to write full generic types everywhere. No nio, so file handling gets ugly down to Java 1.5, the version I started my career with. There are not so many changes. We just should remove override from interfaces. And I would say it even became a little bit more clear now. And application. Here comes the second big punch. Generics are gone. Welcome back to object class and class cast exception nightmares. The Java we know today is gone. There are no for each loops. There are no enums. There are no annotations. The Java memory model is completely different. So it becomes harder to predict the behavior of the program.

Now we should dive into Java 1.4. And with this change we'll lose everything we are accustomed to. You can see a lot of errors. Let's tackle them Y by Y. First of all, we just lost our scanner. So, we have to replace it with new buffer reader. Now, also there are no more generics. We have to remove them all. Also, there is no more improved for loop. We have to replace it with index for loop. It seems like the most part of the code will left intact. But even here there are small issues. There is no more string format anymore. We have to replace it with like usual string concation. And this is just a tedious work for person then for sneakers and then for named entity which is not generic anymore either. Static inputs do not work anymore. We have to remove them and rewrite. Remove generic mentions anywhere. Replace generic mentions with objects somewhere. Fix some signatures. Now what do we do with lists? Can we just make it a list without generic? No. Arrays as list doesn't work this way. Maybe we can put it into an array of entities. Nope. Doesn't help. Even though it says it should, but it actually looks in the newer GTK. Maybe I should cast everything to entity. Nope. Still doesn't help. Let's create an array and just fill the list because this is how you you are supposed to fill lists in Java 1.4. Set property is not statically imported but now it should work. Let's try and it runs.

These days many developers prefer simple languages and they would actually appreciate Java 4 for its simplicity but of course it's very verbose. Now Java 1.3 what else could we lose right? Let's see. It seems like not that much. Oh there is no more Java login here. What should I do? How will I even work it around? I will be honest with you. I had to generate a code that will replace my custom format with some random bunch of Java code. It is not beautiful anymore. I am just using string concatenation. It potentially can be a function and it will be a complicated one. Essentially, I would have to implement locker on myself. Is it is this all I'm creating date time stamp source I'm putting level hard coding it here there is no throwable on this line so should probably be fine also calling system get property line separator just to put a correct new line here it just says that I can replace it with system line separator but it actually doesn't know that in 1.3 it didn't exist and when I'm running and something is definitely wrong or Right. I forgot to call system out printer land. Now it should be fine and it works more or less as expected.

No login framework. Welcome back to system outprint line and system error print line. If you don't have a logger, you'll have to invent one. Ever wondered why they ask us how hashmap and prework? Well, now you need it because you don't have a collection framework. Yep. No list. No map. You'll be building everything using a race. This is where the pain really sets in. Now, down to Java 1.2. Idea doesn't even support it. As well as Java 1.2 doesn't support modern operating systems. So, I had to actually install Windows 98 emulator on my Mac, which is a whole separate challenge. And if you want, I can share a link to how to do it. It's not that simple actually and I don't have any kind of IDE here. So I will use you Notepad++ which at least has syntax highlighting. I also had to find the Java 1.2 archive to install it. And you can see that installer doesn't even have this famous runs on three billion devices. Luckily it's not a real Windows 98. I shouldn't care really about my disk space. I can install whatever I want because my hard drive on this virtual machine is 10 GB almost unimaginable for those times. Okay. And also now I will have to download my source file because there is no simple way to transfer a source file from host machine to virtual machine. Here is how I do it. I have a small server and I have this Java file installed but I had to fight Windows. I do not use Windows for for a long long time. I don't even use total command anymore. Let me restore my memory. Right now it gets back to me. I should use open with to open my Java file with Notepad++. But at least syntax highlighting looks correctish. I don't need a big window here, but I will also need to start my MS DOS prompt to call Java C and Java when I want to run my executable. And there is no autocomp completion. So I will just drag and drop binaries every time when I want to do something. Suddenly it compiles. Let's try to run it and runs as expected. No exchanges here.

On the most awaited version we go. Drum roll. We are finally at the dawn of Java. No inner classes. No reflection. It's primitive but it's where it all started. Portability the JVM and the right ones run everywhere moto. It's clunky but it's the seat which grew into everything we know and love today. Rolling back through Java versions wasn't just a geeky experiment. It was a time machine. Every feature we lost, lambdas, sealed classes, and IO was added there for a reason. They made code safer, cleaner, and more maintainable. And now the last part, Windows Java 1.1, the last version available at the Oracle website. Installation of it takes quite some time. Even though my current machine is orders of magnitude faster than my real machine with Windows 90s. Luckily, I shouldn't care about my disk space. I can even install sources of Java. I don't know how I will use them, but it should be possible. We don't want to read the RMA file. We want to try to compile my program. Maybe everything will go smooth again, right? Nah, it won't. And I don't even have any error reporting in my Notepad++, only syntax highlighting. So if something is incorrect, it's on me. I have to find it and fix it. I will just read errors one by one from the terminal and we'll try to fix them. There are no more lists, only vectors because there is no more more collection API. So I will have to change all the list invocation to vectors. And there is no nice way to fill a vector from an array. I should just run a loop to do it. Luckily I still remember how to write simple loops. But without any help from ID, it is just a lot of typing you know and no one suggests me what are the functions or methods inside vector. I have to remember them somehow. Here the same thing. There is no more reverse or something like that for collections. I should manually reverse the factor now. You know why they ask you to do it on an interviews, right? Because probably one day you'll have to write in Java 1.1. Gosh, it's so much typing. Even for a simple loop, seems like it should work. Let's test it. I'm still trying to use history, but it's not there. Nope. Yeah, right. It's so tedious to fix the all the errors by hand. And it's so simple to miss a place with an incorrect code. And it's not at element, it's element at. It was such a stupid mistake. Now it compiles. Let's try to run it. Thanks God we are done here.

Here's the real question. Why did we even do it? It's easy to get modern Java for granted. We got used to sealed classes, streams, records, and all the good stuff, but when you strip them away, you realize how far we've come. That's it for today's experiment. If you had fun geeking out with old school Java with me, make sure to like, subscribe, and hit that bell icon so you don't miss what's next. Also, tell me in the comments, what version of Java did you start with? I started with Java 5. We've got more jump throwbacks coming up, so stay tuned and I'll catch you later.

Summary

In this video, the presenter takes viewers on a journey backward through Java versions—from Java 8 all the way to Java 1.1—highlighting the loss of features with each step. As they regress, they deal with the removal of lambdas, streams, generics, enhanced for-loops, annotations, logging frameworks, and even the collections API, revealing how much modern Java has evolved. The experiment becomes a mix of nostalgia, technical struggle, and appreciation for Java’s progress over the decades. It's a fun yet eye-opening reminder not to take today’s powerful Java features for granted.

Social Media

Videos
card image
Apr 2, 2026
Java Memory Options You Need in Production

JVM memory tuning can be tricky. Teams increase -Xmx and assume the problem is solved. Then the app still hits OOM. Because maximum heap size is not the only thing that affects memory footprint. The JVM uses RAM for much more than heap: metaspace, thread stacks, JIT/code cache, direct buffers, and native allocations. That’s why your process can run out of memory while heap still looks “fine”. In this video, we break down how JVM memory actually works and how to control it with a minimal, production-safe set of flags. We cover heap sizing (-Xms, -Xmx), dynamic resizing, direct memory (-XX:MaxDirectMemorySize), and total RAM limits (-XX:MaxRAMPercentage) — especially in containerized environments like Docker and Kubernetes. We also explain GC choices such as G1, ZGC, and Shenandoah, when defaults are enough, and why GC logging (-Xlog:gc*) is mandatory before tuning. Finally, we show how to diagnose failures with heap dumps and OOM hooks. This is not about adding more flags. It’s about understanding what actually consumes memory — and making decisions you can justify in production.

Videos
card image
Mar 26, 2026
Java Developer Roadmap 2026: From Basics to Production

Most Java roadmaps teach tools. This one teaches order — the only thing that actually gets you to production. You don’t need to learn everything. You need to learn the right things, in the right sequence. In this video, we break down a practical Java developer roadmap for 2026 — from syntax and OOP to Spring, databases, testing, and deployment. Structured into 8 levels, it shows how real engineers grow from fundamentals to production-ready systems. We cover what to learn and what to ignore: core Java, collections, streams, build tools, Git, SQL and JDBC before Hibernate, the Spring ecosystem, testing with JUnit, and deployment with Docker and CI/CD. You’ll also understand why most developers get stuck — jumping into frameworks too early, skipping SQL, or treating tools as knowledge. This roadmap gives you a clear path into real-world Java development — with priorities, trade-offs, and production context.

Further watching

Videos
card image
Apr 30, 2026
Java Flight Recorder Tutorial: How to Profile Java Applications

High CPU, GC spikes, or slow startup are common production issues, but logs and metrics don’t always reveal what the JVM is actually doing. Java Flight Recorder (JFR) provides a precise, low-overhead view of JVM behavior, safe for use even in production environments. In this video, you’ll learn how to use JFR to identify real bottlenecks such as CPU hotspots, memory allocation pressure, thread contention, and I/O stalls. We walk through the full workflow, including starting recordings with JVM flags, controlling them via jcmd, running JFR inside Docker containers, and attaching to live systems using ephemeral containers. Then we analyze a real Spring Boot recording in JDK Mission Control, breaking down GC behavior, allocation patterns, thread states, and method-level hotspots. If you want to move from symptoms to root cause with more confidence, this approach will help. Full article with commands and examples: [https://bell-sw.com/blog/how-to-profile-java-applications-with-jfr-beginner-s-guide/](https://bell-sw.com/blog/how-to-profile-java-applications-with-jfr-beginner-s-guide/)

Videos
card image
Apr 22, 2026
Dynamic SQL Queries with Spring Data JPA in 6 Minutes

If your repository layer has multiple queries for different filter combinations, your data access logic is already getting harder to maintain. In this video, we implement dynamic SQL queries in Spring Data JPA using Specifications — a composable approach that helps avoid query duplication and keeps your filtering logic clean. We build a flexible filtering system with optional parameters (category, language, format, price) and show how Specification.unrestricted() skips empty filters, while Specification.allOf(...) combines them into a single query. We also address a common issue: string-based field access. It’s fragile and can break at runtime when your model changes. Using the JPA Static Metamodel, we move to compile-time safety. The result is a cleaner, more maintainable way to implement dynamic filtering in Spring-based applications.

Videos
card image
Apr 8, 2026
Best Oracle Java Alternatives in 2026 Comparison of OpenJDK Distributions

A comparison of major OpenJDK distributions (Temurin, Liberica, Zulu, Corretto, Semeru, etc.), covering who maintains them, how updates are delivered, and what lifecycle guarantees they provide. We also explain why upstream OpenJDK isn’t production-ready and how your vendor choice impacts real-world systems. Useful for Spring Boot, containers, and Kubernetes to avoid hidden risks and choose the right runtime.