一个函数的调用过程
代码:
public class Main {
public static void main(String args[]) {
int a = 1;
int b = 2;
int t = a + b;
}
}
首先我们先看字节码:
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: istore_3
8: return
虚拟机会开辟一段内存做为栈帧.栈帧上有局部变量表,还有操作数栈.暗蓝色代表局部变量表:
0: iconst1: 将常量 1 放入操作数栈顶
1: istore1: 取出栈顶值(出栈操作),放入局部变量表第一个位置,这时 frame 栈帧 变成了这样:
2,3 步同理
4,5 iload; 取出对应局部变量表的值,并存入操作栈顶 (取 a 值 1 送入操作栈顶,然后取 b 值 2 送入操作栈顶),现在变为这样
6 iadd: 对操作栈顶 2 个数据做出栈操作,求和后送入栈顶,结果为操作栈只有一个数,3
7. istore3: 同理,取出栈顶值,放入局部变量表第三个位置
栈和堆
堆(heap)是一块独立的内存空间.在创建对象的时候, 我们可以把真正的对象放到堆里,只在栈里记录这个对象的地址就可以了
现在有如下代码:
public class Main {
public static void main(String args[]) {
A a = new A(1);
A b = new A(2);
swap(a, b);
System.out.println("a's value is " + a.value +", b's value is " + b.value);
}
public static void swap(A a, A b) {
int t = a.value;
a.value = b.value;
b.value = t;
}
}
class A {
public int value;
public A(int v) {
this.value = v;
}
}
传入 swap 的都是副本,但是都是指向同一个地址,所以 swap 是可以正常修改对象值的,相反的,如果传入的参数是 primitive type,那么在 swap 里修改的就是副本的值了,对原值没有任何影响
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于