Is Java really slow?

Modern Java is one of the fastest languages, even though it is still a memory hog. Java had a reputation for being slow because it used to take a long time for the VM to start up.

If you still think Java is slow, see the benchmarks game results. Tightly optimized code written in a ahead-of-time compiled language (C, Fortran, etc.) can beat it; however, Java can be more than 10x as fast as PHP, Ruby, Python, etc. There are specific areas where it can beat common compiled languages (if they use standard libraries).

There is no excuse for “slow” Java applications now. Developers and legacy code/libraries are to blame, far more than the language. Also, blame anything ‘enterprise.’

In fairness to the “Java is slow” crowd, here are areas where it is still slow (updated for 2013):

  • Libraries are often written for “correctness” and readability, not performance. In my opinion, this is the main reason Java still has a bad reputation, especially server-side. This makes the String problems exponentially worse. Some simple mistakes are common: objects are often used in place of primitives, reducing performance and increasing memory use. Many Java libraries (including the standard ones) will create Strings frequently, rather than reusing mutable or simpler formats (char[] or StringBuffer). This is slow and creates tons of garbage to collect later. To fix this, I suggest developers use primitive collections and especially Javalution’s libraries, where possible.

  • String operations are a bit slow. Java uses immutable, UTF-16-encoded string objects. This means you need more memory, more memory access, and some operations are more complex than with ASCII (C, C++). At the time, it was the right decision for portability, but it carries a small performance cost. UTF-8 looks like a better choice now.

  • Array access is a bit slower compared to C, due to bounds checks. The penalty used to be big, but is now small (Java 7 optimizes away a lot of redundant bounds checks).

  • Lack of arbitrary memory access can make some I/O and bit-level processing slow (compression/decompression for example). This is a safety feature of most high-level languages now.

  • Java uses a LOT more memory than C, and if your application is memory bound or memory bandwidth bound (caching, etc.) this makes it slower. The flipside is that allocation/deallocation is blazing fast (highly optimized). This is a feature of most high-level languages now, and due to objects and use of GC rather than explicit memory allocation. Plus bad library decisions.

  • Streams-based I/O is slow due to the (IMO, poor choice) to require synchronization on each stream access. NIO fixed this, but it is a pain to use. One can work around this by doing read/write to an array, instead of an element at a time.

  • Java doesn’t provide the same low-level functionality C does, so you can’t use dirty inline assembler tricks to make some operations faster. This provides portability and is a feature of most high-level languages now.

  • It is common to see Java applications tied to very old JVM versions. Especially server-side. These old JVMs can be incredibly inefficient, compared to the latest versions.

In the end, Java was designed to provide security and portability at the expense of some performance, and for some really demanding operations it shows. Most of its reputation for slowness is no longer deserved.


However, there are several places where Java is faster than most other languages:

  • Memory allocation and de-allocation
    are fast and cheap.
    I’ve seen cases
    where it is 20% FASTER (or more!) to
    allocate a new, multi-kB array than
    to reuse a cached one.

  • Object instantiation and object-oriented features are blazing fast to use (faster than C++ in some cases), because they’re designed in from the beginning. This is partially from good GC rather than explicit allocation (which is more friendly to lots of small object allocations). One can code C that beats this (by rolling custom memory management and doing malloc efficiently), but it is not easy.

  • Method calls are basically free and in some cases faster than large-method code. The HotSpot compiler uses execution information to optimize method calls and has very efficient inlining. By using the additional execution information, it can sometimes outperform ahead-of-time compilers and even (in rare cases) manual inlining. Compare to C/C++ where method calls come with a small performance penalty if compiler decides not to inline.

  • Synchronization and multi-threading are easy and efficient. Java was designed to be thread-aware from the beginning, and it shows. Modern computers usually feature multiple cores, and because threading is built into the language, you can very easily take advantage. Basically an extra 100% to 300% speed boost vs. standard, single-threaded C code. Yes, carefully written C threading and libraries can beat this, but that’s a lot of extra work for the programmer.

  • Strings include length: some operations are faster. This beats using null-delimited strings (common in C). In Java 7, Oracle took out the String.subString() optimization, because people were using it stupidly and getting memory leaks.

  • Array copy is highly optimized. In the lastest versions, Java uses hand-tuned assembler for System.arraycopy. The result is that in arraycopy/memcopy-heavy operations, I’ve seen my code beat the equivalent in C by reasonable margins.

  • The JIT compiler is smart about using L1/L2 cache. Ahead-of-time compiled programs can’t tweak their code in real-time to the specific CPU & system they’re running on. JIT provides some very efficient loop transformations this way.

A couple of other historical facts contributed to the “Java is slow” reputation:

  • Before JIT compilation (Java 1.2/1.3), the language was only interpreted, not compiled, and thus very slow.
  • JIT compilation took time to become efficient (major improvements with each version)
  • Classloading has become a lot more efficient over the years. It used to be quite inefficient and slow during startup.
  • Swing and UI code did not use native graphics hardware very well.
  • Swing is just awful. I blame AWT and Swing for why Java never caught on for the desktop.
  • Heavy use of synchronization in library classes; unsynchronized versions are now available
  • Applets take forever to load, because of transmitting a full JAR over the network and loading the VM to boot.
  • Synchronization used to carry a heavy performance penalty (this has been optimized with each Java version). Reflection is still costly, though.

Leave a Comment