通过字节码扒一扒java编译器瞒着我们做了什么(3)
2017-07-24 11:20
197 查看
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。
源码:
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。
相关文章推荐
- 通过字节码扒一扒java编译器瞒着我们做了什么(1)
- 通过字节码扒一扒java编译器瞒着我们做了什么(2)
- 什么是使用记录访问权限呢?这是在Android5.0(Api level 21)新添加的,通过该权限我们可以查看设备上其它应用使用情况的统计信息等。
- 通过Volley我们能学到什么?(2) — 刨析网络请求框架
- ping域名怎么用?通过ping域名我们能看见什么?
- 我们通过Kotlin得到了什么?
- 通过Volley我们能学到什么?(3) — 缓存原理
- 【大数据部落】通过数据挖掘我们能从股市数据得到什么
- 对于SQL的Join,在学习起来可能是比较乱的。我们知道,SQL的Join语法有很多inner的,有outer的,有left的,有时候,对于Select出来的结果集是什么样子有点不是很清楚。Coding Horror上有一篇文章,通过文氏图 Venn diagrams 解释了SQL的Join。我觉得清楚易懂,转过来。 交差集" cross join 《Linux命令行与shell脚本编程大全
- Dagger是什么和我们怎么通过使用它获得收获
- 通过Volley我们能学到什么?(1) — 工作原理与设计模式
- 我们可以通过结构和指针构建强大的数据结构
- 我们访问一个页面的时候都做了什么
- java中反射机制通过字节码文件对象获取字段和函数的方法
- 我们做什么人才?看李开复北大演讲主题21世纪最需要的7种人才
- 管中窥豹--我们见到了什么?
- 高斯混合模型Gaussian Mixture Model (GMM)——通过增加 Model 的个数,我们可以任意地逼近任何连续的概率密分布
- IE9的Beta的发布给我们带来了什么?
- 核高基是什么意思?为什么要搞核高基?核高基与我们有啥关系?
- 管中窥豹--我们见到了什么?