Java内存模型与生命周期以及JVM

Java内存模型与生命周期以及JVM

JVM简介

虚拟机

所谓虚拟机就是一台虚拟的计算机。它是一款软件,用来执行一系列虚拟计算机指令。大体上, 虚拟机可以分为系统虚拟机和程序虚拟机。

Java虚拟机

Java虚拟机是一台执行Java字节码的虚拟计算机,它拥有独立的运行机制,其运行的Java字节码也未必由Java语言编译而成。

Java技术的核心就是Java虚拟机,因为所有Java程序都运行在Java虚拟机内部

JVM特点
  • 一次编译,到处运行
  • 自动内存管理
  • 自动垃圾回收功能

JVM的位置

JVM是运行在操作系统上的,它与硬件没有直接的交互。

JVM的整体结构

截屏2021-07-18 下午5.00.52

Java代码执行流程

截屏2021-07-18 下午5.05.44

JVM的生命周期

启动

Java虚拟机的启动是通过引导类加载器创建一个初始类完成的,这个类是由虚拟机的具体实现指定的。

执行

  • 一个程序中的Java虚拟机有着一个清晰的任务:执行Java程序。
  • 程序开始时他才运行,程序结束时他就停止。
  • 执行一个所谓的Java程序的时候,真真正正执行的是一个叫做Java虚拟机的进程。

退出

  • 程序正常执行结束
  • 程序异常或错误而异常终止
  • 操作系统错误导致终止
  • 某线程调用Runtime类或System类的exit方法,或Runtime类的halt方法,并且java安全管理器也允许这次exit或halt操作
  • 除此之外,JNI规范描述了用JNI Invocation API来加载或卸载Java虚拟机时,Java虚拟机的退出情况

JVM的内存结构

JVM内存空间包含:方法区、java堆、java栈(虚拟机栈)、本地方法栈、PC程序计数器。

Java虚拟机定了了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁。另外一些则是与线程一一对应的,这些与线程对应的数据区域会随着线程开始和结束而创建和销毁。

如图,灰色的区域为单独线程私有的,红色的为多个线程共享的,即

  • 每个线程:独立包括程序计数器、栈、本地栈
  • 线程间共享:堆、堆外内存(方法区、永久代或元空间、代码缓存)

程序计数器

JVM中的程序计数寄存器(Program Counter Register)中,Register的命名源于CPU的寄存器,寄存器存储指令相关的现场信息。CPU只有把数据装载到寄存器才能够运行。JVM中的PC寄存器是对屋里PC寄存器的一种抽象模拟。

作用

PC寄存器是用来存储指向下一条指令的地址,也即将将要执行的指令代码。由执行引擎读取下一条指令。

  • 它是一块很小的内存空间,几乎可以忽略不计。也是运行速度最快的存储区域
  • 在jvm规范中,每个线程都有它自己的程序计数器,是线程私有的,生命周期与线程的生命周期保持一致
  • 任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。程序计数器会存储当前线程正在执行的java方法的JVM指令地址;或者,如果实在执行native方法,则是未指定值(undefined)。
  • 它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成
  • 字节码解释器工作时就是通过改变这个计数器的值来选取下一步需要执行的字节码指令
  • 它是唯一一个在java虚拟机规范中没有规定任何OOM情况的区域

内存中的堆和栈

  • 栈是运行时的单位,而堆是存储的单位
    即:栈解决程序的运行问题,即程序如何执行,或者说如何处理数据。堆解决的是数据存储的问题,即数据怎么放、放在哪儿。
  • 一般来讲,对象主要都是放在堆空间的,是运行时数据区比较大的一块
  • 栈空间存放 基本数据类型的局部变量,以及引用数据类型的对象的引用
虚拟机栈
  • java虚拟机栈(Java Virtual Machine Stack),早期也叫Java栈。 每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应这个一次次的java方法调用。它是线程私有的

  • 生命周期和线程是一致的

作用:

  • 主管java程序的运行,它保存方法的局部变量(8种基本数据类型、对象的引用地址)、部分结果,并参与方法的调用和返回。
栈的特点
  • 栈是一种快速有效的分配存储方式,访问速度仅次于PC寄存器(程序计数器)
  • JVM直接对java栈的操作只有两个
    • 每个方法执行,伴随着进栈(入栈,压栈)
    • 执行结束后的出栈工作
  • 对于栈来说不存在垃圾回收问题

  • 一个jvm实例只存在一个堆内存,堆也是java内存管理的核心区域。
  • Java堆区在JVM启动的时候即被创建,其空间大小也就确定了。是JVM管理的最大一块内存空间(堆内存的大小是可以调节的)
堆的细分内存结构
  • JDK 7以前: 新生区+养老区+永久区
  • JDK 8以后: 新生区+养老区+元空间

方法区

方法区可以看作是一块独立于Java堆的内存空间。

  • 方法区(Method Area)与Java堆一样,是各个线程共享的内存区域
  • 方法区在JVM启动时就会被创建,并且它的实际的物理内存空间中和Java堆区一样都可以是不连续的
  • 方法区的大小,跟堆空间一样,可以选择固定大小或者可拓展
方法区的内部结构

分析JVM情况

堆、栈、方法区的交互关系

具体分析
public class SimpleHeap {
    private int id;

    public SimpleHeap(int id) {
        this.id = id;
    }

    public void show() {
        System.out.println("My ID is " + id);
    }
    public static void main(String[] args) {
        SimpleHeap sl = new SimpleHeap(1);
        SimpleHeap s2 = new SimpleHeap(2);

        int[] arr = new int[10];

        Object[] arr1 = new Object[10];
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值