4

If I use a normal class like List, Vector or something else, I get a size() function which returns the length of the regarded class but if I use an array of a class or a default data type I get a public member length which returns the current length of the array.

int a[] = new int[3];
a.length; // used without ()

Vector<Integer> v = new Vector<Integer>();
v.length(); // used with ()

Why is that? I mean an array is not an own class isn't it? So if it is no class it can't have a member varaible. I can't get an idea how that is handled in the background (ByteCode). I know that an array in the memory is stored with a pointer to the first element of the array and with the index (i) the memory pointer is shifted to ArrayPointer + i*(size of DataType).

Now you can say the computer goes throught all elements of an array and counts all the elements but how can a computer know where an array ends and where the next starts? And from where comes the 'member varaible' from the array where the size is stored?

I mean we use arrays so often but I know so little what happens behind the Java code in the ByteCode. Can you explain to me how that is possible?

Cilenco
  • 6,951
  • 17
  • 72
  • 152

5 Answers5

13

Arrays are objects in Java, but they don't correspond to real classes. Effectively, the JVM implicitly creates array classes on the fly, but for performance reasons, they aren't actual classes.

Since they are objects, they can be stored in Object fields and passed around like normal. However, they are treated a bit differently at the bytecode level.

First off, arrays are created with the newarray, anewarray, or multinewarray instructions for single dimension primative, single dimension object, and multidimensional arrays respectively. By contrast, regular objects are created with the new instruction.

Getting and setting elements is done with the *aload and *astore instructions.

Also, x.length is not a real field. Instead it gets compiled to the arraylength instruction. This can be seen by compiling the following code.

public void test(int size){
    int[] x = new int[size];
    String[] y = new String[size];
    System.out.println(x.length);
    System.out.println(y.length);
}

results in the following bytecode

.method public test : (I)V
    .limit stack 2
    .limit locals 4
    iload_1
    newarray int
    astore_2
    iload_1
    anewarray java/lang/String
    astore_3
    getstatic java/lang/System out Ljava/io/PrintStream;
    aload_2
    arraylength
    invokevirtual java/io/PrintStream println (I)V
    getstatic java/lang/System out Ljava/io/PrintStream;
    aload_3
    arraylength
    invokevirtual java/io/PrintStream println (I)V
    return
.end method

Attempting to access the length field by manually creating bytecode will result in an exception, because the field doesn't actually exist.

.method static public main : ([Ljava/lang/String;)V
    .limit stack 1
    .limit locals 1
    aload_0
    getfield [Ljava/lang/String; length I
    return
.end method

results in

Exception in thread "main" java.lang.VerifyError: Expecting reference to class i
n class ArrayTest at constant pool index 30 in method ArrayTest.main([Ljava/lang
/String;)V
        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
        at java.lang.Class.getMethod0(Unknown Source)
        at java.lang.Class.getMethod(Unknown Source)
        at sun.launcher.LauncherHelper.getMainMethod(Unknown Source)
        at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
Antimony
  • 37,781
  • 10
  • 100
  • 107
  • Wow thank you. That was the answer I wanted, to understand the logic behind the Java code. Thank you very much :) – Cilenco Dec 18 '13 at 06:55
  • So just to clarify, there's no means by which we can access the length of an array in Java other than using `.length`? – Mapsy Apr 28 '15 at 15:45
  • 1
    @Alex As far as I know, yes. Technically, you could do it via native code, but that probably isn't what you mean. – Antimony Apr 29 '15 at 02:29
  • I've been looking at the Java Bytecode lately and was wondering if the arraylength was a constant or does the JVM actively count each element in the array everytime? – Salsero69 Nov 28 '17 at 19:46
  • It's stored as part of the array object representation. Otherwise, the JVM would have no way to do bounds checking and no way to know how much memory to deallocate when freeing. For any given object, array length is a constant. – Antimony Nov 28 '17 at 21:51
1

Arrays in java have a class, and are therefore objects. Constructing it is done differntly from "normal" classs. More on that maybe in

Why isn't there a java.lang.Array class? If a java array is an Object, shouldn't it extend Object?

Community
  • 1
  • 1
jcklie
  • 4,054
  • 3
  • 24
  • 42
0

An array is actually a class ,it extends Object like any other class, but its been handled internally by the language for better performance and convenience .As a class it can have fields and methods.

SteveL
  • 3,331
  • 4
  • 32
  • 57
0

An array is an object you can try this yourself by simply assigning an array to an object value. For example:

public Object test(){
  int[] test = new int[5];
  Object obj = test; 
  return obj;
}

If you want to know what an array is on a byte level: the array itself is just pointer to a bit of information on the length of the array, some other information and a pointer to a piece of reserved memory in which you can store the data (sequential memory the size of your array). Accessing the data is a simple matter of looking up the [pointer]+[indexnumber]*[sizeofeachitem] and then you know which piece of memory to look at.

Thijser
  • 2,625
  • 1
  • 36
  • 71
-1

Array types actually are classes! As stored in memory, they enclose their basic class information (including the class information of their containing element if they aren't an array of natives), the number of elements they hold, and following that the actual array data. length in an array object is a final field rather than a method, because arrays never hold a different number of elements.

For other kinds of structures, like Vector, the number of elements in the object can change from moment to moment, so length() must be a method. Likewise with String: even though the String class is immutable, it inherits the length() method from CharSequence; some kinds of CharSequence can be variable in their length, so it is again implemented as a method.

Mumbleskates
  • 1,248
  • 10
  • 18
  • x.length is compiled to an arraylength instruction. It's not a real field. – Antimony Dec 17 '13 at 23:02
  • @Antimony The length of the array is actually stored in the header of its data, so it may as well be even if it isn't treated the same as other classes. Even the documentation for the effective implementation of the array classes refer to `length` as a `public final` field, even though it's treated as low level data in the JVM. – Mumbleskates Dec 17 '13 at 23:31
  • Except that the question asked about the bytecode level, and at the bytecode level, there's no such field. It's implemented as a special instruction. – Antimony Dec 18 '13 at 02:35
  • This was just me misconstruing the question; I gathered that they were looking for the bytewise representation of the data in memory, rather than the assembly instructions used. – Mumbleskates Jan 21 '14 at 21:29