adimas - Fotolia

Get started Bring yourself up to speed with our introductory content.

Is Java slow? Compared to C++, it's faster than you think

If you find that Java is slower than other languages, such as C++, here's how to better compare the two and the major differences between compiled and interpreted languages.

Is Java slow?

It's a commonly asked question in a world where every software developer wants to get the most out of every clock cycle their programs consume. It was also a topic at a Java "Birds of a Feather" session at Oracle Code One 2019.

The consensus is that no, it is not. In fact, when compared against its peers, Java is pretty fast. Java is able to compete with -- and sometimes outperform -- other interpreted languages based on how it manages memory, completes just-in-time (JIT) compiles and takes advantage of various features of its underlying architecture.

Compiled vs. interpreted languages

The fact remains that Java is an interpreted language. In contrast, C++ -- a language which Java is often compared to -- is statically typed. It is the dynamic nature of the Java language that often gets users worried about possible speed issues.

With an interpreted language, code is compiled into an intermediary form before it is converted into machine code. In Java, this intermediary is called bytecode. At runtime, a Java virtual machine (JVM) turns this bytecode into machine code, and it's the machine code that runs on the processor. Java bytecode can run on any computer with a JVM installed, which is the basis of Java's write-once, run-anywhere mantra. But, this intermediary translation from bytecode to machine code consumes resources. This step irks those who are primarily focused on performance.

Java vs. C++ performance

In contrast, a program written in C++ gets compiled directly into machine code -- without an intermediary translation required at runtime. This is one reason why C++ programs tend to perform faster than those written in Java.

Java will work faster than C on the CPU you don't have yet.
Gil TeneCTO, Azul

However, there are exceptions. When a C++ program is compiled, it's optimized based on the architecture of the system on which it runs. For example, if a C++ program is targeted against an ARM-based processor, it can take advantage of all the features that architecture currently offers. It cannot take advantage of any features that don't yet exist in that architecture.

Java can.

When a Java program runs, it inspects the underlying system, and the JVM can optimize the machine code it creates based on the available features. If a new processor comes out with new optimization features, the JVM can immediately generate machine code to use those features. In contrast, a program written in C++ would need to be completely recompiled and redeployed to use the new features.

So, is Java slow?

"Java will work faster than C on the CPU you don't have yet," Azul CTO Gil Tene said at the Code One session. "When the AVX-512 vector support came out for Skylake CPUs, JIT compilers that knew how to vectorize ran twice as fast, while C stayed at the same speed," Tene said. Until those old C programs were recompiled, the Java programs maintained a performance edge.

Many factors influence an application's speed.

Is Java slow? No.

Is Java a program as fast as one written in C++? Not always, but there are cases where it can, in fact, be faster.

Dig Deeper on Application performance measurement and Java performance

Join the conversation


Send me notifications when other members comment.

Please create a username to comment.

In which situations would you prefer to program with C or C++ versus Java?
There are other optimizations that may allow Java to outperform C++. Two such are devirtualization and inlining. In devirtualization, the runtime detects that there is only one type of object that can appear at a given instance method call site. The runtime can then convert that method call into a direct native subroutine call that doesn't indirect through a jump table. C++ can't do this. When inlining, methods called frequently by a calling method are collapsed into a compiled version of the calling method. This can be done several calls deep. C++ compilers can inline methods in the same class, or those defined in C++ header files, but can't generally inline across classes or dynamically detect when inlining would be most beneficial. The two together are powerful: Devirtualization allows inlining of instance methods. Inlining then opens up many more optimizations that C++ compilers are unable to detect.
C++ can absolutely do devirtualization and cross-module inlining when the optimizer is running in a whole program optimization mode. While some optimization decisions cannot be taken fully dynamically (during run-time), profile-guided optimization gets very close to that.
Wow @LukLuk you are absolutely right! I haven't been on a C++ project for several years and didn't know WPO or Link Time Optimization was available for C++. Thanks for bringing me up to date.

