java内存结构学习的一种打开方式
用Java开发已经四年,中途学了python,Scala,接触这些开发语言后,总感觉Java就像老奶奶裹脚——又臭又长。然,Java虐我千百遍,我待Java如初恋。聊起Java,不得不谈Java的内存结构,请注意,要区别Java内存模型(JMM,关于happens-before、读写屏障啥的)。
结构图
java内存结构包括5大部分,先来一张图围观一下:
其中堆存放的有对象实例、数组;局部变量表存储各种基本数据类型,对象引用(区别对象实例,这个是对象在堆中的地址);方法区存储已被虚拟机加载的类信息、常量、静态变量、即使编译器编译后的代码等数据。
what?这些和我学习Java有毛线关系?来,请思考下面这道题中i、j、k的值:
public static void main(String[] args) {
int i =1;
i =i++;
int j =i++;
int k = i + ++i *i++;
System.out.println("i = "+i);
System.out.println("j = "+j);
System.out.println("k = "+k);
}
我们需要知道,程序的执行就是不断入栈出栈的过程,int i =1,就是在本地变量表中存入i的值1,先来撸张初始状态的图。
i =i++;
这个操作执行了下面的过程:
- 将i 的值1压入操作数栈;
- 修改局部变量表中的i值,为2;
- 赋值语句执行出栈操作,将操作数栈中i的值1返回给局部变量表中的i。
这个操作执行后你会神奇的发现:原来啥子也没有变。
int j =i++;
这个操作执行了下面的过程:
- 在局部变量表中添加变量j;
- 将i的值入栈,为1;
- 修改局部变量表中的i值,为2;
- 赋值语句将操作数栈中的i出栈,赋值给j,为1;
此时内存中的变量状态如下:
int k = i + ++i *i++;
这个操作执行了下面的过程:
- 在局部变量表中添加变量k;
- 将i的值加入操作数栈,为2;
- 将局部变量表中的i值加1,为3(注意++i和i++执行顺序的区别);
- 将局部变量表中的i值加入操作数栈,为3(第二个i);
- 将局部变量表中的i值再次加入操作数栈,为3(第三个i);
- 将局部变量表中的i值加1,为4;
- 赋值语句执行出栈操作 3+3+2,将值11赋值给k;
下面的图是没有执行赋值语句前的内存中变量状态:
相信你已经知道最后的结果了吧:
i = 4
j = 1
k = 11
你是不是要感叹下:原来还能这样…