Daily-It

개발, AI, 인프라, 자동화와 일상 IT 제품 후기를 직접 써보며 정리하는 기술 블로그입니다.

Java Project Valhalla: hoping the Java I’ve used for years gets even better

Summary

From the perspective of someone who has used Java for a long time, Project Valhalla does not feel like just another syntax feature. Honestly, there is some hope mixed in. I have used Java as my main language for nearly 20 years, and I still like the stability and ecosystem Java gives me. So even while using Python, Go, and Rust these days, there has always been a thought somewhere in the back of my mind: “If only Java could get a little better in this area.”

Recently I have been using Python more often thanks to AI. I have also used Go and Rust. AI support is part of the reason, but speed, memory usage, and lightweight deployment are also hard to ignore. Project Valhalla will not suddenly turn Java into Rust. Still, value classes, identity-free objects, flattening, and a better bridge between primitives and classes could make Java more convincing again in performance-sensitive areas.

Table of contents

Why I’m thinking about Java performance again

I have used Java as my main language for about 20 years. When building enterprise backends, batch systems, API servers, and long-running operational systems, there have not been many choices as stable as Java. The ecosystem is large, the JVM is mature, and frameworks such as Spring are powerful. After using it for so long, Java became more than just familiar to me. I came to like the balance Java provides.

Of course, liking Java does not mean there are no frustrations. In fact, because I have used it for so long, the frustrations are easier to see. The memory overhead when many small objects are created, the split between primitives and objects, and the moments when I have to give up a clean domain model for performance are all examples. When you like Java, it is natural to hope these parts get better.

The last few years have changed things a bit. AI coding tools reduce the friction of writing Python. In the past, I might have insisted on Java for type safety and structure, but now it is much easier to experiment quickly in Python with AI assistance.

I have also been using Go and Rust more recently. The reason is simple: speed, deployment, memory usage, and lightweight runtime behavior in container environments. Go makes it easy to build small and simple servers. Rust gives strong performance and memory safety.

So is Java now destined to remain a “heavy but stable legacy choice”? I think Project Valhalla may be an important answer to that question. And honestly, as someone who has used Java for a long time, I hope the answer is positive. Rather than switching completely to a new language, I would be happier if the Java I already like became a better fit for modern performance requirements.

The problem Project Valhalla is trying to solve

One of Java’s biggest strengths is its object model. Classes, interfaces, encapsulation, and polymorphism make it easier to structure large systems. The problem is that representing everything as objects has a cost.

Think about small value objects such as Money, Point, Range, Color, EventTime, and UserId. In a domain model, these types are good. Money amount is much clearer and safer than a bare long amount.

But from the JVM’s point of view, creating many of these objects has costs.

  • Each object has identity.
  • Heap allocation is needed.
  • The program has to follow references.
  • An array stores references, not the values directly.
  • CPU cache locality can suffer.
  • GC pressure can increase.

In practice, developers often make this tradeoff.

Should I keep the domain model clean?
Or should I flatten things into primitives and arrays for performance?

This tradeoff appears often in real projects. At first, we design things in an object-oriented way. But when performance becomes a problem, we move down to long, int, double[], LongStream, or custom buffers. The code may get faster, but the domain meaning becomes weaker. Or rather, in B2B we sometimes tell ourselves, “It’s the domain!” and lean even harder into object-oriented modeling for maintainability.

Project Valhalla is an attempt to reduce this old gap. The OpenJDK Valhalla page describes the goal as augmenting the Java object model with value objects, combining object-oriented abstractions with the performance characteristics of simple primitives.

The key change: value classes and identity-free objects

The core of JEP 401 is Value Classes and Objects. The idea is simple:

Let Java directly represent objects where only the value matters and object identity does not.

Normal Java objects have identity. Even if two objects contain the same values, they can still be different objects.

new Point(1, 2) != new Point(1, 2)

In today’s normal Java object model, “same value” and “same object” are different things. equals() may return true, but == is different.

Valhalla’s value objects change that assumption. They have no identity and are distinguished only by their state. JEP 401 includes an example like this:

value record Point(int x, int y) {}

Point p = new Point(17, 3);
Objects.hasIdentity(p);      // false
new Point(17, 3) == p;       // true

This matters because the JVM can optimize more aggressively. If an object has no identity, the JVM does not always need to treat it as “something located at a specific place on the heap.” Depending on the situation, the JVM can flatten or scalarize it.

