JVM内存模型详解

news2024/10/6 16:22:58

46d4d50456914680a18486756c8ef87b.gifJVM内存模型和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/416269.html

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

相关文章

【教学类-30-04】10以内减法题不重复(一页两份)(包括6以内、7以内、8以内、9以内、10以内减法题 只抽取25个)

作品展示 ——10以内不重复减法题 需求: 1、制作10以内减法题 材料准备: Word模板 代码展示: 6、7、8、9、10以内减法一页两份(10以内减法一页两份(6以内、7以内、8以内、9以内、10以内不重复减法题) 时间…

文件访问被拒绝?5个解决方法!

案例:文件访问被拒绝 【朋友们,想问问大家的电脑有遇到过文件访问被拒绝的情况吗?真的太头疼了,大家都是怎么解决的呢?】 在日常使用电脑和操作文件时,有时我们可能会遇到文件访问被拒绝的情况。这可能会…

Scala框架Akka学习

Scala框架Akka 文章目录Scala框架AkkaAkka概述Akka特点Akka与Scala.actors.Actor的关系Akka模型介绍Actor模型的优点Akka模型的核心概念如何创建Actor添加依赖在Akka中,Actor负责通信,在Actor中有一些重要的生命周期方法**akka的架构原理**创建Actor的步…

Charles二次开发-接口解密

1,使用背景 最近工作中对公司接口进行抓包,发现接口路径和返回都是经过加密的,对于查看接口路径及接口返回结果带来了不便,于是想到了对Charles进行小改造,在Charles上增加一个按钮对加密的请求、响应结果解密&#x…

[学习笔记]计算机图形学(一)

计算机图形学学习笔记(一) 什么是计算机图形学 计算机图形学的主要研究内容就是研究如何在计算机中表示图形、以及利用计算机进行图形的计算、处理和显示的相关原理与算法。 什么是好的画面? 从技术层面简单的评判标准:直接看画面…

Android实现RecyclerView分组显示功能完整示例(自定义组头和Item布局)

实现效果截图&#xff1a; 首先&#xff0c;我们需要为RecyclerView添加一个分组的概念&#xff0c;我们可以创建一个Group类来表示分组&#xff0c;包括分组名称和分组中的数据项列表。代码如下&#xff1a; public class Group {private String name;private List<Item&g…

ChatGPT-5到底有多强?Battle!咱貌似也不输呀!

盘点今年的热点话题&#xff0c;ChatGPT是不可避免要被反复提及的一part。从去年的-3.0到今年的-3.5&#xff0c;再到上月刚发布-4.0。从用户体验和市场反馈来讲&#xff0c;这半年的时间&#xff0c;ChatGPT每一步都走得又稳又快&#xff01; 回想起今年2月初ChatGPT全网爆火的…

最短路径-dijkstra/floyd

目录 floyd -dijkstra floyd floyd:用来求所有顶点之间的最短路径问题,求最短路径具体节点顺序&#xff0c;求各点之间最短路径长度 理解floyd&#xff1a; 二维矩阵图&#xff0c;就是不断通过测试新的节点k&#xff0c;看看k节点能不能作为中间节点优化各点之间的最短距离…

SourceMap源码映射详细讲解

SourceMap源码映射详细讲解 前端工程打包后代码会跟项目源码不一致&#xff0c;当代码运行出错时控制台上定位出错代码的位置跟项目源码上不对应。这时候我们很难定位错误代码的位置。SourceMap的用途是可以将转换后的代码映射回源码&#xff0c;如果设置了js文件对应的map资源…

Java每日一练(20230416)

目录 1. 三数之和 &#x1f31f;&#x1f31f; 2. 基本计算器 &#x1f31f;&#x1f31f;&#x1f31f; 3. 通配符匹配 &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java…

Android:编译libevent动态库并移植jni中,在Android AVD虚拟机上实现一个http服务器

libevent源码&#xff1a;libevent-2.1.8-stable Android Studio版本&#xff1a;Android Studio Electric Eel | 2022.1.1 Patch 2 AVD虚拟机为x86. https://developer.android.google.cn/studio/run/emulator-networking?hlzh-cn#connecting 大体步骤&#xff1a; 1.在ws…

Vue2_01_data_插值

插值语法 {{name}} data: vue实例的数据对象 data中数据变化时将重新渲染容器 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><!--引入vue,引入之后vue.js 创建了一个全局变…

c语言进阶篇_动态内存管理(数组可以自动扩容?)

前言 &#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏: &#x1f354;&#x1f35f;&#x1f32f; c语言初阶 &#x1f511;个人信条: &#x1f335;知行合一 &#x1f349;本篇简介:>:讲解c语言中的动态内存管理知识,涉及malloc函数、call…

微信小程序运行及更新机制

微信小程序运行及更新机制1、微信小程序运行机制1.1 前台和后台1.2 小程序启动&#xff1a;冷启动和热启动1.3 小程序销毁2、微信小程序更新机制2.1 启动时同步更新定期检查发现版本更新用户长时间未使用小程序2.2 启动时异步更新开发者手动触发更新2.3 小程序管理后台的相关设…

软件测试分类详解

一图看清软件测试分类 一、按测试技术分&#xff08;是否查看代码&#xff09; **1. 黑盒测试**&#xff1a;软件功能是否正常使用【功能的测试】 **2. 白盒测试**&#xff1a;代码逻辑是否正确【结构的测试】 **3. 灰盒测试**&#xff1a;介于两者之间的测试&#xff0c;也…

第12章_集合框架

第12章_集合框架 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 本章专题与脉络 1. 集合框架概述 1.1 生活中的容器 1.2 数组的特点与弊端 一方面&#xff0c;面向对象语言对事物的体现都是以对…

iOS 项目嵌入Flutter 运行

一 创建Flutter 模块命令行flutter create --template module my_flutter创建完成后&#xff0c;该模块和普通的Flutter项目一直&#xff0c;可以通过Android Studio或VSCode打开、开发、运行&#xff1b;和之前项目不同的iOS和Android项目是一个隐藏文件&#xff0c;并且我们…

黑马点评缓存练习题shop-type缓存,附带详细解析

黑马点评缓存练习题shop-type缓存 依照shop详情的缓存 Controller代码 public class ShopTypeController {Resourceprivate IShopTypeService typeService;GetMapping("list")public Result queryTypeList() {return typeService.queryList();} }创建service接口方…

SentenceTransformers介绍

SentenceTransformer使用范例 1使用SentenceTransformers获得句子向量嵌入 from sentence_transformers import SentenceTransformer#模型下载 model SentenceTransformer(paraphrase-MiniLM-L6-v2)# 编码句子 sentences [Python is an interpreted high-level general-pur…

JavaScript【五】JavaScript中的对象

文章目录&#x1f31f;前言&#x1f31f;对象&#xff1a;&#x1f31f;声明对象&#xff1a;&#x1f31f;隐式创建对象&#xff1a;&#x1f31f;实例化Object&#xff1a;&#x1f31f;实例化自定义构造函数&#xff1a;(会重复占用内存)&#x1f31f;new运算符具体做了什么…