But how effective are WPO/LTO really? The mere existence of more than one implementation of a particular method in a program would disqualify ALL call sites for that method from devirtualization. Without run time information (eg has a class containing a second implementation ever been instantiated?) I suspect this capability is extremely constrained. Similarly for inlining, without runtime information about how often particular call sites are actually encountered, how can cost-effective inlining decisions be made?
As far as devirtuizarion, C++ is a strongly typed language. Because of that the compiler knows exactly at each call cite which method will be called. If it so choose it could actually devirtualize every fall so long as it wanted to duplicate, specialized versions of each method (which I may well do based upon profiling data).
That's not correct. The C++ compiler does not know which method implementation will be called because it cannot predict the class of the target. Thus, even with Whole Program Optimization (WPO) the C++ compiler must generate a full virtual call at any call site for which more than one method implementation exists in the whole program. This, I think, is very limited.

A Java runtime, by contrast, can actually profile virtual call sites to determine what target classes are occuring at each. So even if multiple implementations exist it can still speculatively devirtualize and trap back to a virtual call if an unusal class is encountered. This allows inlining of virtual methods and all of the profitable optimizations that proceed from that. Until C++ gets an adaptive runtime and JIT compiler (and becomes essentially Java) it can't do this.
One of the misconceptions about performance is that it depends only the language, its tools and the hardware. But of course they depend on the code itself too.
On a bad day, of course, you COULD write a program in C++ so badly and a program in Java so well that the Java would outperform the C++. 
But that is not the point. 
Performance comparisons need to check the optimal use of both languages in order to get a meaningful comparison.
Specifically regarding devirtualization. 
This is a no brainer.
In C++, if you want to, you can write methods that are not virtual at all. You cannot do that in Java. All methods are virtual. 
So, if you WANT to write non-performant C++ you might decide to use virtuals but if you WANT to write fast code in C++, then you will beat Java every time.

And of course, as LukLuk wrote C++ compilers can devirtualize. And the fact that they do not need to run in real time (they can make as many passes as they like) increases the opportunities for optimization by orders of magnitude.
In fact one of the most astounding capabilities of modern C++ compilers is their ability to make source code disappear at compile time. Replacing loops and function calls with constants, vectorizing and so much more.

I challenge the author or any of the commenters on this thread to propose one program that is written WELL in both languages that when compared fairly for speed will run faster in Java than in C++.

You wont find one.
Correcting a couple of misstatements:
1. Java JIT compilers can also eliminate code, recognize constants, vectorize, inline, etc.
2. You CAN write non-virtual methods in Java - they're called static, and they're a single instruction for dispatch, just like C++.
3. It's not an advantage to have to explicitly keep track of which methods are virtual and which are not - that's just another opportunity for programmer error.
4. Performance is not static - it's not one program vs another - it's measured in the actual execution of the program on a real load.

The big advantage that Java has over C++ (or any other statically compiled language) is being able to respond to the actual run time experience of a program. Turns out that most programs are incredibly repetitive - they go down the same code paths over and over - and some code paths are never taken at all. That creates opportunities for "speculative" optimizations - optimizations based on previous experience. Some of the optimizations that this allows are:
1. Dynamic devirtualization - if no objects have been instantiated that have a different implementation of a specific method, all calls to that method can be devirtualized. Or if only a single object type is ever actually seen at a given callsite, that specific callsite can be devirtualized. C++ cannot do this.
2. Intelligent inlining - C++ programmers and/or compilers have to guess which methods should be inlined. Java JIT compilers can actually measure which inlines are profitable and which ones are not worth the space. Even with the same method, not all calls are worth inlining. C++ cannot do this.
3. Dynamic code elimination - if there's a code path which has never been taken, a Java JIT compiler can speculatively eliminate that code and anything that depends on it, replacing it with a trap that can catch an attempt to go down that path, if one ever happens. C++ cannot do this.
4. Adaptive code generation - the same Java program running on the same JVM can recognize the hardware capabilities of the system on which it is running and generate the most efficient native code for that cpu. So you don't have to specify the execution target at compile time. C++ cannot do this.
5. Adaptive recompilation - many programs pass through "phases" of execution - different load conditions, different data, different request types, etc. A Java JIT compiler can recognize when previous optimization decisions have become suboptimal and decide to generate new code. C++ cannot do this.
I think your conclusion is incorrect.
In the rare case that you describe the Java code may run slower, but that is only if all the following come together:

