JVM概念及虚拟机栈——JVM(1)

本文介绍了Java从编译到运行的过程,重点解析了JVM作为规范的角色,包括其跨平台性和语言无关性。讨论了JVM对内存的规范,特别是虚拟机栈的概念和实例演示,详细阐述了栈帧的结构。此外,还提到了本地方法栈、运行时数据区的其他区域以及JVM内存处理的初步理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.Java从编译到运行的过程

1.图示(JDK,JRE,JVM三者关系)

在这里插入图片描述
java文件经过javac的编译后形成了class字节码文件,然后送入JVM在JRE的类库的帮助下进行类加载。从这张图也可以看出JDK,JRE,JVM之间的关系。

2.三者关系

  • JVM: JVM只是一个翻译,把Class翻译成机器识别的代码,但是需要注意,JVM 不会自己生成代码,需要大家编写代码,同时需要很多依赖类库,这个时候就需要用到JRE。
  • JRE: JRE是什么,它除了包含JVM之外,还提供了很多的类库(就是我们说的jar包,它可以提供一些即插即用的功能,比如读取或者操作文件,连接网络,使用I/O等等之类的)这些东西就是JRE提供的基础类库。JVM 标准加上实现的一大堆基础类库,就组成了 Java 的运行时环境,也就是我们常说的 JRE(Java Runtime Environment)。
  • JDK: 但对于程序员来说,JRE还不够。我写完要编译代码,还需要调试代码,还需要打包代码、有时候还需要反编译代码。所以我们会使用JDK,因为JDK还提供了一些非常好用的小工具,比如 javac(编译代码)、javap(反编译)等。这个就是JDK。

二.JVM是一种规范

为什么说JVM是一种规范呢?有以下两个原因

①JVM的跨平台性

同一个Java程序,可以在多个不同的操作系统上执行,不受平台的影响(当然前提是你安装了属于此平台的JDK)。比如安装了windows版本的JDK,我的Java程序就可以在windows操作系统上面运行。

②JVM的语言无关性

JVM识别的就是class文件,不管你是什么语言,Java也好,kotlin也好,还是你自己创的语言也好,只要能编译成class文件,JVM就能识别并进行操作。

综上,我们说JVM是一种规范。

常见的JVM实现有
在这里插入图片描述
我们用的一般就是Hotspot
下面我们看一下JVM是怎么规范的

三.JVM对内存的规范

JVM在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,也就是对内存进行规范化。我们把进行规范化的这块区域叫做运行时数据区域。里面包含的内容如图所示
在这里插入图片描述
根据是否为线程共享,分成两部分。
一部分是线程共享区,里面有方法区(方法区在hotspot中有时被称为永久代、元空间)和,另一部分是线程私有区,里面有虚拟机栈本地方法栈程序计数器
除了运行时数据区域之外,还有没经过虚拟化的直接内存,也就是没经过规范化的内存。这部分也可以被Java程序所使用。比如电脑内存是16G,JVM占用了5G,那么剩下的11G就被称为直接内存。但是这部分使用起来不太方便。

1.虚拟机栈讲解

①概念

存储当前线程运行java方法所需的数据,指令,返回地址。有栈帧这个概念,一个方法就是一个栈帧。

②实例演示

在这里插入图片描述
比如这一段程序,是在main方法中A调用B,然后B调用C。那么在程序执行的过程中,虚拟机栈发生的变化是这样的。

首先main方法是主线程,我们命名为线程1,执行main方法的时候,main方法会作为一个栈帧,进入虚拟机栈内

在这里插入图片描述

然后main方法调用A方法,A方法作为另一个栈帧进入虚拟机栈

在这里插入图片描述

以此类推

在这里插入图片描述
在这里插入图片描述
虚拟机栈还可以进行大小设置,默认值取决于平台,具体怎么设置不用管。
这样的话就掌握了虚拟机栈和栈帧的概念了

2.栈帧里面有什么

在这里插入图片描述
一般来讲有四个,分别是局部变量表,操作数栈,动态连接(这个先不管),完成出口

  • 先解释下程序计数器吧,它指向当前线程正在执行的字节码指令的地址

我们换一张图,继续对栈帧进行细致的讲解
在这里插入图片描述
演示程序如下
在这里插入图片描述
这一部分演示程序非常简单,就不再解释了。我们之前说,JVM针对的是字节码文件即class文件,所以我们展示下上述代码编译后形成的class文件
我们只看work方法的红框部分
在这里插入图片描述
最左边的数字,后面带个冒号的那些数字,是字节码的地址,也就是字节码的偏移量,程序计数器保存的就是这个值。比如程序计数器保存着1,那么下一步就执行istore_1这个指令。OK,下面让我们来详细演示下这个过程。

iconst_1istore_1

在这里插入图片描述
在这里插入图片描述
后面两步和前两步一样.

iconst_2istore_2

在这里插入图片描述

③然后执行iload_1iload_2

在这里插入图片描述

iadd

在这里插入图片描述

bipush 10

在这里插入图片描述

imul

这个也是分了两步
在这里插入图片描述
后面两步就是把这个30存到局部变量表,然后又取出来,最后通过完成出口完成,并返回这个30。
完成出口是调用此方法的那个位置,比如这里是在main方法的第三行调用的此方法
在这里插入图片描述
那么完成出口可能就记3,然后方法返回的时候就通过3来返回到方法调用的位置,继续向下执行

OK,以上就是通过一段程序,来对栈帧里面的结构进行的介绍。

3.本地方法栈

本地方法栈跟 Java 虚拟机栈的功能类似,Java 虚拟机栈用于管理 Java 函数的调用,而本地方法栈则用于管理本地方法的调用。但本地方法并不是用 Java 实现的,而是由 C 语言实现的(比如Object.hashcode方法)。
本地方法栈是和虚拟机栈非常相似的一个区域,它服务的对象是 native 方法。你甚至可以认为虚拟机栈和本地方法栈是同一个区域。HotSpot直接把本地方法栈和虚拟机栈合二为一 。

4.运行时数据区中的其他区域

在这里插入图片描述
除了刚刚讲的线程私有区和直接内存,还有方法区和堆。那么一段程序执行后,某些代码在哪些区域是怎么划分的呢?看下面的代码
在这里插入图片描述

  • agesex都是静态变量或者常量,这些是跟随着类的,会在方法区里面。
  • 后两个objectisKing是成员变量,是跟随着对象的,等对象new出来之后他们才有,而对象是在堆里面new的,所以他们两个也在堆里面。
  • main方法里面的xy还有lobject都是局部变量,会在局部变量表里面。

四.深入理解JVM内存处理

实例代码
在这里插入图片描述
它运行的时候,内存处理的流程是

  • ①JVM申请内存
    ②初始化运行时数据区
    ③类加载
    ④执行方法
    ⑤创建对象

前三步完成以后,会是这个样子
在这里插入图片描述
最后创建对象,是这样子
在这里插入图片描述
那么对象创建了,如何进行回收呢?下篇文章将会详细讲解垃圾回收机制,现在我们只需要知道,堆可以分成两部分,新生代和老年代,新生代又可以分成三部分在这里插入图片描述

如图,蓝色的是新生代,橙色的是老年代。一个对象经过多次垃圾回收后都没被回收,那么它就会进入老年代。
了解到这里,就够了。

了解:JHSDB工具的使用

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值