A language can’t be slow. Or how fast do you think English is?
And modern JVMs are highly optimized.
What it means to be fast or slow
How many Kilometers does your Application run per Hour?
When we talk about how fast or slow something is we need to define how we measure it. Is it relevant how long it takes to start up or is this ignored? If it is relevant then an application written in Java might be rather slow compared to something that is compiled. The JVM needs to be started and the code needs to be loaded and interpreted. But Java is usually not used for such small tools that exit quickly. A Java application might run for months or even years without ever restarting.
If you measure delay or throughput you’d probably just ignore startup time. You’d start measuring time after the system started and you can send requests and measure how long it takes until you get a response. Or you send a bunch or requests and and see how many get processed in a second, a minute, an hour, etc.
Why Java is fast
Most Java applications are very fast. Those that are slow are probably because of slow network, bad scalability of the system (this is due to bad design, Java scales very well), blocking I/O (Java supports asynchronous I/O) or use of unsuitable data structures and algorithms.
Java comes with a Just-In-Time-compiler that will make sure code runs fast (i.e. optimized). This is not the case for most compiled software. A C++ compiler can do a lot of optimization at compile time, but not at runtime.
Java is full of pre-existing classes that allow you to use the full power of the computer it runs on. An application can even run on many computers.
Once you understand the Java Memory Model it is easy to use and very efficient.
Some Weaknesses of Java
Java will evaluate all expressions that are passed as parameters. Even if the method won’t actually use it. This can be fixed by using lambdas, but that is more work and you still get some overhead for the lambda. Other languages are not that eager.
Parallel and asynchronous programming wasn’t that relevant in the 90ies as they are now. So other languages can do some things better. Java doesn’t have an easy way to define an immutable type. The new Stream API (since Java 8) is somewhat cumbersome to use.
There are some things that Java does to make it robust. It may seem that this also makes it slow.
Array access is always checked
Whatever language you are using, you wouldn’t want to access the wrong parts of memory. This is a common problem and one solution is to enforce checks to prevent “Array Index Out Of Bounds”. But Java code is optimized and a simple for loop doesn’t need to be checked at runtime. In most cases the compiler can figure out that it is impossible that an index is accessed that is out of bounds. And since Java does it automatically you can be sure you do not forget it and you do not check unnecessarily.
Casts are always checked
That’s another common problem. In C++ you can cast without any runtime type checks. Then you might access data that doesn’t actually belong to that object. So in other languages you should still do that check. What’s the point of a “fast” application that crashes occasionally?
And these checks can be optimized too.
Garbage Collection takes a lot of Time
But modern implementations can do a lot of work in parallel and most of the time only newly created objects get collected. And modern software written in C++ often uses reference counting that also takes some time.
Garbage Collection can be tuned so it can be optimized for throughput or memory usage or short delays. Even real-time systems are possible with Java.
All methods are virtual
In Java you have static methods and if not static they are virtual. So at runtime the JVM needs to find which method to actually invoke. This doesn’t take that much time and you proably won’t override that many methods. So this can be optimized.
Almost everything is an Object
Structs can be a bit more lightweight. And Strings are just a wrapper for a char (at least up to Java 8). But the JVM optimizes this. A JVM can simply load it’s own optimized String class. Creation of objects takes some time but modern JVMs do if very fast. They can reuse old objects of the same type. A JVM could even optimize the code so objects exist only in the registers of the CPU (escape analysis).
You shouldn’t optimize
Just because you can optimize in C++, doesn’t mean you will. But you really shouldn’t, unless you write code that really needs to be as fast as possible. Optimized code is difficult to read and hard to maintain. So for games and many other things Java isn’t the right choice. But for web applications, desktop and mobile apps, and many other kinds of software it is a very “fast” solution.
Java will become even faster
Java 10 might introduce value types. Maybe that allows for even more optimization. At least the JVM will know what types are immutable without any analysis. Strings will be optimized too.