Jvm 内存模型之二撩裙边/方法执行

Jvm 内存模型之初探花裙中我们已经大致了解了jvm内存的逻辑结构以及各个存储区域的作用。然而在迈向资深老司机的道路上,浅尝辄止可不行,撩起花裙加深印象才符合老司机的风格。接下来咱们可以一个java类文件来研究类执行过程中其各个部分如何与jvm内存逻辑模型的各个部分映射的。

public class HelloWorld implements Runnable {

    private String[] aHeapStringArray = {"a"+"a"};

    private static String aStaticString = "aa";

    private final String aFinalString = "aa";

    static {
        System.out.println("hello world on load");
    }

    public void aVoidMethod(){
        int aInt = 888;
        System.out.println("hello world thread end");
    }

    @Override
    public void run() {
        aVoidMethod();
    }

    public static void main(String[] agr) throws InterruptedException {
        int aInt = 888;
        Thread thread = new Thread(new HelloWorld());
        thread.start();
        Thread.sleep(aInt);
        System.out.println("main thread end");
    }
}

这个类实现了Runnable 接口,共包含三个属性、三个方法、一个静态代码块。那么就从作为入口的main方法开始逐步分析。
第一步:在执行main方法之前,需要先载入HelloWorld的class文件

  1. jvm会先去方法区查找是否存在HelloWorld类信息。
  2. 当jvm未查找到HelloWorld类的相关信息时会去classpath下找到HelloWorld的class文件并装载,将class文件的字节流结构化到方法区的存储空间中。
  3. 装载完成后,在链接时将class包含字面量”a”,”aa”,888,”hello world on load”,”hello world thread end”,”main thread end” 并将这些字面量存入常量池。可以注意到,程序中出现了多处”a”,”aa”,888等字面量,但是在常量池中每个字面量仅会存储一份。可简单理解为常量不重复。然后将代码中的字面量替换为引用。
  4. 链接完成后,类初始化过程开始,并执行class包含静态代码。调用系统函数输出”hello world on load”。至此class载入及初始化过程完成。

第二步:jvm调用main方法

  1. jvm启动一个线程调用HelloWorld,即执行主线程。
  2. 根据main方法中的局部变量,例如int aInt 、Thread thread、返回值信息等生成栈帧并将栈帧压入虚拟机栈。
  3. 修改主线程的程序计数器数值,记录当前执行的字节码代码行号。(伴随着代码执行同步修改的,下文中不再说明)
  4. 调用Thread的构造方法,生成该方法的栈帧压栈。
  5. 调用HelloWorld的构造方法(由于HelloWorld没有构造方法,此处调用默认构造方法),生成此构造方法的栈帧并压入虚拟机栈(为了简化理解此处忽略了调用父类的构造方法过程,姑且任务此时处于栈顶)。
  6. 向堆内存申请一块内存区域存储HelloWorld的实例,实例中至少包含对于其他对象的引用(例如数组引用),类信息等。
  7. 执行完HelloWorld的构造方法后返回HelloWorld对象实例的引用, HelloWorld的栈构造方法的栈帧弹栈,并继续执行当前栈顶的Thread的构造方法。
  8. Thread构造方法执行完毕,将此线程的对象存放在Thread thread的引用中。
  9. 将Thread的start方法入栈,执行start方法,启动hello world 线程。主线程程序计数器记录当前主线程代码执行位置。
  10. 若cpu切换至hello world 线程时,新增一个程序计数器,新增虚拟机栈,将run方法压栈,开始执行run方法。
  11. 若cpu切换回主线程,则主线程根据程序计数器记录的位置继续执行。
  12. 当主线程虚拟机栈的方法全部弹出时主线程执行完毕,hello world 线程同理。至此,方法执行完毕。

其实jvm执行类的细节远比上文描述中复杂,本文的目的仅仅是梳理类执行的过程与jvm内存模型中的各个部分关系。若需详细了解其执行细节,还需要进一步梳理。


小弟原创,欢迎拍砖

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值