Java performance Issues
by, 11-16-2011 at 08:17 PM (1228 Views)
In this post, I will talk about Java performance Issues briefly.
The output of a Java compiler is a bytecode and not an executable code. The Java Virtual Machine (JVM) interprets the Java bytecode at runtime. Most of the modern programming languages such as C, C++ are not interpreted and compiled to the executable code because of the performance concern. When a program is interpreted, it generally executes slowly when compared with an executable code.
Certain language features in Java such as array bounds checking, run-time type checking, and virtual function indirection bring upon an unavoidable time penalty. Though this is not unique to Java only and these issues are associated with some other programming languages as well. Also there are certain features not available in Java, viz. Java does not have arrays of structures or a genuine multi-dimensional array, but Java only has an array of references to objects or further arrays. In addition to that without using an object from a Java method you can not return more than one value. Ultimately, Java code makes more heap allocations when compared with some other languages.
Byte code vs. native compilation
There is a difference between performance of JIT compilers and native compilers. JIT compilation takes more time. It is not so good for short-lived applications and for applications which contain large amount of data. However, when a program is compiled to native code, performance of the program can be compared with that achieved by a native compiler. Many JIT compilers support manual inlining of method calls at run time though Java does not support it. Sun's HotSpot JVM provides support for runtime recompilation. This can improve the performance of the static compilation considerably.
Java program requires more memory resources and is slow when compared with most of the natively compiled modern day programming languages such as C or C++. This is because the Java Library must be loaded in to memory before program execution takes place. In addition to that, both the Java binary and native recompilations must be in the memory at the same time. Further, Java Virtual Machine (JVM) also requires memory resources for it self. These all add and Java memory usage is high when compared to C, C++ etc.
Java has its own memory management. However, in certain situations memory must be released explicitly as it is done in C++. For example, in JDBC database connections you need to release the memory. In short, Java does not manage all resources for memory.
To avoid allocation errors such as memory leaks, Java (also) has garbage collection. As a result, in a way, in Java memory management is automatic.
In C++, programmers are allowed to control where objects are stored. This facilty is not available in Java which always allocates objects on heap. Only compiler can optimize this.
Programming languages such as C, C++ provide more flexibility over memory management. Java has its own way of garbage collection. In Java garbage collection occurs when an object is removed from memory. Programmer has no control over when the garbage collection occurs. Programmer can neither delay it nor decide when to do the garbage collection. Though this reduces chances of memory leak to a great extent and make programming easy so that programmer can focus on another important aspect, it also reduces the flexibility where in some cases a more efficient memory management can be done.
Java's automatic garbage collection can add overhead if compared with manual deallocation of memory. Further depending upon garbage collector implementation automatic garbage collection can have a positive or negative impact on performance.
Java's garbage collector can run at any time. As a result sometimes Java is inappropriate for application which will run at real time. There was a problem with older JVMs in which due to collection there may be temporary interruption to the thread of program. In new JVMs too concurrent collection may slow down program execution to some extent.
By using different modern techniques, the new JVMs have improved performance of the garbage collection considerably. However, earlier Java Virtual Machines, that is JVM's 1.0 and 1.1 used a mark-sweep collector to fragment the heap after the garbage collection, due to this there was not so good overall performance. Due to this, from Java 1.2, the JVM's switched to a generational collector for better performance and quality.
When it comes to lower level programming C or even C++ is sometimes considered better than Java. When Java was designed, the main focus was on portability and security, which was lagging in the popular languages such as C, C++ etc. As in Java main emphasis is on portability and security, program can not directly access hardware or a peripheral device such as a scanner, digital camera, audio recorder, video capture, or virtually any hardware that requires direct memory space control. This obviously makes programming which requires these devices difficult in Java. However, it is not impossible to communicate and include programming for these devices in Java.
Interfacing with native code
Sometimes a software application can not be written and developed entirely in Java, for example when Java's default class library does not support certain operating system and/or hardware specific features. In such a situation, the Java Native Interface (JNI) is very useful.
However, using Java Native Interface (JNI) is not full proof and has some limitations of its own. These limitations are machine dependency, potential deadlock situations, memory allocation leaks, and inconsistent or not so reilable application performance. Further as different languages or programming techniques are used code becomes complex and difficult to maintain. However, due to the very nature of problem (operating system and/or hardware, programming languages) all these issues are common with any other programming language as well.
When Java Programming Language was designed, the main goal was that the programs written using Java language should be able to run across different platforms securely. To be able to run programs written in Java language across different platforms securely, mainly depends upon Java Virtual Machine (JVM) implemented on those platforms. It means stability and version of Java Virtual Machine (JVM) is very important. However, only on platforms Solaris (Sun's own platform), Linux, and Windows you will find most updated Java Virtual Machine (JVM). Where as HP and IBM provide their own implementation for their operating systems and found that it is not actively updated with the latest release of Java. The JVMs found on these platforms were even a year old.
Various JVM implementations
On Windows, there's JVMs from Sun, IBM and Microsoft. The IBM one often has slightly higher performance, but when Sun releases a new specification, it takes a bit longer for IBM to implement it. The Microsoft JVM is totally obsolete (version 1.1.4). On Linux, there's Sun, IBM, Blackdown and kaffe. The last two are open source efforts, though the Blackdown team works together closely with Sun. kaffe is not a complete implementation, most notably it lacks AWT/Swing support. On OS/2 there are JVM's from IBM, GoldenCode Development, and Innotek Systems. On MacOS (and OS X) Apple does the JVM implementations IIRC. HP does the JVM implementation for HP-UX, and SGI for Irix. IBM's implementation is the primary (and typically only) one for AIX, OS/400, and other IBM platforms.