In simple terms, the direction looks like this:

Current object layout:
array → reference → heap object → fields

Possible optimized value-object layout:
array → field values placed more directly

That difference matters when a program creates many small objects.

Is there real hope for performance improvement?

Yes, there is hope. But we should not expect every Java program to suddenly become faster. As someone who has used Java for a long time, what I expect is not one dramatic miracle, but a structural improvement in the parts that have long felt frustrating.

There are three main reasons Valhalla is interesting for performance.

1. It can reduce the allocation cost of small objects

Java backends constantly create small immutable objects. DTOs, records, domain values, tuple-like objects, and event objects appear during request processing. JIT and escape analysis can optimize some of this, but not always in a way we can rely on.

Value classes give the JVM a better path to treat these objects more like values. Because object identity is not required, the JVM has more room to avoid heap allocation or break the object into fields.

2. Memory layout can improve

Today, a Point[] in Java is essentially an array of references to Point objects. Each Point can live somewhere else on the heap. When data is scattered, CPU cache behavior gets worse.

Valhalla moves toward allowing value objects to be stored more compactly inside fields and arrays. OpenJDK documents describe flattening and scalarization as important optimization points.

Performance is also about how continuously the CPU can read data. One reason Go and Rust often feel strong is that they make data layout easier to control directly. Valhalla is Java’s attempt to get closer to that world while keeping Java’s programming model.

3. It can reduce the tradeoff between domain modeling and performance

This is the most important part to me. Java developers sometimes give up the object model because of performance.

Types such as Money, Coordinate, and TimeRange belong naturally in the domain model. But when performance becomes important, we are tempted to unpack them into primitives.

If Valhalla succeeds, we can have an option like this:

value class Money {
    private long cents;

    public Money(long cents) {
        this.cents = cents;
    }

    public long cents() {
        return cents;
    }
}

If this kind of type can be optimized closer to a value at runtime, developers can preserve meaning in the code while reducing the performance penalty.

Why this matters to Java developers

From the perspective of someone who has used Java for nearly 20 years, Valhalla matters not because it makes Java look like the newest language, but because Java is trying to reduce its weaknesses while keeping its strengths.

Java’s strengths are still significant.

  • It is good for maintaining large systems.
  • The JVM ecosystem is stable.
  • Operational and observability tools are mature.
  • Libraries and frameworks are abundant.
  • It works well for team development and long-term operations.

But the weaknesses are also clear.

  • Memory usage can feel heavy.
  • Small-object-heavy code can increase GC pressure.
  • The primitive world and the generic/object world are awkwardly separated.
  • It is hard to control data layout in performance-sensitive code.

When using Go and Rust, these differences are easy to feel. Go has simple binaries, fast startup, and a straightforward concurrency model. Rust gives strong performance and memory safety. Python dominates when it comes to AI ecosystems and fast experimentation.

If Java can improve small value objects and memory layout through Valhalla, it can strengthen this position again:

stability for large systems
+ expressiveness of domain models
+ mature JVM operations
+ better value-type performance

This combination is still powerful. That is why Valhalla feels more personal to me than just another technical feature. It suggests that the Java I have used for years is still moving forward, and that some situations where I had to choose another language for performance reasons might become possible in Java again.

Caveats: this is not a silver bullet yet

There are also things to be careful about.

1. JEP 401 is still a Preview feature

OpenJDK JEP 401 is Value Classes and Objects (Preview). JVM Weekly reported that JEP 401 is being integrated into the main OpenJDK repository and is targeting JDK 28, but the important point is that it is still a Preview feature.

So this is not something I would immediately introduce across production systems. It is better to treat it as something to study, test, and evaluate.

2. Generics are not solved all at once

Many Java developers are waiting for better primitive generics such as List<int>. JEP 402 discusses enhanced primitive boxing, but the document also explains that generics still use erasure. List<int> will not immediately behave like an int[].

JEP 402 says future JVM enhancements may allow specialized performance optimizations for primitive parameterizations. So this is part of the larger Valhalla direction, but not a one-step miracle.

3. The object model requires new intuition

Having no identity is an advantage, but it also requires care.

  • Value objects cannot be used for synchronization.
  • The meaning of == changes.
  • Identity-based data structures or caches may not fit.
  • We should not think of them like mutable objects.

JEP 401 also notes that developers may be surprised by changes in operations such as == and synchronized.

