JVM内存模型和结构详解

news2024/10/5 15:29:45

9613c0055473406cb9e456ddd0bb2f2c.jpgJVM内存模型和Java内存模型都是面试的热点问题,名字看感觉都差不多,实际上他们之间差别还是挺大的。

 

 

通俗点说,JVM内存结构是与JVM的内部存储结构相关,而Java内存模型是与多线程编程相关@mikechen。

 

什么是JVM

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一个虚构出来的计算机,有着自己完善的硬件架构,如处理器、堆栈等。

 

 

 

为什么需要JVM?

Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。

 

Java文件必须先通过一个叫javac的编译器,将代码编译成class文件,然后通过JVM把class文件解释成各个平台可以识别的机器码,最终实现跨平台运行代码。

 

 

 

 

 

JVM内存模型

JVM内存模型可以分为两个部分,如下图所示,堆和方法区是所有线程共有的,而虚拟机栈,本地方法栈和程序计数器则是线程私有的。

 

323009a709984f5e8979faab9fd5fa58?from=pc

 

在JVM1.8中,图中的 方法区为元数据区,下面展开谈一谈这五个区域的作用。

 

 

 

堆(Heap)

在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old ),新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。

 

下图中的Perm代表的是永久代,但是注意永久代并不属于堆内存中的一部分,同时jdk1.8之后永久代也将被移除。

 

41a3037a558f4cdeb4fb3dc2149058f5?from=pc

 

堆是java虚拟机所管理的内存中最大的一块内存区域,也是被各个线程共享的内存区域,该内存区域存放了对象实例及数组(但不是所有的对象实例都在堆中)。

 

其大小通过-Xms(最小值)和-Xmx(最大值)参数设置(最大最小值都要小于1G),前者为启动时申请的最小内存,默认为操作系统物理内存的1/64,后者为JVM可申请的最大内存,默认为物理内存的1/4,默认当空余堆内存小于40%时,JVM会增大堆内存到-Xmx指定的大小,可通过-XX:MinHeapFreeRation=来指定这个比列。

 

当空余堆内存大于70%时,JVM会减小堆内存的大小到-Xms指定的大小,可通过XX:MaxHeapFreeRation=来指定这个比列,当然为了避免在运行时频繁调整Heap的大小,通常-Xms与-Xmx的值设成一样。堆内存 = 新生代+老生代+持久代。

 

在我们垃圾回收的时候,我们往往将堆内存分成新生代和老生代(大小比例1:2),新生代中由Eden和Survivor0,Survivor1组成,三者的比例是8:1:1,新生代的回收机制采用复制算法,在Minor GC的时候,我们都留一个存活区用来存放存活的对象,真正进行的区域是Eden+其中一个存活区,当我们的对象时长超过一定年龄时(默认15,可以通过参数设置),将会把对象放入老生代,当然大的对象会直接进入老生代,老生代采用的回收算法是标记整理算法。

 

 

方法区(Method Area)

其实方法区是在JDK1.8以前的版本里存在的一块内存区域,主要就是存放从class文件里加载进来的类的,而且常量池也是在这块区域内的。

 

但是在JDK1.8之后,这块区域摇身一变,换了名字,叫做“Metaspace”,翻译过来就是“元数据空间”的意思,当然它只是改了个名,实现的功能是没变的。

 

方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

 

 

 

1.类型信息

 

对每个加载的类型(类class、接口interface、枚举enum、注解annotation),JVM必须在方法区中存储以下类型信息:

①这个类型的完整有效名称(全名=包名.类名)

②这个类型直接父类的完整有效名(对于interface或是java.lang.0bject,都没有父类)

③这个类型的修饰符(public, abstract,final的某个子集)

④这个类型直接接口的一个有序列表

 

2.域信息(Field)成员变量

 

JVM必须在方法区中保存类型的所有域的相关信息以及域的声明顺序。

域的相关信息包括:域名称、域类型、域修饰符(public, private,protected,static,final, volatile, transient的某个子集)

 

3.方法(Method)信息

 

JVM必须保存所有方法的以下信息,同域信息一样包括声明顺序:

 

方法名称

方法的返回类型(或void)·方法参数的数量和类型(按顺序)

方法的修饰符(public, private,protected,static, final,synchronized,native,abstract的一个子集)

方法的字节码(bytecodes)、操作数栈、局部变量表及大小(abstract和native方法除外)

 

 

虚拟机栈(JVM Stack)

虚拟机栈(Java Virtual Machine Stack),早期也叫Java栈,每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的Java方法调用。

 

虚拟机栈的作用:主管Java程序的运行,它保存方法的局部变量、部分结果,并参与方法的调用和返回。

 

每个方法被执行的时候都会创建一个”栈帧”,用于存储局部变量表(包括参数)、操作栈、方法出口等信息。

 

每个方法被调用到执行完的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

 

