The JavaTM Virtual Machine Specification Second Edition
5.3.3 Creating Array Classes
The following steps are used to create the array class C denoted by N using class loader L. Class loader L may be either the bootstrap class loader or a user-defined class loader.
If L has already been recorded as an initiating loader of an array class with the same component type as N, that class is C, and no array class creation is necessary. Otherwise, the following steps are performed to create C:
If the component type is a reference type, the algorithm of this section (§5.3) is applied recursively using class loader L in order to load and thereby create the component type of C.
The Java virtual machine creates a new array class with the indicated component type and number of dimensions. If the component type is a reference type, C is marked as having been defined by the defining class loader of the component type. Otherwise, C is marked as having been defined by the bootstrap class loader. In any case, the Java virtual machine then records that L is an initiating loader for C (§5.3.4). If the component type is a reference type, the accessibility of the array class is determined by the accessibility of its component type. Otherwise, the accessibility of the array class is public.
http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html#79473
1.类加载器检查数组类是否已经创建了。没有,则需要创建数组类。否则,就无需创建了。
2.如果数组元素是引用类型,那么类加载器会先加载数组类。
3.JVM根据元素类型和维度,创建相应的数组类。 (解释:数组类由维度和定义类型所决定,即维度不同类型相同则不属于同一个类,维度相同类型相同(即使长度不一样)才是同一个类,(注意:长度不是这个类的成员变量,虽然看上去很像,我们可以通过反射的机制检查下))
1.为什么获取数组的长度用.length(成员变量的形式),而获取String的长度用.length()(成员方法的形式) class loader加载完数组类后,都是调用 arraylength,对于String本身是一个新的不同于数组类的对象,暴露的length()方式也是arraylength的调用
2.数组对象的类是什么? 不是java.util.Arrays,首先需要明确和这个没有关系 数组类由维度和定义类型所决定,即维度不同类型相同则不属于同一个类,维度相同类型相同(即使长度不一样)才是同一个类,(注意:长度不是这个类的成员变量,虽然看上去很像,通过反射的机制检查下)....这个类是一个非法命名类,估计是为了避免和其他自定义类产生冲突,java.lang.Class 550行中有描述
3.JVM没有为数组类生成length这个成员变量,那么Array.length这样的语法如何通过编译执行的?需要阅读字节码
int[] xxx = new int[1];
Class clazz = xxx.getClass();
//class [I 没有任何package的非法类名
//数组的类名由若干个'['和数组元素类型的内部名称组成,'['的数目 代表了数组的维度
System.out.println(xxx.getClass().getName());
System.out.println(clazz.getDeclaredFields().length);
System.out.println(clazz.getDeclaredMethods().length);
System.out.println(clazz.getDeclaredConstructors().length);
System.out.println(clazz.getDeclaredAnnotations().length);
System.out.println(clazz.getDeclaredClasses().length);
System.out.println(clazz.getSuperclass());
[I
0
0
0
0
0
class java.lang.Object
public class Test {
public static void main(String[] args) {
int ab[] = new int[3]; int ii = ab.length;
}
}
public static void main(java.lang.String[]);
Code:
Stack=1, Locals=3, Args_size=1
0: iconst_3 //将int型常量3压入操作数栈
1: newarray int //常量3出栈,初始化维度为1个int数值,引用压栈
3: astore_1 //引用出栈,保存索引到1位置(即将数组引用赋值给ab)
4: aload_1 //将ab压栈(ab.length调用)
5: arraylength //ab出栈,获取数组长度(具体长度获取由jvm获取),将数组长度压栈
6: istore_2 //变量存贮数组长度到索引2位置
7: return
LineNumberTable:
line 3: 0
line 4: 7
}
编译器也可以对Array.length()这样的语法做特殊处理,直接编译成arraylength指令。这样的话,我们就可 以使用方法调用的风格获取数组的长度了,这样看起来貌似也更加OO一点。那为什么不使用Array.length()的语法呢?也许是开发Java的那帮 天才对.length有所偏爱,或者抛硬币拍脑袋随便决定的吧。 形式不重要,重要的是我们明白了背后的机理。
java要比c/c++中的数组更安全,Java使用特定的指令访问数组的元素,这些指令都会对数组的长度(arraylenth)进行检查,java.lang.ArrayIndexOutOfBoundsException
汇编书籍推荐< >王爽
没有评论:
发表评论