JVM内存模型介绍

news2024/9/28 7:26:19

9211cb6bad7d406dbe5a4765a34c04b6.jpgJVM(Java Virtual Machine)又被分为三大子系统,类加载子系统,运行时数据区,执行引擎。在这里我们主要讲解一下JVM的运行时数据区,也就是我们常说的JVM存储数据的内存模型。在这里提一点,平常我们常说内存模型,其实在Java中存在两大内存模型,一个是JVM的内存模型,也就是堆,栈之类的。还有一个是Java线程工作的内存模型,java工作的内存模型指的是主内存,工作内存,两个是不同的概念

 

 

JVM的结构图

 

 

 

​ 这里重点讲一下JVM的运行时数据区,也就是我们所说的JVM内存模型。其实像JVM结构中的类加载子系统,也能够讲出很多东西出来。

 

​ 首先,JVM的内存模型分为线程私有,线程共享的区域

 

线程私有部分

 

​ 图中所画的部分程序计数器,虚拟机栈,本地方法栈是每个线程私有的部分,大概讲述一下每个部分所起到的作用

 

​ 程序计数器:线程在运行期间,由于会出发CPU时间片资源抢夺的情况,假如线程A执行到if判断,循环,异常处理等这些字节码指令,时间片突然被抢占,出现阻塞,程序计数器会帮助记录每个线程所执行到下一条字节码指令,等线程A再次拿到时间片继续执行。

 

 

​ 虚拟机栈:每个线程在执行每个方法时,都会创建一个栈帧,栈帧里面又会包括一些局部变量表,操作数栈,方法出口等信息,每个方法从执行到执行完成,也就是完成我们的入栈和出栈过程

 

​ 首先看一段代码,来讲解栈帧中每个部分的作用

 

public class Test {

 

    public static void test() {

        int a = 1;

        int b = 2;

        int c = (a + b) * 10;

    }

 

    public static void main(String[] args) {

        test();

    }

}

​ 以上代码对应的虚拟栈图

 

 

 

​ 局部变量表:在我们程序中,方法中定义的一些局部变量都会存放在我们的局部变量表,也就是我们代码中的a,b,c这种局部变量

 

​ 将上述代码用javap -c Test命令可以查看到程序的字节码指令

 

public class com.ezhiyang.crm.config.Test {

  public com.ezhiyang.crm.config.Test();

    Code:

       0: aload_0

       1: invokespecial #1 // Method java/lang/Object."<init>":()V

       4: return

 

  public static void test();

    Code:

       0: iconst_1 // 将一个常量1加载到操作数栈

       1: istore_0 // 将一个数值(也就是常量1)从操作数栈存储到局部变量 表,也就是我们代码中的int a = 1

       2: iconst_2

       3: istore_1

       4: iload_0

       5: iload_1

       6: iadd // 执行加法操作

       7: bipush // 将10入操作数栈 10

       9: imul // 执行乘法操作

      10: istore_2 // 再将乘法出来的结果从操作数栈存储到局部变量 表,也就是我们的int c = (a + b) * 10

      11: return

 

  public static void main(java.lang.String[]);

    Code:

       0: invokestatic #2 // Method test:()V

       3: return

}

 

​ 操作数栈:像我们的程序后面都会被编译成这种字节码指令,而操作数栈将变量之间的运算入栈,然后存储计算结果,再出栈赋值给局部变量表

 

​ 方法出口:代码中main()方法调用了test()方法,这时test()执行完成后,需要继续执行main()方法,方法出口记录了test()方法执行完成后的一个出口,也就是回到main()

 

​ 本地方法栈:在Java代码中我们有时可以看到用native修饰的方法,而这些方法并不由Java语言去实现,而是由Java去调用底层的C++语言实现的,跟我们的虚拟机栈有点类似,只不过是执行native方法的线程栈帧

 

线程共享部分

 

​ 线程共享的部分就是我们图中所画的堆,方法区(又叫做永久代,JDK1.8后被改为元空间)

 

​ 看一张方法区内存分布图

 

 

 

​ 方法区:方法区主要存储的是虚拟机加载的类信息(版本,字段,方法,接口等信息),成员常量,静态变量等数据,其中又包括一部分是运行时常量池,运行时常量池存放的是编译期间生成的符号引用,后面经过解析出来的直接引用也会储存在常量池中。

 

​ 当虚拟机new指令时,首先会根据这个指令的参数在常量池中定位到一个类的符号引用,如果定位不到,则需要重新对这个类进行加载,解析和初始化了,这里就涉及了Class文件加载的7大过程。如果能找到符号引用,证明这个类已经加载过,并会给该对象分配内存空间,调用构造方法进行初始化。也就是我们new一个对象发生了那些事

 

​ JDK1.8后,方法区被叫做元空间,并且内存大小限制不限JVM的内存大小限制,而是直接使用计算机的直接内存,受计算机的内存大小限制

 

 

