Archive for the ‘JVM & ByteCode’ Category
Java performance tips – Part 2 : Better String handling
StringBuffer vs String
As we all know both String & StringBuffer are used to hold string (character sequence) values. The basic & the most important difference between the objects being created using String & StringBuffer : objects of String are immutable (means, no one can change it); but the objects created using StringBuffer are mutable. Consider the following code block,
// Example 1 String aString = "Hello"; aString = aString + "World !";
// Example 2
StringBuffer aStringBuffer = new StringBuffer("Hello");
aStringBuffer.append("World !");
Here both example 1 & 2 are doing the same thing. If someone ask us which one we think is a better way to append a string to other, hmmm… sometimes, no most of the times people may choose the first method. B’ coz the “+” operator seems super cool, right?
The String concatenation using the “+” works in a crazy way. It will internally create a temporary StringBuffer object using the current value and will use the append() to get the things done. Why? Any guess? Yeah, you are right. B’ coz the object created using String is immutable.
I found the byte-code equivalent of both the string concatenation from javaworld.com. Let’s have a look at it.
Byte-code equivalent of example 1:
0 new #7 <Class java.lang.String> 3 dup 4 ldc #2 <String "Hello"> 6 invokespecial #12 <Method java.lang.String(java.lang.String)> 9 astore_1 10 new #8 <Class java.lang.StringBuffer> 13 dup 14 aload_1 15 invokestatic #23 <Method java.lang.String valueOf(java.lang.Object)> 18 invokespecial #13 <Method java.lang.StringBuffer(java.lang.String)> 21 ldc #1 <String "World !"> 23 invokevirtual #15 <Method java.lang.StringBuffer append(java.lang.String)> 26 invokevirtual #22 <Method java.lang.String toString()> 29 astore_1
Byte-code equivalent of example 2:
0 new #8 <Class java.lang.StringBuffer> 3 dup 4 ldc #2 <String "Hello"> 6 invokespecial #13 <Method java.lang.StringBuffer(java.lang.String)> 9 astore_1 10 aload_1 11 ldc #1 <String "World !"> 13 invokevirtual #15 <Method java.lang.StringBuffer append(java.lang.String)> 16 pop
I donno how to interpret it. But we can easily understand what is happening there, right?
StringBuffer vs StringBuilder
StringBuilder is same as StringBuffer but not thread-safe. All the public methods of StringBuffer are synchronized. StringBuilder offers better performance than StringBuffer in most of the conditions. StringBuffer is advised to use only if some kind of synchronization is needs.
Data Types in Java: a different approach
As far as I think, the need of having different data types in java is execute the instructions properly to serve the request.
JVM supports two kinds of data types: Primitive & Reference.
Primitive data type
Numeric
Floating point (float & double)
Integral (byte, short, int, long, char)Boolean
Even though boolean is a primitive data type, its represented using byte or int.
Boolean value representations:
false: 0 (zero)
true: non-zero integerreturnAddress
This is unavailable to the java developer. Used to implement finally in programs. Not directly associated with the Java programming.
Reference data type
The reference type holds the reference of dynamically created objects which are in the heap.
The reference type can hold three kinds of values.
class type
Points to an object/class instanceinterface type
Points to an object, which is implementing corresponding interfacearray type
Points to an array instanceor “null” (Hmm.. this is the fourth one)
Difference between primitive & reference data types
The primitive data types hold the value itself. But reference data types hold reference to objects. Means they are not objects, but reference to objects.
What is a word?
Word is again an abstract concept, which is the basic unit of size for data values in JVM. What the specification demands is, the data types byte, int, short, char, float, returnAddress & reference should fit in to a WORD! Means, 32 bits at least. Afaik, the motive behind the abstract concept of word is that, the amount of memory assigned to a program shouldn’t be a limiting factor for its execution.
Understanding JVM
JVM (Java Virtual Machine) is all about,
an abstract specification; which is a concept
a concrete implementation; which runs on many platforms (can be a combination of hardware and software)
a runtime instance; which can host a single java application (each runs on different JVM)
Every java application will be running in a separate JVM instance even if they are in the same machine. The JVM starts the execution of a Java application from an initial class’ main method. The “java” program from Sun’s JDK is an implementation of a java virtual machine.
“java <initial class name> <arg1> <arg2> …. ” is the implementation dependent way in Sun’s JDK to spawn a new instance of JVM along with the specification of the application initial class and the arguments needed. The main() of the initial class is the starting point of the application’s initial thread.
JVM Architecture
Major subsystems
Class loader subsystem:
Responsible for loading classes and interfacesExecution engine:
Responsible for the execution of the instructions specified in the classes
Other components
Runtime data areas
Native interface; interacts with the native libraries

More about runtime data areas
Mechanism to hold all kinds of data items such as instructions, object data, local variable data, return values & intermediate results.
Organization of runtime data areas
How runtime data are stored in the runtime data areas depends on the implementation of the JVM. Some implementation may enjoy the availability of memory and some others may not. The abstract nature of runtime data area specification allows the implementation of JVM in different machines easier.
Some runtime data areas are shared among all the threads in the application, while some others are too specific to an active thread.
Runtime data areas shared among all threads:
Method area: holds the details of each class loaded by the class loader subsystem.
Heap: holds every object being created by the threads during execution
Thread specific runtime data areas:
Program counter register:
points to the next instruction to be executed.Java stack:
hold the state of each method (java method, not a native method) invocations for the thread such as the local variables, method arguments, return values, intermediate results. Each entry in the Java stack is called “stack frames“. Whenever a method is invoked a new stack frame is added to the stack and corresponding frame is removed when its execution is completed.Native method stack:
holds the state of each native method call in an implementation dependent way.
Note:
In JVM there is no registers to store the intermediate values. They are stored in the java stack itself.


