【Java JVM】运行时数据区
JVM 在执行 Java 程序的过程中会把它管理的内存分为若干个不同的数据区域, 这些区域有着各自的用途。
根据《Java虚拟机规范》中规定, JVM 所管理的内存大致包括以下几个运行时数据区域, 如图所示:
这个运行时数据区被分为了 5 大块
- 方法区 (Method Area)
- 堆 (Heap)
- 虚拟机栈 (Virtual Machine Stacks)
- 本地方法栈 (Native Method Stacks)
- PC 寄存器 (Program Counter Register)
其中: 绿色部分是各个线程之间独享的部分, 而蓝色部分是所有线程共享的区域。
1 PC 寄存器 (Program Counter Register)
-
程序计数器是一块较小的内存分区, 你可以把它看做当前线程所执行的字节码的指示器(类似于, 记录了线程执行到了哪个位置, 下一步的位置)。在虚拟机的概念模型里, 字节码解释器工作时, 就是通过改变计数器的值来选择下一条需要执行的字节码指令。
-
程序技术器为线程私有, 每个线程都有它们各自的程序计数器, 这样在多线程的情况下, 线程之间的来回切换, 也能正确找到上次切换时执行的位置。
-
如果线程正在执行的是一个 Java 方法, 那么程序计数器记录的是当前线程正在执行的字节码指令的地址; 如果线程正在执行的是一个 native 方法, 则计数器值为空。
-
此内存区域是唯一一个 Java 虚拟机规范中没有规定任何 OutOfMemoryError (OOM) 情况的区域。
2 虚拟机栈 (Virtual Machine Stacks)
-
虚拟机栈是线程私有的, 它的生命周期与线程相同。
-
虚拟机栈可以看做是 Java 方法执行的内存模型: 每个方法执行的同时都会创建一个栈帧用于存储局部变量表, 操作数栈, 动态链接, 方法返回等信息。 一个 Java 方法从调用到执行完的过程, 就对应着一个栈帧从虚拟机栈入栈到出栈的过程。
-
局部变量表中存放了编译期可知的基本数据类型, 对象引用, returnAddress 类型 (指向了一条字节码指令的地址)。局部变量表里面的数据类型的存储空间是以槽 (Slot) 表示的, 64 位的 long 和 double 类型占 2 个槽, 其他的只占 1 个。局部变量表所需的内存空间在编译器就完成分配了, 运行期间不会改变局部变量表的大小, 既槽的个数是确定的 (但是一个槽的所占的空间大小, 则是有 JVM 自行实现的, 可以是 32b, 64b 等)。
-
在虚拟机栈中可能会出现两种异常:StackOverflowError 和 OutOfMemory。
4.1 如果线程请求的栈深度大于当前 JVM 所允许的深度, 会抛出 StackOverflowError 异常
4.2 虚拟机栈可以动态扩展, 当扩展时无法申请到足够的内存, 会抛出 OutOfMemory 异常
3 本地方法栈 (Native Method Stacks)
-
本地方法栈与虚拟机栈所发挥的作用是非常相似的, 其区别只是虚拟机栈为 JVM 执行 Java 方法服务, 而本地方法栈则是为虚拟机使用到的本地 (Native) 方法服务。
-
在 HotSpot 虚拟机中直接把本地方法栈和虚拟机栈合二为一。
-
同样的本地方法栈也会抛出 StackOverflowError 和 OutOfMemory。
4 堆 (Heap)
-
JVM 只有一个堆, 同样的所有的线程共享这个堆, 他的生命周期同样和 JVM 一样。
-
堆主要存放的是类的实例和被分配的数组数据。
-
堆是 JVM 中内存最大的一块, 也是垃圾回收管理的主要区域, 堆在物理上是可以为不连续的内存空间, 只要逻辑上连续即可。
-
堆的实现是可以固定大小, 也可以是动态扩展的, 当堆的内存使用完了, 同样会抛出 OutOfMemoryError。
5 方法区 (Method Area)
-
JVM 只有一个方法区, 所有的线程共享着这个唯一的方法区, 他的生命周期和 JVM 一样。
-
方法区用于存储已被 JVM 加载的类型信息, 常量, 静态变量, 即时编译器编译后的代码等数据。
-
方法区逻辑上是属于堆的一部分, 它却有一个别名叫作 “非堆” (Non-Heap), 用于区分堆 (Heap)。
-
方法区中, 垃圾回收比较少见, 但并不是不进行 GC, 这个区域的回收目标主要是针对常量池的回收和对类的卸载, 当方法区内存不足时, 会导致 OutOfMemoryError (OOM)。
-
《Java虚拟机规范》对方法区的约束是非常宽松的, 所以导致对不同的 JVM 对这个区域的实现有差异。比如: HotSpot 用永久代来实现方法区, 但是其他的 JVM 没有这种方式, 不存在永久代的概念的。
说到 HotSpot, 就不能不说不同 JDK 版本下, 方法区的实现和几个常量池的概念。
5.1 HotSpot 方法区的实现
在 JDK8 之前, HotSpot 方法区是通过永久代的方式实现的, 但是到了 JDK8, 方法区的实现改为元空间 (MetaSpace) 的方式, 同时从以前的堆空间移到了本地内存 (Native memory) 中。
Metaspace 的组成
- Klass Metaspace: 就是用来存 klass 的, klass 是我们熟知的 class 文件在 JVM 里的运行时数据结构, 这个区域不一定有的, 只有开启压缩指针, 同时
-Xmx
(设定程序运行期间最大可占用的内存大小) 小于等于 32G (大于这个临界值, 会导致压缩指针关闭), 才会有这个区域- NoKlass Metaspace: 专门来存 klass 相关的其他的内容, 比如 method, constantPool 等, 虽然叫做 NoKlass Metaspace, 但是也其实可以存 klass 的内容。当然了, 如果没有 Metaspace 的时候, klass 内容也会存储在这里。
上面说的临界值 32G 的确定, 可以看这里 聊一聊JAVA指针压缩的实现原理 (图文并茂, 让你秒懂)
5.2 常量池(Constant Pool)
在 JVM 中关于常量池的关键字有 class 常量池, 字符串常量池, 运行时常量池。
5.2.1 class 常量池
这里的 class 常量池, 主要指的是 class 文件里面的常量池。
当我们的 .java 文件编译为 .class 文件后, .class 文件里面有一个常量池的项,
用于存放编译器生成的各种字面量 (Literal) 和符号引用 (Symbolic References)。
字面量: 各种常量, 如文本字符串, final 的常量值。
符号引用: 一组符号描述所引用的目标。
class 常量池的内容, 如图
在 .class 文件中的样子大体如下
Constant pool:#1 = Methodref #4.#13 // java/lang/Object."<init>":()V#2 = Methodref #3.#14 // SymbolicReference.fn2:()V#3 = Class #15 // SymbolicReference#4 = Class #16 // java/lang/Object
5.2.2 字符串常量池 (String Constant Pool)
在 JVM 中有一个字符串常量池, 在我们平常创建字符串时, 会先到这个字符串池中查看是否已有相关的字符串了, 有的话直接使用这个字符串, 没有再创建然后加入到这个字符串常量池中。
在 HotSpot 里实现的字符串常量池功能的是一个 StringTable 类, 它是一个 Hash 表, 默认值大小长度是 1009 (JDK7 及后面的版本可以通过参数进行修改)。
这个 StringTable 在每个 HotSpot 的实例只有一份, 被所有的类共享。
当类加载到了 JVM 后, 类中涉及到的字符串常量, 在堆中生成字符串对象实例, 会将这些字符串对象实例的引用值存到字符串常量池中, 既存到 StringTable 中。
也就是我们的字符串常量具体的值是放在堆中的, 但是会有个引用指向它, 同时这个引用存放在 StringTable 中。
Java 有一道经典的题目
String s1 = new String("s1");
一共创建的多少个对象? 里面就涉及到对应的字符串是否已经在字符串常量池中存在。
具体的分析可以看一下这篇文章: 面试题系列第2篇:new String()创建几个对象?有你不知道的
5.2.3 运行时常量池 (Runtime Constant Pool)
当类加载到内存中后, JVM 就会将 class 文件的常量池中的内容存放到运行时常量池中。
运行时常量池相对于 class 文件常量池的另外一个重要特征是具备动态性
- class 文件常量池的符号引用存在运行时常量池中, 经过解析之后, 也就是把符号引用替换为直接引用
- 运行期间也可以将新的常量放入池中, 比如 String 的 intern() 方法
在 JDK8 之前 运行时常量池都是存放在方法区中, JDK8 及后面版本, 则将运行时常量池放到了堆中。
所以 HotSpot 在 JDK8 的时候, 运行时数据区是这样的
6 直接内存 (Direct Memory)
HotSpot 在JDK8 中, 将方法区的实现修改为了元空间的方式, 同时将元空间的存储移到了直接内存。
直接内存 (Direct Memory) 并不是虚拟机运行时数据区的一部分, 也不是《Java虚拟机规范》中定义的内存区域。
本机的直接内存的分配不会受到 Java 堆大小的限制, 但是会受到本机总内存的影响, 所以在内存不够的时候, 也会导致 OutOfMemoryError 异常。
7 参考
《深入理解Java虚拟机》- 周志明
相关文章:
【Java JVM】运行时数据区
JVM 在执行 Java 程序的过程中会把它管理的内存分为若干个不同的数据区域, 这些区域有着各自的用途。 根据《Java虚拟机规范》中规定, JVM 所管理的内存大致包括以下几个运行时数据区域, 如图所示: 这个运行时数据区被分为了 5 大块 方法区 (Method Area)堆 (Heap)虚拟机栈 (V…...
k8s中pod监控数据在grafana中展示
实现目标:将kubesphere[K8S]中运行的pod监控数据在grafana平台进行展示。 前提说明:需要在k8s每个集群中内置的prometheus配置中将pod指标数据远程写入到victoriametrics持久化数据库中。 实现效果如下: CPU使用量: round(sum by (namespace, pod) (irate(container_cpu…...
人机协同之间也有混馈机制
不懂数学的狮子,能精准的在最佳时刻、最佳路径捕捉到羚羊,这种天赋的“算计”能力,可谓叹为观止!里面既有反馈也有前馈,应该是混馈机制。混馈机制是指信息在系统中同时进行正向和反向的传递与调节。在狮子捕捉羚羊的过…...
微服务网关Gateway
springcloud官方提供的网关组件spring-cloud-starter-gateway,看pom.xml文件,引入了webflux做响应式编程,请求转发用到了netty的reactor模型,支持的请求数在1W~1.5W左右。hystrix停止维护后,官方推荐resilience4j做服务熔断,网关这里也能看到依赖。 对于网关提供的功能…...
flume:Ncat: Connection refused.
一:nc -lk 44444 和 nc localhost 44444区别 nc -lk 44444 和 nc localhost 44444 是使用 nc 命令进行网络通信时的两种不同方式。 1. nc -lk 44444: - 这个命令表示在本地监听指定端口(44444)并接受传入的连接。 - -l 选项…...
selenium 与 chromedriver安装
本文章向大家介绍selenium 安装与 chromedriver安装,主要包括selenium 安装与 chromedriver安装使用实例、应用技巧、基本知识点总结和需要注意事项供大家参考。 一、安装selenium 1、Selenium简介 Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开…...
【Unity】2D项目中如何让Camera展示的大小正好等于某一个Game Object的大小
【背景】 用Unity做工具软件的话希望Camera大小正好和界面Panel一致。 【方法一:手动调整】 相机设置成正交后手动调整边框,当然这种方法精确度不高。 【方法二:在Camera上追加如下脚本】 这里面的public变量里面拖放你想要对齐的目标对象即可。 using UnityEngine;pu…...
last block incomplete in decryption
测试AES加密参数时报出的错,对比参数,发现接口收到的请求参数少了个号。这是因为号在URL中是一个特殊字符,所以传递时可能会丢失。 处理方案 使用param.replaceAll(" ", "")统一替换空格为号。前端传递参数时,…...
Guardrails for Amazon Bedrock 基于具体使用案例与负责任 AI 政策实现定制式安全保障(预览版)
作为负责任的人工智能(AI)战略的一部分,您现在可以使用 Guardrails for Amazon Bedrock(预览版),实施专为您的用例和负责任的人工智能政策而定制的保障措施,以此促进用户与生成式人工智能应用程…...
flutter学习-day12-可滚动组件和监听
📚 目录 简介可滚动组件 SingleChildScrollViewListView separated分割线无限加载列表带标题列表 滚动监听和控制 ScrollController滚动监听NotificationListener滚动监听 AnimatedList动画列表滚动网格布局GridView 横轴子元素为固定数量横轴子元素为固定最大长度…...
LeetCode:967连续查相同的数字(DFS)
题目 返回所有长度为 n 且满足其每两个连续位上的数字之间的差的绝对值为 k 的 非负整数 。 请注意,除了 数字 0 本身之外,答案中的每个数字都 不能 有前导零。例如,01 有一个前导零,所以是无效的;但 0 是有效的。 …...
深入剖析NPM: Node包管理器的介绍和使用指南
导言:NPM(Node Package Manager)是JavaScript世界中最受欢迎的包管理器之一。它的出现大大简化了JavaScript开发过程中的依赖管理和模块化。本文将向您介绍NPM的基本概念、功能和常见用法,并为您提供一份详尽的NPM使用指南。 一、…...
AI视频-stable-video-diffusio介绍
介绍 stbilityai/stable-video-diffusion-img2vid-xt模型,由Stability AI开发和训练的基于散度的图像到视频生成模型。该模型可以接受一张静态图像作为条件,并生成出一个短视频。 该模型通过在SVD Image-to-Video [14帧]的基础上进行微调而来,可以生成576x1024分辨…...
day01-报表技术POI
前言 报表[forms for reporting to the higher organizations],就是向上级报告情况的表格。简单的说:报表就是用表格、图表等格式来动态显示数据,可以用公式表示为:“报表 多样的格式 动态的数据”。 1、开发环境搭建 功能说…...
如何预防最新的.locked、.locked1勒索病毒感染您的计算机?
尊敬的读者: 近期,网络安全领域迎来一股新潮——.locked、.locked1勒索病毒的威胁,其先进的加密技术令人生畏。本文将深入剖析.locked、.locked1勒索病毒的阴谋,提供特色数据恢复策略,并揭示锁定恶劣行径的先锋预防手…...
实现两张图片的接缝线拼接
使用ORB算法检测特征点,并通过BFMatcher进行特征点匹配。然后,根据Lowes ratio test选择好的匹配点,并使用findHomography计算单应性矩阵。最后,使用warpPerspective将图像进行透视变换,然后将第二张图像粘贴到变换后的…...
基于JNI 实现 嵌套 List 类型参数解析
基于JNI 实现 嵌套 List 类型参数解析 背景分析解决 背景 在前面两篇文章中,我们总结了Java 调用 C/C SDK 的几种方案,分享了JNI在实践过程中的一些踩坑点,而在这篇文章将继续分享针对Java List类型及其嵌套类型,我们的JNI如何接…...
探索灵活性与可维护性的利器:策略(Strategy)模式详解
目录 编辑 1. 策略模式概述: 2. 主要角色: 3. 实例场景: 4. 具体实现步骤: 步骤一:定义策略接口 5. 使用策略模式的客户端代码: 总结: 我的其他博客 1. 策略模式概述: 策…...
压缩包文件暴力破解 -Server2005(解析)
任务五十一: 压缩包文件暴力破解 任务环境说明:Server2005 1. 通过本地PC中渗透测试平台Kali使用Nmap扫描目标靶机服务版本信息,将 Telnet 版本信息字符串 作为 Flag 提交; flag:Microsoft Windows XP telnetd 2. 通过本地PC中渗透测试平台Kali对服务器场景Windows进行渗透测…...
mars3d加载arcgis发布的服务,⽀持4523坐标
问题 1.从这个服务地址加载,具体在哪⾥去转坐标呢? 加个 usePreCachedTilesIfAvailable:false 参数即可 坐标系为4490的arcgis影像服务图层,配置后瓦片加载不出来,没报错 甚至可以跳转 没有看出问题,或者测…...
『K8S 入门』二:深入 Pod
『K8S 入门』二:深入 Pod 一、基础命令 获取所有 Pod kubectl get pods2. 获取 deploy kubectl get deploy3. 删除 deploy,这时候相应的 pod 就没了 kubectl delete deploy nginx4. 虽然删掉了 Pod,但是这是时候还有 service,…...
十七、如何将MapReduce程序提交到YARN运行
1、启动某个节点的某一个用户 hadoopnode1:~$ jps 13025 Jps hadoopnode1:~$ yarn --daemon start resourcemanager hadoopnode1:~$ jps 13170 ResourceManager 13253 Jps hadoopnode1:~$ yarn --daemon start nodemanager hadoopnode1:~$ jps 13170 ResourceManager 15062 Jp…...
华为云CodeArts Deploy常见问答汇总
1.【Deploy】部署java项目,为什么通过springboot启动步骤启动失败了? 答:用户所部署的jar包源码并不是springboot框架,所以无法用springboot启动步骤启动,该步骤并不等同于java -jar 命令,需要使用shell脚…...
前后端交互—开发一个完整的服务器
代码下载 初始化 新建 apiServer 文件夹作为项目根目录,并在项目根目录中运行如下的命令,初始化包管理配置文件: npm init -y运行如下的命令,安装 express、cors: npm i express cors在项目根目录中新建 app.js 作为整个项目的入口文件&a…...
前端框架的虚拟DOM(Virtual DOM)
聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…...
什么是http状态码?
什么是http状态码? 当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含 HTTP 状态码的信息头(server header)用以响应浏览器的请求。 ht…...
linux/CentOS 7安装Nginx
Nginx 是 C语言 开发,建议在 Linux 上运行,当然,也可以安装 Windows 版本,本篇则使用 CentOS 7 作为安装环境。 Nginx一般使用非root账号安装,如果还没有非root账号,先创建账号 创建账号 创建组…...
软件工程期末复习+数据仓库ETL
一、软件工程 请用基本路径测试方法为下列程序设计测试用例,并写明中间过程: 第1步:画出流程图 1.菱形用于条件判断。用在有分支的地方。 2.矩形表示一个基本操作。 3.圆形是连接点 第2步:计算程序环路复杂性 流图G的环路复杂…...
学习C语言——体会计算机中的0和1
/* 把hello隐写入一个整型数组,这个小程序可以考察是否清楚数据在内存中存储的具体细节。 具体的说,int类型在小端机器上的存储方式是高位在高地址,低位在低地址,从视觉习惯上和我们的日常书写习惯相反; char类型占用…...
PyTorch官网demo解读——第一个神经网络(1)
神经网络如此神奇,feel the magic 今天分享一下学习PyTorch官网demo的心得,原来实现一个神经网络可以如此简单/简洁/高效,同时也感慨PyTorch如此强大。 这个demo的目的是训练一个识别手写数字的模型! 先上源码: fr…...
大连网站建设个人/站长工具whois查询
原标题:用Python打造一款文件搜索工具,所有功能自己定义!一、前言大家好,又到了Python办公自动化系列。在日常的办公中,我们经常会从一堆不同格式的文件(夹)中搜索特定的文件,可能你是凭着记忆去找或是借助…...
网站建设企业蛋糕/软文推广经典案例
git add -A和 git add . git add -ugit add . :监控工作区的状态树,运行会把工作时的所有变化提交到暂存区,包括文件内容修改(modified)以及新文件(new),但不包括被删除的文件。git add -u :仅监控已经被add的文件&…...
做预算查价格的网站是哪个/深圳百度首页优化
终于决定买空间了,不过鉴于国内建站太过于和谐了,所以只能考虑在国外购买。godaddy(中文是"去老爹"?囧~)算是国内用户用得最多的,而且做得确实也挺不错的,就买了一个域名和一个共享空间。买好后发现域名可用…...
wordpress的pingback/公司广告推广方案
[ASP.NET MVC2 系列] [ASP.NET MVC2 系列] ASP.Net MVC教程之《在15分钟内用ASP.Net MVC创建一个电影数据库应用程序》 [ASP.NET MVC2 系列] ASP.Net MVC教程之《ASP.NET MVC 概述》 [ASP.NET MVC2 系列] 理解MVC应用程序的执行过程 [ASP.NET MVC2 系列] ASP…...
网站1688批发/自己怎么优化网站排名
传送门 Description \(windy\)定义了一种\(windy\)数。不含前导零且相邻两个数字之差至少为\(2\)的正整数被称为\(windy\)数。\(windy\)想知道, 在\(A\)和\(B\)之间,包括\(A\)和\(B\),总共有多少个\(windy\)数? Input 包含两个整数…...
怎么做科技小制作视频网站/微信小程序
文章目录数学符号设变量时常用的希腊字母大小关系分数开方同余一般符号二项式符号上下添加额外信息上标符号上下标上下划线箭头集合省略号矩阵小括号形式中括号形式行列式带省略号的形式带横线或竖线分隔的形式逻辑运算分支公式间距设置颜色更多参考End数学符号 设变量时常用的…...