​ 堆:堆是JVM中最大的一块内存区域了,主要存放我们程序中new出来的对象,提一点并非所有的对象都是在堆上进行分配,随着线程逃逸,标量替换等技术的发展,对象也有可能在栈上进行分配。下面通过一段代码进行讲解,对象不一定在堆上进行分配

 

public class Test {

 

    public static void test() {

        A a = new A();

    }

 

    public static void main(String[] args) {

        test();

    }

}

 

class A {

    int a = 0;

}

像这段代码,执行test()方法时,new了一个A对象,但是A对象又只有一个基本类型变量a,A对象也没有出现线程逃逸现象,因为JVM存在一些指令优化功能,并会把A对象直接进行标量替换成int a = 0,这时就会出现对象在栈上进行分配。

 

堆也是GC进行回收最主要的区域,容易出现OutOfMemoryError异常

 

 

 

​ 堆中又分为young(新生代),old(老年代),分配的内存比例1:2。young新生代中的对象具有"朝生夕死"的特点,也就是对象刚创建不久,并会被回收掉。是Minor回收的主要区域。而老年代中的对象具有的特点则是不容易被回收掉,一些大对象比如数组并会存放在老年代中。是Full GC回收的主要区域。后面写一篇JVM GC垃圾回收的文章做介绍,这里不做过多的讲解了

 

​ young新生代中又分为eden区,两个survivor区,分配的内存比例8:1:1。我们程序中所new出的对象首先会在eden区进行分配,然后经过Minor GC,eden区没有被回收的对象又会被放到survivor Form区,survivor Form区经过GC后的对象没有被回收掉,又会转移到survivor To区,这两个区的对象是可以双向转移的。新生代采用GC的算法是复制算法,两个survivor区正是复制算法所要预留出来的区域

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/503862.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

行业趣闻 | 在施工现场“打灰”,挺好的?

房地产市场的不景气对土木行业的冲击、某某大学土木工程专业招不到人、某央企施工人员因吐槽土木行业现状而被辞退…… 面对互联网上诸多对土木行业的调侃和流言&#xff0c;许多土木工程专业的同学变得迷茫了。 这个行业的实际情况究竟是怎样的&#xff1f; 图源网络 2018年10…

Auto-GPT:揭示 ChatGPT、GPT-4 和开源 AI 之间的联系

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、什么是Auto-GPT&#xff1f;二、Auto-GPT 是如何工作的&#xff1f;三、Auto-GPT 能做什么&#xff1f;四、谁制造了 Auto-GPT&#xff1f;五、ChatGPT 或 …

DPDK抓包工具dpdk-dumpcap的使用

在进行网络开发中&#xff0c;我们经常会通过抓包来定位分析问题&#xff0c;在不使用DPDK的情况下&#xff0c;Linux系统通常用tcpdump&#xff0c;windows用wireshark&#xff0c;但是如果我们使用了DPDK来收包&#xff0c;就无法用这两个工具来抓包了。 这个时候我们需要用D…

Linux新字符设备驱动实验

1、新字符设备驱动原理 一、分配和释放设备号 使用 register_chrdev 函数注册字符设备的时候只需要给定一个主设备号即可&#xff0c;但是这样会 带来两个问题&#xff1a; ①、需要我们事先确定好哪些主设备号没有使用。 ②、会将一个主设备号下的所有次设备号都使用掉&#…

多线程(线程同步和互斥+线程安全+条件变量)

线程互斥 线程互斥&#xff1a; 任何时刻&#xff0c;保证只有一个执行流进入临界区访问临界资源&#xff0c;通常对临界资源起到保护作用 相关概念 临界资源&#xff1a; 一次仅允许一个进程使用的共享资源临界区&#xff1a; 每个线程内部&#xff0c;访问临界资源的代码&am…

信息抽取与命名实体识别:从原理到实现

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

STM32-江科大

新建工程 引入启动文件 Start中是启动文件&#xff0c;是STM32中最基本的文件&#xff0c;不需要修改&#xff0c;添加即可。 启动文件包含很多类型&#xff0c;要根据芯片型号来进行选择&#xff1a; 如果是选择超值系列&#xff0c;那就使用带 VL 的启动文件&#xff0c;…

多元统计分析-主成分分析的原理与实现

目录 一、什么是主成分分析&#xff1f; 二、主成分分析的原理 三、主成分分析的应用 四、使用sklearn实现主成分分析 五、总结 一、什么是主成分分析&#xff1f; 主成分分析&#xff08;Principal Component Analysis&#xff0c;PCA&#xff09;是一种常用的多元统计分…

Docker部署FAST OS DOCKER容器管理工具