栈帧(Stack Frame) 是用于虚拟机执行时方法调用和方法执行时的数据结构,它是虚拟栈的基本元素,栈帧由局部变量区、操作数栈等组成,如下图所示:

 

 

 

 

 

每一个方法从调用到方法返回都对应着一个栈帧入栈出栈的过程。最顶部的栈帧称为当前栈帧,栈帧所关联的方法称为当前方法,定义这个方法的类称为当前类,该线程中,虚拟机有且也只会对当前栈帧进行操作。

 

栈帧的作用有存储数据,部分过程结果,处理动态链接,方法返回值和异常分派。

 

每一个栈帧包含的内容有局部变量表、操作数栈、动态链接、方法返回地址和一些额外的附加信息。在编译代码时,栈帧需要多大的局部变量表,多深的操作数栈都可以完全确定的,并写入到方法表的code属性中。

 

 

 

本地方法栈(Native Stack)

本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java 方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native 方法服务。

 

虚拟机规范中对本地方法栈中的方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。

 

甚至有的虚拟机(譬如Sun HotSpot 虚拟机)直接就把本地方法栈和虚拟机栈合二为一。

 

与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError 和OutOfMemoryError异常。

 

 

 

程序计数器(PC Register)

在JVM的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。

 

分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。

 

JVM的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,为了各条线程之间的切换后计数器能恢复到正确的执行位置,所以每条线程都会有一个独立的程序计数器。

 

当线程正在执行一个Java方法,程序计数器记录的是正在执行的JVM字节码指令的地址;如果正在执行的是一个Natvie(本地方法),那么这个计数器的值则为空(Underfined)。

 

程序计数器占用的内存空间很少,也是唯一一个在JVM规范中没有规定任何OutOfMemoryError(内存不足错误)的区域。

 

 

 

 

 

JVM内存模型小结

本篇介绍了JVM虚拟机中运行时数据区的五个内存区域:堆、方法区、虚拟机栈、本地方法栈、程序计数器。

 

这些地方也是我们平时开发中最常接触到的地方,所以对其有所掌握了解还是很有必要的,也有助于JVM问题排查。

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

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

相关文章

Redis缓存雪崩及解决办法

缓存雪崩 1.缓存雪崩是指在同- -时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到 达数据库,带来巨大压力。 2.解决方案: ◆给不同的Key的TTL添加随机值 ◆利用Redis集群提高服务的可用性 ◆给缓存业务添加降级限流策略 降级可做为系统的保底…

java程序1补充:从键盘输入圆的半径,求圆的周长和面积(简易与交互两版)

编写一个java程序,从键盘输入圆的半径,求圆的周长和面积,并输出。 要求: (1)半径仅考虑int型正整数,并综合利用所学较好地处理异常输入,包括非法整数、负整数输入时的处理。输入半…

网络编程套接字基本概念认识

目录 认识端口号 认识TCP协议 认识UDP协议 网络字节序 socket编程接口 socket 常见API sockaddr结构 认识端口号 端口号(port)是传输层协议的内容 端口号是一个2字节16位的整数; 端口号用来标识一个进程, 告诉操作系统, 当前的这个数据要交给哪一个进程来处理; IP地址 …

数字电路仿真编译文件指定方式

目录 1 最基本的方式 2 指定多个文件 3. 使用filelist文件 4 指定整个目录中的所有指定后缀的文件 5 指定include文件的搜索路径 6 追加宏的定义 7 Verdi相关的选项 8 Vivado中的处理方式 1 最基本的方式 最基本的方式就是直接在命令行指定单个源文件,比如说…

VMware安装华为存储模拟器

实验需要的软件: VMware Workstation Pro ST00000000201812000*配套的license文件 Dorado5000 V3存储模拟器磁盘 存储模拟器磁盘和license文件资源,在本人主页发布的资源中去下载 安装步骤: 1. 点击 “文件->新建虚拟机”。 2. 在弹框…

MySQL高级篇(SQL优化、索引优化、锁机制、主从复制)

目录 0 存储引擎介绍1 SQL性能分析2 常见通用的JOIN查询SQL执行加载顺序七种JOIN写法 3 索引介绍3.1 索引是什么3.2 索引优劣势3.3 索引分类和建索引命令语句3.4 索引结构与检索原理3.5 哪些情况适合建索引3.6 哪些情况不适合建索引 4 性能分析4.1 性能分析前提知识4.2 Explain…

SQL Server数据库使用

文章目录 前言一、SQL Server 2008 R2 安装例:安装一台SQL Server 2008 R2服务器 二、SSMS管理工具简介1.SQL Server 2008 R2常用的工具2.连接到服务器 三、SQL Server数据库分类及管理1.SQL Server数据库分类2.SQL Server数据库文件类型3.SQL Server数据库管理例&a…

操作系统第五章——输入输出管理(中)

