一、从JVM底层来分析++i或者是i++
开本堂公开课的原因是上周一个同学在群里面问了一个问题,群里面的同学都在讨论,各种解释各种答案,可谓是百家齐放,百家争鸣,但是没有一个可靠权威的答案,老师今天就趁七夕给大家带来权威的解释(从jvm字节码层面分析)。
DEMO:群926452303里争论的问题
public class Hello{//public 修饰的类的名称要和文件名称保持一致(不考虑内部类的情况)
public static void main(String [] args){
int x=5;
x=++x + x++;
System.out.println(x);//
}
}
此时我们运行的结果是12,那为什么不是13呢?其实上代码分析到这里你发现了非常复杂难懂,自己都晕了,下面我们换一种更底层的思想来分析。
如果要彻底分析清楚这个问题,那么我们要从字节码指令层面来开始,如果要听懂本次课那么你先要掌握栈帧、操作数栈、局部变量的三个概念,现在就带着你来学习这几个概念。
1. 栈帧概念
在执行方法的时候jvm会在虚拟机栈中创建一个叫做栈帧的结构,这个栈帧由什么组成呢?分别由局部变量表、操作数栈、动态链接、返回地址、附加信息,那么与本次课有关是局部变量和操作数栈。
2.局部变量表
局部变量表是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。
3.操作数栈(栈顶)
操作数栈也常被称为操作栈,它是一个后入先出栈,当一个方法刚刚执行的时候,这个方法的操作数栈是空的,在方法执行的过程中,会有各种字节码指向操作数栈中写入和提取值,也就是入栈与出栈操作。例如,在做算术运算的时候就是通过操作数栈来进行的,又或者调用其它方法的时候是通过操作数栈来行参数传递的。
package com.sun;
public class Test {
public static void main(String[] args) {
int x=5;//局部变量,保存到一个叫做局部变量表的结构中
x=++x + x++;
System.out.println(x);
}
}
/**
Code:
stack=2, locals=2, args_size=1
0: iconst_5 //将一个int类型的常量5压入栈(栈顶)
1: istore_1 //将栈顶的元素弹出保存到局部变量1号位置中 此时就是x==5
2: iinc 1, 1 //表示局部变量表中1号位置的元素自增1 变成了x==6
5: iload_1 //第一次把局部变量1号位置的元素压入栈顶,此时栈顶的第一个元素变的值变成了6
6: iload_1 //第二次把局部变量1号位置的元素压入栈顶,此时栈顶的第二个元素变的值变成了6
7: iinc 1, 1 //表示局部变量表中1号位置的元素自增1 变成了x==7(但是与栈顶的两个元素无关)
10: iadd //将栈顶的两个元素弹出进行相加(6+6),之后在压入栈变成了12
11: istore_1 //将栈顶的元素弹出保存到局部变量1号位置中 此时局部变量1号位置变成12(x==12)
12: getstatic #2 //调用静态方法(与流有关)
15: iload_1
16: invokevirtual #3 //调用输出的方法在控制台输出 就是12
19: return
*/
DEMO:继续分析代码
//定义一个类
public class Hello{//public 修饰的类的名称要和文件名称保持一致(不考虑内部类的情况)
public static void main(String [] args){
int x=5;//局部变量,保存到一个叫做局部变量表的结构中
x=++x + ++x;
System.out.println(x);//本次代码输出的值是多少?
}
}
package com.sun;
public class Test {
public static void main(String[] args) {
int x=5;//局部变量,保存到一个叫做局部变量表的结构中
x=++x + ++x;
System.out.println(x);
}
}
/**
Code:
stack=2, locals=2, args_size=1
0: iconst_5
1: istore_1 x==5
2: iinc 1, 1 x== 6
5: iload_1 //栈顶元素值==6
6: iinc 1, 1 //x==7
9: iload_1 //栈顶的第二个元素就是7
10: iadd //栈顶的元素弹出相加再压入栈顶 变成13
11: istore_1 //x==13
12: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
15: iload_1
16: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
19: return
*/
最后
IT行业的道路固然是充满了阳光了,一路上充满了美景,但是也充满了艰苦和崎岖,在突破了之后一路的阴霾,云霄之上,必然是一番广阔的云海。
- 整理了一份关于java的系统化资料,从Javase- ssm-springcloud,包括了面试题,PDF电子书,网上商城项目,个人博客项目,分布式项目等都有想学习Java或者转行,大学生都非常实用,无任何套路免费提供,,加我裙下载,有什么问题都可以来问我----926452303点我即可进入
- 最新Java精讲视频,PDF书籍教程,面试题,学习手册
在这里说一下,因为我是自学出来的,也深知自学的艰苦,如果你现在也在自学Java,在自学的过程当中有遇见任何关于学习方法,学习路线,学习效率等方面的问题,资料都可以评论留言,有遇见任