Docker部署FAST OS DOCKER容器管理工具 一、FAST OS DOCKER介绍1. FAST OS DOCKER简介2. FAST OS DOCKER特点 二、本次实践介绍1. 本次实践简介2. 本次实践环境 三、本地环境检查1.检查Docker服务状态2. 检查Docker版本 四、下载FAST OS DOCKER镜像五、部署FAST OS DOCKER1. 创…

理解控制变量、内生变量、外生变量、工具变量

文章目录 前言一、控制变量二、内生变量、外生变量三、工具变量&#xff08;IV&#xff09; 前言 1.解释变量&#xff08;或自变量&#xff09;&#xff1a;解释变量是指作为研究对象&#xff0c;用于解释某个现象或行为模式的变量。其中有些解释变量是直接影响被解释变量的&a…

自学黑客(网络安全),一般人我劝你还是算了吧

一、自学网络安全学习的误区和陷阱 1.不要试图先成为一名程序员&#xff08;以编程为基础的学习&#xff09;再开始学习 我在之前的回答中&#xff0c;我都一再强调不要以编程为基础再开始学习网络安全&#xff0c;一般来说&#xff0c;学习编程不但学习周期长&#xff0c;而…

重塑未来:AI对教育行业的深远影响与挑战

自从AI人工智能的发展进入“iPhone时刻”以来&#xff0c;我们已身处一个日新月异的时代。在众多领域&#xff0c;AI已经大放异彩&#xff0c;而教育作为培养下一代的关键领域&#xff0c;自然也受到了这场科技革命的影响。 AI对教育行业重大影响 最近可汗学院&#xff08;Kh…

图论网络模型及求最小路径和造价实战

学习知识要实时简单回顾&#xff0c;我把学习的图论简单梳理一下&#xff0c;方便入门与复习。 图论网络 图论网络简介 图论起源于 18 世纪。第一篇图论论文是瑞士数学家欧拉于 1736 年发表的“哥尼斯堡的七座桥”。1847 年&#xff0c;克希霍夫为了给出电网络方程而引进了“…

《Netty》从零开始学netty源码(五十五)之PooledByteBufAllocator

PooledByteBufAllocator 通过前面的学习我们大体了解了PooledByteBufAllocator管辖下的数据结构&#xff0c;整体情况如下&#xff1a; PooledByteBufAllocator主要管理了三类内存&#xff0c;堆内存heapArenas、直接内存directArenas、线程缓存PoolThreadCache&#xff0c;前…

Java笔记_18(IO流)

Java笔记_18 一、IO流1.1、IO流的概述1.2、IO流的体系1.3、字节输出流基本用法1.4、字节输入流基本用法1.5、文件拷贝1.6、IO流中不同JDK版本捕获异常的方式 二、字符集2.1、GBK、ASCII字符集2.2、Unicode字符集2.3、为什么会有乱码2.4、Java中编码和解码的代码实现2.5、字符输…

直方图均衡化与规定化原理解释以及matlab实现

直方图均衡化(HE) Histogram Equalization (HE) 设灰度水平在 r k , k ∈ [ 0 &#xff0c; L − 1 ] r_k,k\in[0&#xff0c;L-1] rk​,k∈[0&#xff0c;L−1] 内 一幅图像 f f f 的非归一化直方图定义为 h ( r k ) n k h(r_k)n_k h(rk​)nk​ s T ( r ) sT(r) sT(r)为…

【统计模型】心脏病患病影响因素探究

目录 心脏病患病影响因素探究 一、研究目的 二、数据来源和相关说明 三、描述性统计分析 四、数据建模 4.1 全模型 &#xff08;1&#xff09;模型构建 &#xff08;2&#xff09;模型预测 4.2 基于AIC准则的选模型A 4.3 基于BIC准则的选模型B 4.4 模型评估 五、结论…

Vector - CAPL - CANoe硬件配置函数 - 02

Hardware Configuration 硬件配置中包含CAN或者CANFD的参数配置&#xff0c;其中包含波特率、时间片1、时间片2、时间量子中的同步跳跃宽度、采样点数等信息&#xff1b;随着研发系统中各类型的平台化&#xff0c;测试想要跟上研发的进度&#xff0c;也必须进行平台化&#xff…

linux【网络编程】之网络套接字预备

linux【网络编程】之网络套接字 一、必备知识1.1 端口号1.2 端口号方面疑问及解决方案 二、TCP/UDP协议三、网络字节流四、socket编程4.1 认识接口4.2 浅析sockaddr结构 一、必备知识 在【网络基础】中我们提到了IP地址&#xff0c;接下来了解一下网络通信中其他方面的知识 1…

浏览器的渲染

浏览器的渲染 浏览器的渲染过程分为两大阶段&#xff0c;八大步骤&#xff0c;由两个线程完成&#xff0c; 下面是总的过程 第一个 渲染主线程 它包括5个步骤&#xff0c; 1、html解析 parse 解析我们的HTML&#xff0c;生成DOM树结构 2、样式计算 computed style 比如我们…