提示:若我会见到你,事隔经年,我如何向你招呼,以眼泪,以沉默 文章目录 5.2.1 IO核心子系统知识总览功能要在那个层次实现 5.2.2 假脱机技术(SPOOLing)知识总览什么是脱机技术假脱机技术——输入井…

Kafka锦集(二):三种不同方式,查看kafka是否已启动

前言 Kafka的启动之前,必不可少的三个操作: 1、启动Zookeeper服务,点击进入 bin/zookeeper-server-start.sh -daemon config/zookeeper.properties 2、 Kafka的下载和安装 3、修改Kafka安装目录下./config/server.properties文件里的监听窗…

考研C语言第三章

3.1 运算 #include <stdio.h>int main() {int result45*2-6/310%4;printf("%d\n",result);return 0; }C语言输出上每次都要带着数据类型&#xff0c;想念java 算术运算符与关系运算符 #include <stdio.h>int main() {int a;while(scanf("%d"…

C#,Matlab混合编程(01)——Mat文件格式简介及读写Mat文件的C#源程序

Matlab 软件 20GB&#xff0c;很大&#xff0c;还有卡脖子的问题。 我们可以利用其生成的 Mat 文件做更多的事。 1 Mat 文件 MAT 文件版本概述 MAT 文件是二进制 MATLAB 文件&#xff0c;用于存储工作区变量。从 MAT 文件版本 4 开始&#xff0c;随后的几个 MAT 文件版本都支持…

qtcreator-ros 安装配置

qtcreator-ros 安装配置 计划利用 QT 搭建简易的小车远程控制客户端&#xff0c;QT 系统学习有点耗时&#xff0c;借助 qtcreator-ros 可以缩短开发周期 How to Install (Users) ROS Qt5 librviz人机交互界面开发一&#xff08;配置QT环境&#xff09; 电脑中已经安装 5.10.1 …

DJ6-1/2/3 文件系统

目录 6.1 文件系统概述 6.1.1 文件、记录和数据项 6.1.2 文件类型 6.1.3 文件系统模型 6.1.4 对文件的操作 6.2 文件的逻辑结构 6.2.1 文件逻辑结构的类型 6.2.2 顺序文件&#xff08;Sequential File&#xff09; 6.2.4 索引文件&#xff08;Index File&…

英文论文(sci)解读复现【NO.12】YOLO-Tea: YOLOv5改进的茶叶病害检测模型

此前出了目标检测算法改进专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读发表高水平学术期刊中的 SCI论文&a…

CocosCreator图片处理:截图裁剪,保存到本地,从本地加载,远端图片转base64

截图裁剪 从相机导出的renderTexture中使用readPixels读取像素数据&#xff0c;通过像素数据创建spriteFrame可以展示到界面上。 this.rt new RenderTexture(); this.rt.initialize({width: view.getVisibleSize().width,height: view.getVisibleSize().height, }) this.ca…

Three.js--》实现3d官网模型展示

目录 项目搭建 实现网页简单布局 初始化three.js基础代码 创建环境背景 加载飞船模型 实现滚轮滑动切换3D场景 设置星光流动特效 今天简单实现一个three.js的小Demo&#xff0c;加强自己对three知识的掌握与学习&#xff0c;只有在项目中才能灵活将所学知识运用起来&…

计算机常见的故障类型

文章目录 前言一、常见故障类型介绍1.硬件故障2.系统故障3.软件故障 二、故障排查思路三、Win操作系统问题1.系统基本信息2.系统资源监视器&#xff08;运行对话框输入“resmon”&#xff09;3.事件查看器&#xff08;运行对话框输入“eventvwr”&#xff09;4.任务管理器&…

使用这些方法让你的 Python 并发任务执行得更好

动动发财的小手&#xff0c;点个赞吧&#xff01; 问题 一直以来&#xff0c;Python的多线程性能因为GIL而一直没有达到预期。 所以从 3.4 版本开始&#xff0c;Python 引入了 asyncio 包&#xff0c;通过并发的方式并发执行 IO-bound 任务。经过多次迭代&#xff0c;asyncio A…

【LED子系统】八、小试牛刀

个人主页&#xff1a;董哥聊技术 我是董哥&#xff0c;高级嵌入式软件开发工程师&#xff0c;从事嵌入式Linux驱动开发和系统开发&#xff0c;曾就职于世界500强公司&#xff01; 创作理念&#xff1a;专注分享高质量嵌入式文章&#xff0c;让大家读有所得&#xff01; 文章目录…

2023电工杯数学建模B题完整模型代码【原创首发】

文末获取全部资料 摘要 近年来&#xff0c;随着人工智能&#xff08;AI&#xff09;技术的发展和广泛应用&#xff0c;其在教育领域的潜力和影响引起了广泛关注。本研究旨在通过一项全面的问卷调查&#xff0c;探讨AI学习工具在大学生学习过程中的影响。 在本项研究中&#…