首先我们要知道:
- 线程的本质是栈;
- 程序执行时,在java栈中,成立一个线程栈,调用方法时方法不断压栈出栈,这个压栈出栈的过程就是线程执行的过程。
- 方法执行 拷贝入栈 ,执行完成 出栈,从第一个线程入栈开始到最终出栈,就是一个线程的过程。
java内存图
以下段代码为例画内存图
public class Test {
public static void main(String[] args) throws Exception {
Person x1 = new Person();
Person x2 = new Person();
Person x3 = new Person();
m1();
x1.m1();
}
public static void m1(){
m2();
}
public static void m2(){
m3();
}
public static void m3(){
Person x1=new Person();
x1.m2();
}
public static void m4(){
}
}
public class Person {
public void m1() {
}
public void m2() {
m3();
}
public void m3() {
}
}
1、java文件在硬盘上,通过编辑器编译为.class文件,类信息文件首先加载进方法区中。
2、我们有Person类和Test类,将这些类信息加载到方法区,对于Test中的5个静态方法main \ m1 \ m2 \ m3 \ m4会在方法区额外开辟一块地方存放,即静态域
3、首先主方法执行, 主方法被拷贝一份入栈。
3.1、Person x1=new Person() ,Person x2=new Person(),Person x3=new Person()new出来的对象在方法堆中。
3.2、变量后边的数字表明的是对应地址
3.3、如果Person类中加入变量怎么画? -- 一样的道理
- 只需要在方法区Person内加入变量,new出来到堆里也增加相应变量就行了
3.4、如果Person类中添加静态方法呢?
- 静态属性需要在方法区内的静态域存放
- static修饰成员变量表示该成员变量只在内存中只存储一份,可以被共享访问、修改
- 注意new出来放入堆中的对象属性,不管是变量还是方法都是非静态的
4、接着调度m1(),m1()拷贝入栈;m1()中调度m2(),m2()拷贝入栈;m2()中调度m3(),m3()拷贝入栈;
5、m3()中new了个对象x1,这个对象在堆中创建
6、x1调度了方法m2(),x1对象内的m2()拷贝入栈(注意是从堆那边拷贝入栈)
7、接着x1调度了方法m2(),但m2()方法内调度了m3(),m3()拷贝入栈;
8、m3运行完后出栈,m2方法是调度m3,运行完后也出栈
9、接下来是T.m3(),已经运行完了也出栈,同时创建的对象x1也会被销毁;
10、在堆中的x1对象由于地址没有被记录了,也随之销毁
11、接着调度m3的m2()完成任务后也出栈
12、调度m2的m1()完成任务后也出栈
13、m1()完成后,主方法内还有x1.m1() 待执行;
14、将x1的m1()拷贝入栈
15、x1.m1() 执行完后,m1()出栈
16、这时主方法已经全部执行完毕,主方法出栈
17、主方法内的变量销毁,以及堆中对应的对象没有地址指向后也随之销毁
这就是java执行过程的内存图。