众所周知,在java中数组也是一种对象,而对象在被创建的时候会隐式地调用其构造方法,在字节码中为:
new #1 //创建实例并将引用压入栈顶 #1为常量池中此类的符号引用
dup //将栈顶元素复制一份并压栈
invokespeclal #2 //将栈顶引用作为参数顶用构造方法 #2为常量池中构造方法的引用<init>
创建数组对象的字节码有newarray,anewarray,以及multianewarray,创建数组对象的字节码为:
newarray #1 //同上
astore_1 //将数组引用放入局部变量表索引为1的位置
可以看到,数组创建时并没有调用其构造方法,今天看《javase8虚拟机规范》时发现有一句“数组并没有外部的字节码文件,不会由类加载器加载,而是由jvm自己生成的”.....那我们来深入♂了解一下数组到底是什么鬼。
首先在idea中创建两个数组,比较其Class是否为同一个
答案为true,再来
答案为false,再来
答案为false。所以大致可以了解到,数组在相同的类型相同维数时Class是同一个,不同类型同一维数会新生成一个Class
emmmm,怪不得jvm要自己创建数组的Class,要是从外部加载,那岂不是......一个维度一个类型就得一个Class文件,那还怎么玩?所以jvm采用按需进行创建,在方法区没有对应类型的Class时,再由jvm创建。
那jvm自己生成的数组字节码到底是啥样的呢?我们用jdk自带的hotspot来进行查看一下吧。
首先编写一个Test类,编译运行!
然后我们用jps(GPS????)来确定Test的pid(后面hotspot会用到),
1566 Test 嗯pid为1566
那么我们来打开hotspot把
啊!麦芽的香气。然后在菜单栏 File=>Attach to Hotspot....弹出的框框中输入pid。
然后打开其tools=>Class Brower
然后依次点击public class Test,void main()....
看吧,在anewarray后面果然没有调用自己的构造方法,我们进常量池看看吧,点击底部的Constant Pool
31、32、33、26、27、28分别为jvm创建的一维数组,二维数组的符号引用,以[Ljava/lang/String 为例 [L是字段描述符,意思是一维对象类型为java/lang/String 的数组,两个[[ 就是二维的意思。
那么真相大白了,jvm给我们的Class文件是这些,而数组Class文件的结构呢?,嗯,或许是能力问题吧,没找到。
我猜测可能jvm并没有真正的生成Class文件,而是形式上创建了Class文件,因为我找不到生成的字节码在哪emmm,不过可以确定的是数组类没有构造方法,字段,普通方法