Java 内存模型(JMM)
JMM,全称 Java Memory Model ,中⽂释义Java内存模型
1. 概述
对于 Java 程序员来说,在虚拟机⾃动内存管理机制下,不再需要像 C/C++ 程序开发程序员这 样为每⼀个 new 操作去写对应的 delete / free 操作,不容易出现内存泄漏和内存溢出问 题。正是因为 Java 程序把内存控制权利交给 JVM 虚拟机。⼀旦出现内存泄漏和溢出⽅⾯的问题, 如果不了解虚拟机是怎样使⽤内存的,那么排查错误将会是⼀个⾮常艰巨的任务。
2. 运行时数据区域划分
- JVM 虚拟机在执⾏ Java 程序的过程中会把它管理的内存划分成若⼲个不同的数据区域。
- JDK 1.8 之前分为:线程共享( Heap 堆区、 Method Area ⽅法区)、线程私有(虚拟 机栈、本地⽅法栈、程序计数器)
- JDK 1.8 以后分为:线程共享( Heap 堆区、 MetaSpace 元空间)、线程私有(虚拟机 栈、本地⽅法栈、程序计数器)
3. 程序计数器(Program Counter Register)
程序计数器是⼀块较⼩的内存空间,是当前线程所执⾏的字节码的⾏号指示器。
字节码解释器在解释执⾏字节码⽂件⼯作时,每当需要执⾏⼀条字节码指令时,就通过改变程序 计数器的值来完成。程序中的分⽀、循环、跳转、异常处理、线程恢复等功能都需要依赖这个计数器 来完成。
程序执⾏过程中,会不断的切换当前执⾏线程,切换后,为了能让当前线程恢复到正确的执⾏位 置,每条线程都需要有⼀个独⽴的程序计数器,并且各线程之间计数器互不影响,独⽴存储。
程序计数器主要有两个作⽤:
- 字节码解释器通过改变程序计数器来依次读取指令,从⽽实现代码的流程控制,如:顺序执⾏、 选择、循环、异常处理。
- 在多线程的情况下,程序计数器⽤于记录当前线程执⾏的位置,从⽽当线程被切换回来的时候, 能够知道当前线程的运⾏位置。
- 程序计数器是唯⼀⼀个不会出现 OutOfMemoryError 的内存区域,它随着线程的创建⽽创建, 随着线程的结束⽽死亡。
4. Java 虚拟机栈(VM Stack)
与程序计数器⼀样, VM Stack 虚拟机栈也是线程私有的,它的⽣命周期和线程相同,⽤于描述 Java ⽅法执⾏时的内存模 型,每次⽅法调⽤的数据都是通过栈传递的。
JMM 内存区域可以粗略的区分为堆内存( Heap )和栈内存 ( Stack )。其中栈就是 VM St ack 虚拟机栈,或者说是虚拟机栈中局部变量表部分。 因为局部变量表主要存放了编译期可知的各 种基本数据类型变量值(boolean、byte、char、short、int、float、long、double)、对象引⽤ (reference 类型,它不同于对象本身,可能是⼀个指向对象起始地址的引⽤指针,也可能是指向⼀ 个代表对象的句柄或其他与此对象相关的位置)。
Java 虚拟机栈是由⼀个个栈帧组成,⽽每个栈帧中都拥有:局部变量表、操作数栈、动态链 接、⽅法出⼝信息。每⼀次⽅法调⽤都会有⼀个对应的栈帧被压⼊ VM Stack 虚拟机栈,每⼀个 ⽅法调⽤结束后,代表该⽅法的栈帧会从 VM Stack 虚拟机栈中弹出。
在活动线程中, 只有位于栈顶的帧才是有效的, 称为当前活动栈帧,代表正在执⾏的当前⽅ 法。在 JVM 执⾏引擎运⾏时, 所有指令都只能针对当前栈帧进⾏操作。虚拟机栈通过 pop 和 p ush 的⽅式,对每个⽅法对应的活动栈帧进⾏运算处理,⽅法正常执⾏结束,肯定会跳转到另⼀个 栈帧上。
Java ⽅法有两种返回⽅式: return 语句或抛出异常,不管哪种返回⽅式都会导致栈帧被弹出。
Java 虚拟机栈会出现两种错误: StackOverFlowError 和 OutOfMemoryError 。
- StackOverFlowError : 当线程请求栈的深度超过 JVM 虚拟机栈的最⼤深度的时候,就 抛出 StackOverFlowError 错误。
- OutOfMemoryError: JVM 的内存⼤⼩可以动态扩展, 如果虚拟机在动态扩展栈时⽆法申请 到⾜够的内存空间,则抛出 OutOfMemoryError 异常。
5. 本地方法栈(Native Method Stack)
本地方法栈用于虚拟机调用的 Native 方法
native 关键字修饰的本地⽅法被执⾏的时候,在本地⽅法栈中也会创建⼀个栈帧,⽤于存放 该 native 本地⽅法的局部变量表、操作数栈、动态链接、⽅法出⼝信息。⽅法执⾏完毕后,相应 的栈帧也会出栈并释放内存空间。也会出现 StackOverFlowError 和 OutOfMemoryError 两种错误。
6. 堆(Heap)
Heap 堆区,⽤于存放对象实例和数组的内存区域。
Heap 堆是 JVM 所管理的内存中最⼤的⼀块区域,被所有线程共享的⼀块内存区域。堆区中 存放对象实例,“⼏乎”所有的对象实例以及数组都在这⾥分配内存。
6.1. 新⽣代、⽼年代
Heap 堆是垃圾收集器 GC ( Garbage Collected )管理的主要区域,因此堆区也被称 作 GC 堆( Garbage Collected Heap )。从垃圾回收的⻆度,由于现在收集器基本都采⽤分 代垃圾收集算法,所以 JVM 中的堆区往往进⾏分代划分,例如:新⽣代 和 ⽼年代。⽬的是更好地 回收内存,或者更快地分配内存。
Heap 堆区中的新⽣代、⽼年代的空间分配⽐例,可以通过 java -XX:+PrintFlagsFinal -version 命令查看。
因为新⽣代是由 Eden + s0 + s1 组成的,所以按照上述默认⽐例,如果 Eden 区内存 ⼤⼩是 40M,那么两个 Survivor 区就是 5M,整个新⽣代区就是 50M,然后可以算出 Old 区内存 ⼤⼩是 100M,堆区总⼤⼩就是 150M。
6.2. 创建对象的内存分配
创建⼀个新对象,在堆中的分配内存。
⼤部分情况下,对象会在 Eden 区⽣成,当 Eden 区装填满的时候,会触发 Young Gar bage Collection ,即 YGC 垃圾回收的时候,在 Eden 区实现清除策略,没有被引⽤的对象 则直接回收。
依然存活的对象会被移送到 Survivor 区。 Survivor 区分为 s0 和 s1 两块内存区 域。每次 YGC 的时候,它们将存活的对象复制到未使⽤的 Survivor 空间( s0 或 s1 ), 然后将当前正在使⽤的空间完全清除,交换两块空间的使⽤状态。每次交换时,对象的年龄会 加 +1 。
如果 YGC 要移送的对象⼤于 Survivor 区容量的上限,则直接移交给⽼年代。⼀个对象 也不可能永远呆在新⽣代,在 JVM 中 ⼀个对象从新⽣代晋升到⽼年代的阈值默认值是 15 ,可 以在 Survivor 区交换 14 次之后,晋升⾄⽼年代。
堆区最容易出现的就是 OutOfMemoryError 错误,这种错误的表现形式会有以下两种:
- OutOfMemoryError: GC Overhead Limit Exceeded : 当 JVM 花太多时间执⾏垃 圾回收,并且只能回收很少的堆空间时,就会发⽣此错误。
- OutOfMemoryError: Java heap space :假如在创建新的对象时, 堆内存中的空间不⾜ 以存放新创建的对象, 就会引发此错误。
7. 元空间(Meta Space)
⽤于存放类信息、常量、静态变量、JIT即时编译器编译后的机器代码等数据等。例如: java.l ang.Object 类的元信息、 Integer.MAX_VALUE 常量等。
JDK1.6:
HotSpot JVM 使⽤ Method Area ⽅法区存储,也叫永久代(Permanent Generation)。
- ⽅法区和“永久代( Permanent Generation )”的区别:⽅法区是 JVM 的规范,⽽永久代( Permanent Generation )是 JVM 规范的⼀种实现,并且只有 HotSpot JVM 才有永久 代“ Permanent Generation ”,⽽对于其他类型的虚拟机,如 JRockit(Oracle)、J9 (IBM) 并没有;
- ⽅法区是⼀⽚连续的堆空间,当 JVM 加载的类信息容量超过了最⼤可分配空间,虚拟机会抛 出 OutOfMemoryError:PermGenspace 的 Error 。
- 永久代的GC是和⽼年代( old generation )捆绑在⼀起的,⽆论谁满了,都会触发永久代和 ⽼年代的垃圾收集。
- 可以通过 -XX:PermSize=N 设置 ⽅法区 (永久代) 初始空间, -XX:MaxPermSize=N 设 置⽅法区 (永久代) 最⼤空间,超过这个值将会抛出错误: java.lang.OutOfMemoryError: PermGen
JDK1.7:
将字符串常量池、静态变量转移到了堆区。
JDK1.8:正式移除永久代,采⽤ Meta Space 元空间代替
元空间的本质和永久代类似,都是对 JVM 规范中⽅法区的⼀种具体实现。不过元空间与永久代 之间最⼤的区别在于:元空间并不在虚拟机中,⽽是使⽤本地内存。因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过运⾏参数来指定元空间的大小。
- 由于 PermGen 内存经常会溢出,容易抛出 java.lang.OutOfMemoryError: PermGen 错误;
- 移除 PermGen 可以促进 HotSpot JVM 与 JRockit VM 的融合,因为 JRock it 没有永久代;
8. 字符串常量池
String 的两种创建⽅式:
- 第⼀种⽅式是在常量池中获取字符串对象;
- 第⼆种⽅式是直接在堆内存空间创建⼀个新的字符串对象;
String 的 intern() ⽅法:
String 的拼接:
String s1 = new String("abc"); 这句代码创建了⼏个字符串对象?
创建 1 或 2 个字符串。如果常量池中已存在字符串常量“ abc ” ,则只会在堆空间创建⼀个字符串常 量“ abc ” 。如果常量池中没有字符串常量“ abc ” ,那么它将⾸先在池中创建,然后在堆空间中创建,因 此将创建总共 2 个字符串对象。
8 种基本类型的包装类和常量池
- Java 基本类型的包装类的⼤部分都实现了常量池技术,即 Byte,Short,Integer,Long,Character,Boolean;
- 前⾯ 4 种包装类默认创建了数值[-128,127] 的相应类型的缓存数据;
- Character 创建了数值在[0,127]范围的缓存数据;
- Boolean 直接返回 True Or False;
- 如果超出对应范围仍然会去创建新的对象
相关文章:

