Java Compared to Native Code

Java is a typical example of the conflict between portability and performance. Java’s portability solves many problems, but there is a performance cost to these solutions. Java is compiled into bytecodes, which are then interpreted. Because the bytecodes are not the instructions of any existing CPU (any actual machine, so to speak), they must be interpreted by a virtual machine, i.e., translated into instructions that can be directly executed by the CPU. This is the primary reason that the simple interpretation of Java bytecodes is 30 to 100 times slower than optimized C, although just-in-time compilers (JITs) can bring this down to 5 to 10 times slower.

Code written in C is compiled into instructions that are native to a particular CPU, so interpretation is not needed, but these instructions have no binary-level portability. Furthermore, C code is not as efficient as hand-coded assembly, but it is much easier to write and good enough for most uses. Source-level C portability is also generally problematic because C programs often take advantage of platform-specific features, and because the C standard itself includes platform dependencies, such as the number of bits in an int. In C, integers can be different sizes on different platforms, so int i means one thing on one platform and another thing on another platform, leading to different results at runtime even if the code compiles smoothly. Java is completely portable at the source level, but that’s ...

Get Web Performance Tuning now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.