DEV Community

Cover image for What I learned while building a Linux-native Java runtime
Naman Jain
Naman Jain

Posted on • Originally published at blogs.namanoncode.me

What I learned while building a Linux-native Java runtime

Building my own runtime taught me how modern event-driven systems actually work under the hood. Here are the five biggest lessons I learned about CPU usage, kernel APIs, and performance benchmarking.

Building zThread taught me far more about Linux and the JVM than I expected.

When I started this project, my goal wasn't to replace Netty or Project Reactor. I wanted to understand how modern event-driven systems actually work under the hood. (This same curiosity eventually led to building ReactiveChainDB v2 to bypass CPU limitations entirely.)

After months of reading Linux documentation, JVM internals, NGINX, Netty, and implementing my own runtime, here are the five biggest lessons.

1. "Zero CPU" doesn't exist

When I first learned about NGINX and epoll, I kept hearing:

"NGINX uses almost no CPU while waiting."

I interpreted that as zero CPU.

That's not actually true.

What's really happening is:

Application
↓
epoll_wait()
↓
Kernel blocks thread
↓
No CPU consumed while sleeping
↓
Kernel wakes thread only when an event occurs
Enter fullscreen modeExit fullscreen mode

The application still uses CPU while processing events.

The real optimization is:

Don't waste CPU while waiting.

That changed how I thought about concurrency.

2. The kernel already solves waiting

Before this project, I assumed event loops were mostly implemented in Java.

They're not.

Linux already provides mechanisms for nearly every kind of asynchronous waiting:

  • epoll
  • eventfd
  • timerfd
  • signalfd
  • inotify

Instead of writing complicated polling loops, applications can ask the kernel:

"Wake me when something interesting happens."

That realization became the foundation of zThread.

3. Throughput benchmarks can be misleading

One of my earliest benchmarks compared:

  • ArrayBlockingQueue.offer()
  • eventfd_write()

The results looked terrible.

Then I realized I wasn't measuring equivalent work.

A queue insertion is an in-memory operation.

An eventfd_write() crosses into the kernel and wakes an event loop.

Those aren't comparable.

I completely redesigned the benchmark suite to compare end-to-end event processing pipelines instead of isolated API calls.

That was probably the most valuable lesson I learned about benchmarking.

4. Foreign Function & Memory API changes everything

A few years ago, calling Linux APIs from Java usually meant JNI.

Today, Java's Foreign Function & Memory (FFM) API makes native interoperability much more approachable.

For zThread, that meant I could call Linux APIs like:

  • epoll_create1
  • epoll_wait
  • eventfd
  • timerfd_create

directly from Java with a much cleaner integration model.

It's one of the most exciting additions to the modern JVM ecosystem.

5. Building the runtime was easier than building good benchmarks

Ironically, writing the event loop wasn't the hardest part.

Designing benchmarks that were:

  • fair
  • reproducible
  • statistically meaningful
  • comparable across frameworks

turned out to be significantly more challenging.

It's surprisingly easy to publish impressive-looking numbers.

It's much harder to build benchmarks that other engineers trust.

That experience fundamentally changed how I read performance claims online.

What's next for zThread?

The project is now:

  • Open source
  • Available on Maven Central
  • Focused on Linux event-driven programming in Java

My next goals are:

  • Better benchmarking
  • Reactor integration
  • More examples
  • Better documentation
  • Community feedback

Final thoughts

This project started as a curiosity:

"How does NGINX actually wait without wasting CPU?"

That single question led me down a rabbit hole of Linux kernel APIs, JVM internals, concurrency, benchmarking, and systems programming.

Whether zThread becomes widely adopted or simply remains a learning project, it has already achieved its biggest goal:

It taught me how modern event-driven systems really work.

If you've worked on Netty, Reactor, Vert.x, or JVM performance engineering, I'd love to hear your thoughts or feedback.

Project link:https://github.com/namanONcode/zThread

Top comments (0)