zoukankan      html  css  js  c++  java
  • Java 执行过程中的内存模型

    一、前言

    本文的主要工作:尝试以时间顺序追踪一遍 Java 执行的整个过程,以及展示 JVM 中内存模型的相应变化。

    本文的主要目的:希望能够通过 Java 执行过程的冰山一角,增进对编程语言工作原理的理解。

    以下面这段代码为例,追踪它的执行过程:

    public class Car {
        private int speed;
    
        public void setSpeed(int speed) {
            this.speed = speed;
        }
    
        public void getSpeed() {
            System.out.println(speed);
        }
    
        public static void main(String[] args) {
            Car car = new Car();
            car.setSpeed(3);
            car.getSpeed();
        }
    }
    

    二、执行过程

    接下来是具体的执行过程,总共包含五个步骤:编译、加载、执行 main 方法、执行成员方法、方法返回。

    Step1:编译

    首先,在我们完成上述这段源码之后,要想让程序跑起来,我们需要将其编译成为字节码文件。字节码是一种跨平台的JVM机器语言,它能够被JVM所解析,而无关底层的操作系统。

    Step2:加载

    当代码需要被调用时,JVM 会加载目标字节码至方法区,并转化为方法区的运行时数据结构,这里的加载过程是通过类加载器完成的。然后内存中(不一定是堆)会生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据结构的访问入口。

    Step3:执行 main 方法

    main 方法可以通过 java.lang.Class 对象进行调用,参考如下代码:

    Method method = targetClass.getDeclareMethod("main", String[].class);
    method.invoke(null, (Object) new String[0]);
    

    之后 PC 寄存器将会指向方法区中的 main 函数地址,线程栈中会生成对应的栈桢,其主要用于存放当前方法的局部变量表、操作栈、以及方法返回地址。接下来,PC 寄存器向后地址偏移,执行引擎开始执行 main 方法体。当语句 Car car = new Car() 执行完毕,栈桢与堆中的相应变化如下:

    Step4:执行成员方法

    对象 car 的 setSpeed 方法调用过程和 main 类似,通过索引 car 的成员方法地址,PC寄存器将指向方法区中的 setSpeed 函数地址,同时线程栈中将产生新的栈桢,其中的方法返回地址用于保存原有 PC 地址偏移。当赋值语句 this.speed = speed 执行完毕,栈桢与堆中发生的相应变化如下:

    Step5:方法返回

    随着 setSpeed 方法的执行结束,Stack 中的相应栈桢出栈,栈顶指针重新指向 main 栈桢。同时 PC 寄存器将根据方法返回地址进行还原,从而继续执行 main 的方法体。当 main 方法也执行完毕出栈后,主线程与虚拟机实例销亡,程序结束。

    三、杂谈

    虚拟机或某一门程序语言,作为一种底层实现,可以满足上层用户的绝大部分需求,但是需求是与时俱进的,总有一天用户需要编写自己的底层实现,比如组件、框架、一门新语言。这时需要打开原有的规范,先破坏它,再重建它,从而定义自己的规范。这也许是我们需要探究底层的缘由之一吧。


    参考链接

    [1] <<深入理解Java虚拟机>>
    [2] https://www.cnblogs.com/zzzz76/p/9282981.html
    [3] https://www.cnblogs.com/zzzz76/p/8150862.html
    [4] https://www.cnblogs.com/zzzz76/p/8076536.html

  • 相关阅读:
    SSM——事务配置
    SSM——Spring+Mybtis整合(代理【mapper】开发模式)
    objective-c(五)关于代码块的使用
    objective-c(四)内存管理
    objective-c(三)类与对象的方法调用
    objective-c(二)基本数据类型介绍
    objective-c(一)关于基本数据类型打印输出方式
    Eclipse启动发生的错误:An internal error occurred during: "Initializing Java Tooling".
    单例模式
    Java 代理模式
  • 原文地址:https://www.cnblogs.com/zzzz76/p/14353483.html
Copyright © 2011-2022 走看看