The JVM supports five basic data types:
These data types are discussed in detail in the next few sections.
3.2.1 Numeric Types
The first four types are identical to the Java basic types of the same name. They are called numeric types. A member of this type is interpreted as a number. This number is an integer if it's a long or an int, or it is an approximation of a real number if it's a double or a float. The long and double values have larger ranges but require more memory. The int and float entries have smaller ranges and require a single entry on the stack or in the local variable array. The long and double have wider ranges, and these require two entries each.
When doing arithmetic or working with the operand stack and local variables, the Java types boolean, byte, short, and char are treated in JVM code as ints. The only difference between these types and int is the range of acceptable values.
A boolean is an int that can be only 0 (false) or 1 (true). A byte can range from 128 to 127, and a short goes from 32,768 to 32,767. The only unsigned type is char, which can be from 0 to 65,535. All these ranges are subsets of the int range, which is 2,147,483,648 to 2,147,483,647.
The JVM defines the arithmetic, local variable, stack, and comparison operations only on type int. There is no special support for comparing booleans, bytes, shorts, or chars. Instead, they are operated on exactly as if they were ints.
The JVM provides some special support for these types. There are special types for arrays of shorts, chars, and bytes. This allows the JVM implementation to represent groups of these restricted ints in a smaller space. For example, to store 1,000 ints in an array, almost four kilobytes of memory might be required. An array of 1,000 bytes can be stored in less than 1K. The details vary from implementation to implementation of the JVM, depending on the goals of the implementor and the platform supporting the implementation.
The JVM also provides some special support for these types as arguments to methods and in fields. We discuss this in detail in section 2.6.
3.2.2 Object Types
A reference is a reference to a Java object of any class. As a Java programmer, you are already familiar with references. When you declare a field like this
you have really said that you want to create a field that holds a reference. Furthermore, you have specified what sort of object it must be: it must be either an instance of Foo or one of the subclasses of Foo. The exact type of the object cannot be determined until the program is run.
A reference takes a single slot on the stack, but it means much more than that. A reference points to an object somewhere on the heap. You can make a copy of the reference without duplicating the object itself. Unlike a numeric type, an object has properties that are independent of the reference to the object.
A reference to an object is not the same thing as the object itself. When you make a copy of a reference, you are not creating a new object. Instead, you have two references to the same object. This distinction may seem pointless, but it's actually very important. When you have two references to an object, changing the underlying object affects the values you get from both references.
If you are a C programmer, you might think of reference types as being somewhat like pointers. This is true in a sense, but JVM references are very different from C pointers. For one thing, you can perform arithmetic on C pointers. You can go looking around in memory using pointers. This is not true of JVM references; once they point to an object, they always point to the same object. The operations available on references look only at the object that the reference points to, not at the memory around it.
Also, references point only to objects, not to local variables, stack entries, or fields within objects. This makes it easier to ensure that the data within each method is not altered by other methods you call. "Stray pointers," which point to memory that you didn't expect them to point to, are impossible in the JVM.
A null is a particular reference that refers to no object; you can store it any place you'd use a reference. However, if you try to access any of its fields or call any methods on it, an exception will be thrown.
In the JVM, Strings are objects, so they're represented on the stack as references to objects of type java/lang/String. The Java language provides special syntax that makes Strings easier to handle, but they are still objects, not values. From the JVM's point of view, there is no difference between Strings and other objects.
3.2.3 Type returnAddress
There is a sixth type, returnAddress, which we tend to ignore in the following discussions. It is relevant only to the jsr and ret instructions, which are discussed in section 5.5. The use of returnAddress is quite restricted, so most of the time you can safely forget about it.