Java 内存模型(JMM)
JMM,全称 Java Memory Model ,中⽂释义Java内存模型 1. 概述 对于 Java 程序员来说,在虚拟机⾃动内存管理机制下,不再需要像 C/C 程序开发程序员这 样为每⼀个 new 操作去写对应的 delete / free 操作,不容易出现内存…...

用于安全研究的 Elastic Container Project
作者:来自 Elastic Andrew Pease•Colson Wilhoit•Derek Ditch 使用 Docker 启动 Elastic Stack 序言 Elastic Stack 是一个模块化数据分析生态系统。虽然这允许工程灵活性,但建立开发实例进行测试可能很麻烦。建立 Elastic Stack 的最简单方法是使用…...

STM8L101低功耗的理解
一.通过降低时钟频率来降低功耗: 规格书如图 1.code 从flash启动,主频率是16Mhz时,功耗测量2.51ma左右,对应程序如下: 2.code从flash启动,主频率是2Mhz时(上电默认值),功…...
Kotlin cancel CoroutineScope.launch的任务后仍运行
Kotlin cancel CoroutineScope.launch的任务后仍运行 import kotlinx.coroutines.*fun main() {runBlocking {val coroutineScope CoroutineScope(Dispatchers.IO)val job coroutineScope.launch {var i 0while (i < Int.MAX_VALUE) {iprintln(i)}}// 2ms 取消协程delay(…...

你是不是分不清哪些字体是商用,哪些非商用?快来看,免得莫名其妙负债。
前言 最近发现有好多小伙伴在做PPT的时候,都有一个很不好的习惯:没有调整好字体。 这里说的没有调整好字体的意思是:在一些公开发布的内容上使用一些可能造成侵权的字体。 字体侵权的后果相当严重。轻者可能面临法律纠纷,重者…...

新电脑工作流搭建记录-前端篇
vscode: url: Visual Studio Code - Code Editing. Redefined 插件:Chinese、git history、git graph、codelf、css peek、auto closed tad、auto rename tag、Quokka.js、Image preview Node 官网直接下载:下载 | Node.js node版本管理…...

XXL-JOB 漏洞大全
一、前言 在当今的数字化时代,任务调度平台对于企业级应用来说至关重要。它们负责自动化和协调各种时间敏感或周期性的任务,确保业务流程的顺畅运行。XXL-JOB作为一款流行的分布式任务调度平台,因其强大的功能和易用性,被广泛部署…...

使用 Visual Studio Code 配置 C/C++ 开发环境
Visual Studio Code(简称 VSCode)是一款非常流行的代码编辑器,提供了丰富的扩展和配置支持,使其成为进行 C/C 开发的一款理想工具。本文将详细介绍如何在 VSCode 中配置 C/C 开发环境,涵盖安装必要的工具和插件、编写简…...

STM32与ESP8266的使用
串口透传 “透传”通常指的是数据的透明传输,意思是在不对数据进行任何处理或修改的情况下,将数据从一个接口转发到另一个接口。值得注意的是要避免串口之间无限制的透明,可以采用互斥锁的方式进行限制使用方法 对USART1和USART3(用他俩举例…...

【计算机网络】数据链路层深度解析
概述三个重要问题封装成帧差错检测可靠传输 使用广播信道的数据链路层数据链路层的互连设备 媒体接入MAC地址集线器与交换机区别以太网交换机生成树协议STP 概述 链路就是从一个结点到相邻结点的一段物理线路,而中间没有任何其他的交换结点。数据链路是指把实现通信…...

【基于轻量型架构的WEB开发】【章节作业】
作业1 mybatis核心对象、配置文件和映射文件 一. 单选题(共10题,50分) 1. (单选题)以下关于<select>元素及其属性说法错误的是()。 A. <select>元素用来映射查询语句,它可以帮助我们从数据库中读取出数据,并组装数据给业务开发…...

一张图解析FastAdmin中的表格列表(bootstrap-table)的功能(备份)
功能描述 请根据图片上的数字索引查看对应功能说明。 1.菜单名称和描述 默认生成的CRUD是没有菜单名称和描述显示的,如果需要显示则可以修改权限管理->菜单规则,给对应菜单的添加上备注信息后即可显示,支持HTML 2.TAB过滤选项卡 在一键…...

【数据结构】假设二叉树采用二叉链表存储,编写一棵二又树中序遍历的非递归算法。
编程题: 假设二叉树采用二叉链表存储,编写一棵二又树中序遍历的非递归算法。 分析: 算法描述: 非递归中序遍历二叉树的算法使用栈来辅助实现。首先,从根节点开始,沿着左子树不断向下, 将每个节点压入栈中。当到达最左端节点后,开始出栈并访问节点,接着转向右子树,重…...

李宏毅结构化学习 02
文章目录 一、上篇博文复习二、Separable Case三、Non-separable Case四、Considering Errors五、Regularization六、Structured SVM七、Cutting Plane Algorithm for Structured SVM八、Multi-class and binary SVM九、Beyond Structured SVM 一、上篇博文复习 图中x表示输入的…...

Android AlertDialog圆角背景不生效的问题
一行解决: window?.setBackgroundDrawableResource(android.R.color.transparent) 原文件: /*** Created by Xinghai.Zhao* 自定义选择弹框*/ SuppressLint("InflateParams", "MissingInflatedId") class CustomDialog(context: Context?) : AlertDia…...

探讨基于AI技术的相亲交友系统设计与实现
摘要 随着人工智能技术的发展,相亲交友领域也开始引入AI技术来改善用户体验,提高匹配成功率。本文探讨了如何利用AI技术设计并实现一个智能化的相亲交友系统,该系统能够根据用户的行为数据和个人偏好,自动推荐合适的潜在伴侣。通…...

(2024.9.20)Endnote插入的参考文献字号太大怎么办?
1、序言 常常写论文的人都知道,插入参考文献时,格式调整到让人头大。Endnote的使用大大方便了我们的同时,也意味着我们要学习软件的使用方法。最近重新安装了一下Endnote,插入的文献字体大小就像抽风了一样。在还没有写完文章之前…...

DataGrip在Windows和MacOS平台上的快捷键
0. 背景信息 No.说明1测试DataGrip版本号 : 2024.2.2 1. Windows下快捷键 2. MacOS下快捷键...

CSS---序号使用css设置,counter-reset、counter-increment、content配合实现备注文案的序号展示
直接上代码,全代码copy即可使用! <template><div class"reminder"><span class"Bold_12_body" style"line-height: 8vw">温馨提示:</span><br /><div class"rule-container"…...

Liquor 表达式引擎基本使用
引入依赖 <dependency><groupId>org.noear</groupId><artifactId>liquor-eval</artifactId><version>1.2.7</version> </dependency>liquor 表达式引擎(ExpressionEvaluator)支持 java 所有的类型、及…...

AI美女屠版小红书火了,被当真人推流,颜值博主慌了
最近,微信群里有一条炸裂的聊天记录,传得沸沸扬扬。 聊天记录原主声称,自己通过flux文生图模型跑出AI美女照片,发在小红书上不仅没有被平台标为AI,还成功获得流量扶持。 随后,原主就附上了自己养的1327个小…...

本地搭建我的世界服务器(JAVA)简单记录
网上参考教程挺多的,踩了不少坑,简单记录一下,我做的是一个私人服务器,就是和朋友3、4个人玩。 笨蛋 MC 开服教程 先放一个比较系统和完整的教程,萌新可用,这个教程很详细,我只是记录一下自己的…...

哪个快?用300万个图斑测试ArcGIS Pro的成对叠加与经典叠加
点击下方全系列课程学习 点击学习—>ArcGIS全系列实战视频教程——9个单一课程组合系列直播回放 点击学习——>遥感影像综合处理4大遥感软件ArcGISENVIErdaseCognition 在使用ArcGIS Pro的过程中,很多朋友发现,Pro有个成对叠加工具集。很多…...

超详细!百分百安装成功pytorch,建议收藏
文章目录 一、Anaconda安装1.1下载anaconda1.2配置Anaconda环境1.3验证anaconda是否安装成功 二、查看电脑显卡三、更新显卡驱动3.1下载驱动3.2、查看显卡驱动版本 四、cuda安装4.1CUDA下载4.2CUDA环境配置4.3验证CUDA是否安装成功 五、安装pytorch4.1下载pytorch5.2验证pytorc…...

web基础—dvwa靶场(四)File Inclusion
File Inclusion(文件包含) 有些 web 应用程序允许用户指定直接文件流的输入,或允许用户将文件上载到服务器。稍后 web 应用程序访问 web 应用程序上下文中用户提供的输入。通过这样种操作,web 应用程序允许恶意文件执行。 如果选择要包含的文件是目标计…...

【Python】练习:控制语句(二)第1关
第1关:分支结构基础实训 第一题第二题第三题第四题(※)第五题(※)第六题第七题 第一题 #第一题 for temp in [-280, -100, 0, 20, 120, 200]:#请在下面编写代码# ********** Begin ********** #if temp>-273.15:F9/…...

Vue3 : Pinia的性质与作用
目录 一.性质 二.作用 三.Pinia 的核心概念 四.使用 1.count.ts 2.count.vue Vue 3 中 Pinia 是一个专为 Vue 3 设计的状态管理库,它旨在提供一种简单、直观的方式来管理应用的状态。 一.性质 1.集成性:Pinia 是 Vue 3 官方推荐的状态管理库&…...

对接金蝶云星空调用即时库存信息查询API
文章目录 前言准备工作获取第三方授权权限与授权配置信息集成金蝶云SDK调用实现备注前言 对于有自己商品信息管理后台并且使用金蝶ERP系统管理物料的商家来说,将金蝶上物料的库存信息同步到管理后台就可以不用去金蝶上确认库存了,可以大大简化管理后台的库存变更工作,这篇文…...

pretrain Llama3
导入模块:导入了一些必要的模块,包括数学计算、时间处理、文件操作、深度学习框架(如torch)、以及自定义的LLama Transformer模型相关内容。 I/O配置:定义了模型输出路径、评估与日志记录的间隔步数、批次大小、最大序…...

[附源码]SpringBoot+VUE+Java实现人脸识别系统
今天带来一款优秀的项目:java人脸识别系统源码 。 系统采用的流行的前后端分离结构,内含功能包括 “人脸数数据录入”,“人脸管理”,“摄像头识别” 如果您有任何问题,也请联系小编,小编是经验丰富的程序员…...