Where I would try it first in real projects

If Valhalla becomes stable, these are the areas I would look at first.

1. Domain value objects

Money
UserId
OrderId
Coordinate
TimeRange
Version

These types carry meaning, but performance concerns often tempt us to unpack them into primitives. If value classes settle well, this is the most natural use case.

2. Large volumes of events, logs, and metrics

Event streams, log processing, and metric aggregation often move huge numbers of small data structures.

EventTime
MetricPoint
TraceId
SpanRange
CounterValue

If these structures can be handled more compactly than a set of heap object references, there may be benefits for GC and cache locality.

3. Numeric, coordinate, and vector-like data

Java may not become the main language for AI training, but value classes still matter on the server side for vector search, recommendation, ranking, coordinate calculations, and financial calculations.

If Panama, the Vector API, and Valhalla mature together, the way we handle performance-sensitive data on the JVM may become much better than it is today.

Conclusion

Project Valhalla is a long-awaited change for Java developers. From the perspective of someone who has used Java for nearly 20 years, the real problem with Java was not that the syntax felt old. It was the gap between the object model and the performance model.

I have used Java for a long time, and I still like it. The stability Java gives when building and operating large systems, the maturity of the JVM ecosystem, and the predictability it provides in team development are not easy to give up. So even while using Python, Go, and Rust these days, I still had the thought somewhere in my mind: “If only Java could get a little better in this area.” (Maybe it is simply because familiar things feel good.)

We want to build good domain models, but when performance matters, we often have to move down to primitives, arrays, buffers, or special optimized code. Valhalla is an attempt to reduce that gap.

Of course, we still need to be careful. JEP 401 is Preview, and generics performance will not be solved all at once. Go and Rust will not lose their strengths. Java will not suddenly become the best choice for every domain again.

Still, I see Valhalla as a realistic hope for Java performance improvement. It is not Java turning into another language. It is Java raising its performance floor in a very Java-like way.

It is surprisingly nice to see a language I have used for so long continue to improve. I hope Valhalla shows that Java is not just a past choice, but still a platform moving forward. These days, AI makes it easier to move between Python, Go, and Rust, but Java still has a strong sense of stability for long-running systems. If value objects and better memory layout are added to that, Java may again be seen not as “a heavy but familiar language,” but as “a language that can run large systems for a long time while reducing performance tradeoffs.”

Once it actually lands, I think I will need to test it in different ways. But personally, I am looking forward to it.

FAQ

Is Project Valhalla confirmed for JDK 28?

As of the sources checked for this article, JEP 401 is Value Classes and Objects (Preview), and industry coverage says it is targeting JDK 28. But because it is a Preview feature, the final specification and practical usage may still change. It is safer to treat it as something to test and learn before using it broadly in production.

Will Valhalla make Java as fast as Go or Rust?

It is not that simple. Valhalla is meaningful for reducing costs around small value objects, memory layout, and allocation. But Go’s simple deployment model and Rust’s ownership-based memory safety solve different problems. Valhalla should be seen as Java reducing a specific long-standing weakness while keeping its existing strengths.

How is a value class different from a record?

A record is concise syntax for a data carrier. But a normal record instance is still an object with identity. A value record or value class is intended to be an identity-free value object. That difference allows the JVM to attempt more compact storage and optimization.

Will generics performance improve immediately?

Not immediately across the board. JEP 402 discusses primitive boxing improvements, but the document also says generics still use erasure. Specialized optimization for primitive parameterization is part of the larger Valhalla direction, but it should be viewed as a staged evolution.

References

  • OpenJDK Project Valhalla: https://openjdk.org/projects/valhalla/
  • JEP 401: Value Classes and Objects (Preview): https://openjdk.org/jeps/401
  • JEP 402: Enhanced Primitive Boxing (Preview): https://openjdk.org/jeps/402
  • State of Valhalla: Part 1, The Road to Valhalla: https://openjdk.org/projects/valhalla/design-notes/state-of-valhalla/01-background
  • State of Valhalla: Part 2, The Language Model: https://openjdk.org/projects/valhalla/design-notes/state-of-valhalla/02-object-model
  • State of Valhalla: Part 3, The JVM Model: https://openjdk.org/projects/valhalla/design-notes/state-of-valhalla/03-vm-model
  • JVM Weekly, Project Valhalla Explained: https://www.jvm-weekly.com/p/project-valhalla-explained-how-a