1. The target CPU has a significantly fast feature that was not known to the C compiler when the program was compiled.
2. The optimization opportunity on the new CPU was for an operation that took a large portion of the code running time.
3. The C code was NOT recompiled for the new CPU feature.
4. The JVM WAS upgraded on the target (because if it wasn't it has no advantage over the C compiler)

All of these are highly unlikely to occur together.
And when they don't the Java code will be slower for all the reasons you gave in the article and many more.
I think point #4 is the most pertinent one. In the scenario given, someone would have updated the JVM, but not taken the time to recompile the C# program. So there are a few favourable assumptions given to the Java program in the given scenario.

A dynamic language like Java will always have more obstacles to overcome than a compiled language like C. But it's good to know that the technology keeps progressing, and the divide between the two continues to get smaller.
I disagree that the divide between the two is getting smaller.
I think that the performance difference between well written C++ programs and well written Java programs is growing and will continue to grow.
C++ is difficult to use and to maintain. There are many problems with the language. In my opinion the only reason that it has persisted and its popularity is steady in some applications is that one of its raison detre's is performance.
Every new addition to the standard goes through extreme scrutiny and hair splitting to make sure that performance is never sacrificed for other very important features (safety, useability, readability). This is what C++ is about. Control over performance.
Of course the Java community cares about performance but it does not have the same all-important priority is it does with C++. 
Different languages different goals. 
The tool box contains different tools for different jobs. That is fine.
But the divide is growing and will continue to do so.
Well maybe it's just the fact that processors are getting faster and the divide between the two is less noticeable. :)

Everyone wants to get the most out of every clock cycle. I wonder if a good article would be about which types of applications are actually bottle-necked by clock-cycle performance? With so many potential bottlenecks in an enterprise architecture, I wonder which types of apps suffer most at the app-on-CPU layer?

If anyone is interested in writing that article, feel free to email me.

I think Cameron is right: the  performance difference between Java and C++ is getting smaller. JVM technology continues to advance, reducing or eliminating previous impediments like garbage collection, startup time, memory footprint, etc.  while at the same time giving a safer, less fragile programming environment. C++ has nowhere to go.
"the  performance difference between Java and C++ is getting smaller"
What is this based on? What conditions were assumed? What kind of program? What hardware?
Come on, this is just wishful thinking.
Java is a powerful language higher in the stack than C++. 
We use Java for "high level applications" including enterprise, servers, networking, Big Data.
It is difficult to write such applications in C++ because it doesn't have any of the library support that is needed.
C++ is a tool for a different job. It is gives you greater control over performance and resource management. And of course with the control comes greater responsibility and more room for error.
For layers that are lower in the stack, for specific libraries that are real time or time critical, C++ is a better tool.

"C++ has nowhere to go"
Excuse me but this statement demonstrates ignorance about the capabilities of the language, the applications in which it excels and also ignorance of the enormous efforts of the industry, and the C++ committer to modernize it.
The achievements of C++ in the last 5 years are astounding and there is much more to come. C++ is not going to be replaced by any other language in the near future, and Java is not even playing in the same court.
If you care to address the ignorance seriously, you can go to the C++ Standardization commitee web page and see how Google and Microsoft are investing in C++. See also whats in store for the C++ standard in C++ 20.

But if you just want a short teaser, here is a video I recommend you watch. It is gives just a glimpse of what the C++ compiler can do for you.
If you really believe the JVM can do this, please enlighten us with some proof.

OK so suggesting a 1.25 hour video clip is not a trivial ask. Nonetheless I ground my way through it only to conclude that: 1) the video doesn't describe anything that Java JIT compilers haven't been doing for years and 2) C++ is copying Java! Java runtimes have been doing Class Hierarchy Analysis (CHA) for almost 20 years. That has been recently added to C++ to allow a very half-baked form of devirtualization (and elimination of the "virtual" keyword). Inlining is similarly handicapped. So the two most productive optimizations, and the two that open the way to many other productive optimizations, are severely constrained.

Unless C++ starts including a runtime engine that is capable of dynamic compilation and recompilation it won't be able to use adaptive techniques like the 5 listed in my Oct 22 post or the many others I didn't list, and the others which are still being developed. If it ever does include such a runtime engine it will become essentially Java.

