通过字节码扒一扒java编译器瞒着我们做了什么(3)

来源:互联网 发布:java序列化 编辑:程序博客网 时间:2024/06/05 19:56

 1.      数组和二维数组在字节码中的实现

源码:

    int[] list1 = {1,2};

int[][] list2 = {{1,2},{3,4}};

字节码:

  int[] list1;

    descriptor: [I

    flags:

 

  int[][] list2;

    descriptor: [[I

flags:

 

        10: aload_0

        11: iconst_2

        12: newarray       int

        14: dup

        15: iconst_0

        16: iconst_1

        17: iastore

        18: dup

        19: iconst_1

        20: iconst_2

        21: iastore

        22: putfield      #24                 // Field list1:[I

        25: aload_0

        26: iconst_2

        27: anewarray     #26                 // class "[I"

        30: dup

        31: iconst_0

        32: iconst_2

        33: newarray       int

        35: dup

        36: iconst_0

        37: iconst_1

        38: iastore

        39: dup

        40: iconst_1

        41: iconst_2

        42: iastore

        43: aastore

        44: dup

        45: iconst_1

        46: iconst_2

        47: newarray       int

        49: dup

        50: iconst_0

        51: iconst_3

        52: iastore

        53: dup

        54: iconst_1

        55: iconst_4

        56: iastore

        57: aastore

        58: putfield      #27                 // Field list2:[[I

--红色部分是一维数组的初始化过程,注意命令newarray,可见在java中数组是分配到堆内存的对象,绿色部分是二维数组的初始化过程,注意27: anewarray     #26                 // class "[I"这行,意思是new 出一个存储引用类型的数组,而这个引用类型是类型[I,什么意思,这是int[]类型的签名,所以可见数组在java中不是基础类型而是个类类型。然后分别new两个一维数组并初始化后加入new出来的二维数组中。

 

2.数组和ArrayList的区别:

之前一直有个疑问,数组会不会也是颗语法糖,会不会编译器最终还是把数组转化成ArrayList类型,通过字节码可以发现,两者是不同类类型。

源码:

int[]list1 = {1,2};

List<String>list3 = new ArrayList<String>();

 

字节码:

 

  int[] list1;

    descriptor: [I

flags:

  java.util.List<java.lang.String> list3;

    descriptor: Ljava/util/List;

    flags:

Signature: #16                          // Ljava/util/List<Ljava/lang/String;>;

 

 10: aload_0

 11: iconst_2

 12: newarray       int

 14: dup

 15: iconst_0

 16: iconst_1

 17: iastore

 18: dup

 19: iconst_1

 20: iconst_2

 21: iastore

 22: putfield      #24                 // Field list1:[I

 

        61: aload_0

        62: new           #29                 // class java/util/ArrayList

        65: dup

        66: invokespecial #31                 // Methodjava/util/ArrayList."<in

it>":()V

 

--红色部分是一维数组的初始化指令,而绿色部分是ArrayList的初始化指令,显而易见,两者根本不是同种类类型,编译器并没有帮我们做转换。

 

3.可见性关键字volatile:

源码:

volatileint a = 99;

字节码:

  volatile int a;

    descriptor: I

flags: ACC_VOLATILE

       4: aload_0

       5: bipush        99

       7: putfield      #24                 // Field a:I

--可见,对于volatile定义的成员,字节码中成员声明和正常的int 成员是不同的,但是初始化过程跟正常int成员一模一样,说明,可见性是由JVM来保障的,并非由代码保障的。估计是JVM遇到volatile变量就会禁止各个线程的寄存器拷贝该变量以此保障volatile变量在多线程中的可见性。

 

4.null对象是什么?

源码:

Arraylist4 = null;

字节码:

       72: aload_0

       73: aconst_null

       74: putfield      #36                 // Field list4:Ljava/lang/reflect/

rray;

--可见null在字节码中就是null。