So the bottom line is, given time to observe actual program behavior, Java will outperform C++ in most cases. Long term, Java's performance is continuing to improve and C++ without an adaptive runtime has nowhere to go.
Didn't you enjoy it? The guy is brilliant.
I am not an expert in the JVM JIT compiler, but to compare it with the C++ is comparing apples and pears.
It is possible that at the point where the code gets compiled, the two can do similar tricks, but as always actual performance is impacted by the entire system (the bottlenecks therein) not by the optimizations done in one area.
Java programs use virtual function calls heavily. Java programs leverage this and reflection heavily in their code. Hey, this is Java and it has powerful tools - let's use them. Once you do, performance is heavily impacted. (and when Java is used for the right task, the trade off is definitely worth it).
So, how many assembly instructions get executed when you add an integer to an ArrayList<Integer>? How many get executed when you add a byte to an std::vector<int>?
Come on, look at the bigger picture. When I need to debug code in Java libraries I step in and step in and step in. It almost never ends. You want to tell me that in run time all of this magically disappears?
"Nowhere to go".
I think you should be a little less categorical in your statements. There is a huge community of very smart computer science experts who disagree. Of course, you disagree if you like, and you might even by right, but statements like that reduce the credibility of the rest of your comments.
But back to the issue at hand.
Where can I find a specific example of a problem whose most efficient solution in Java and whose most efficient solution in C++ runs faster in Java?  
Perhaps we suffer from mutual ignorance. But I work with compiler people frequently and can say with high confidence that there's very little in a C++ compiler that isn't in a Java JIT compiler, and there's lots in a Java JIT compiler that isn't and can never be in a C++ compiler. So maybe it actually is apples and crabapples. :-)

Yes, Java programmers use virtual functions. But so do C++ programmers. And Java can devirtualize more call sites, and make them more efficient than can C++ (Godbolt confirms this in the video).

Some, not all, Java programs use reflection, and reflection is expensive. Most Java programmers are aware of this and use it judiciously when needed. But C++ doesn't even have reflection. There are no such thing as class, method or field objects. So there are useful design patterns that can't even be expressed in C++.

I don't think it's fair to pick on Java programming practices. If you take the same program design and code it in Java and in C++, the Java version will outperform the C++ version once it gets warmed up. Java simply has more optimization tools at its disposal.

Excluding allocation algorithms for array resizing which obviously are completely different, the code generated for Java's ArrayList<int>.add() - yes Java has lists of primitives - and C++'s std::vector<int>.push_back() is probably nearly identical. Both will have to dereference a pointer, retrieve the current end index, check the size, write the data and write the new end index.

Java's remaining handicaps have nothing to do with code generation. They are memory management and warmup. Both of these are waaay better than they used to be and getting better all the time.
You fail to respond to the core issues:

"Yes, Java programmers use virtual functions. But so do C++ programmers"
That isnt the point. The point is that C++ programmers don't have to.

"But C++ doesn't even have reflection"
The point here is not to praise Java for the features that it has and that C++ doesn't. The fact that runtime reflection does not exist in C++ does not make it less performant.

"If you take the same program design and code it in Java and in C++, the Java version will outperform the C++ version once it gets warmed up"
That again is not the point.
Using the same design for different languages will generally not be optimal for both languages.
In order to compare the two you need to choose the optimal design in each language and check which one runs faster.

"C++'s std::vector<int>.push_back() is probably nearly identical"
Come on, you don't really believe that, do you?

"Java's remaining handicaps have nothing to do with code generation. They are memory management and warmup."
I didn't say that Java has handicaps, but now that you mention it, memory management.
Garbage collection may be getting better, but you do not control it and C++ allows you to control it. 
The tradeoff is simple. You get security and safety from a GC, but you don;t get to control performance. Threads are stopped underneath you, memory is compacted, tables are moved around.
These are GREAT features and C++ does not have them.
But when you really need the speed, you take control and do it in C++.

And as I mentioned, I would like to see one problem that for which the optimal solution in Java is faster than the optimal solution in C++. 
If you are so sure that this is easy to prove, just suggest one. If you cant find a link that demonstrates it, make one up of the top of your head. I am willing to take the challenge to implement the solution in C++ and you implement in Java. 
Let's see which runs faster.

Cameron - despite your brilliant name, you got a few of the basics a bit mixed up ...

"The fact remains that Java is an interpreted language."

No, Java is not an interpreted language. An "interpreted language" is one in which an interpreter actually executes by interpreting the source code.

Java is compiled to an IR (called Java byte code), and that IR is sometimes interpreted -- depending on the implementation of the JVM. Note that interpreting the IR does not make Java an "interpreted language".

"In contrast, C++ -- a language which Java is often compared to -- is statically typed."

Java is also statically typed.