从进程的角度来看JVM的内存分布

news2024/9/22 17:16:41

JVM(下面JVM都是指代HotSpot)本质上是运行在操作系统上的一个C++程序,本文会从这个角度来构建对于JVM内存的完整视角,以HotSpot这个JVM实现运行在Linux操作系统上进行分析,在分析的过程中会解释清楚一些不太好理解的概念,诸如堆外内存,NIO可以避免native堆与java堆的数据拷贝...

一、JVM进程内存占用图像

图像拆解解析

用户态虚拟内存、内核态虚拟内存,动态映射与线性映射

上图中机器持有4G的物理内存,JVM进程则对应4G的虚拟内存空间(物理内存与虚拟内存大小并不需要保持一致); PS:为什么以4G(32位)为例,因为64位的设计因为地址空间足够反而简单一些。

可以看到在虚拟地址空间中,0G~3G的虚拟地址空间为用户空间,3G~4G的虚拟地址空间为内核空间;因为CPU是通过虚拟地址进行内存访问,而内核空间需要访问所有的物理地址,所以需要在1G的内核空间映射4G的物理地址

  • 内核在3G~3G+896MB的空间中进行线性映射,即从物理地址0~896MB的部分(ZONE_DMA+ZONE_NORMAL),直接加上3GB的偏移(在Linux中用PAGE_OFFSET表示);

  • 在3G+896MB~4G的空间中进行动态映射,即对于ZONE_HIGHMEM中的某段物理内存和这128M中的某段虚拟空间建立映射,完成所需操作后,需要断开与这部分虚拟空间的映射关系,以便ZONE_HIGHMEM中其他的物理内存可以继续往这个区域映射;

PS:为什么内核空间需要访问所有的物理地址,举个简单的例子,对于read某个磁盘文件的调用,需要将pageCache中的数据拷贝到用户空间的缓冲区中,所以内核空间需要访问所有的物理地址;

JVM进程载入,操作系统进行进程初始化

首先,Linux会通过JVM的ELF(进程的二进制代码)进行进程启动,并放入上图中最左侧的text段(只读)

  • 在初始化过程中,data段存储已初始化的全局变量,bss段存储未初始化的全局变量,C stack段 也就建立了;
  • 接着在JVM进程运行的过程中,需要加载一些lib.so的动态链接库,或者通过mmap进行一些共享内存的映射;
  • 然后HotSpot会通过brk(mmap)进行C heap的扩展,并在C heap中进行Java Heap、MetaSpace区域的初始化;初始化的过程中,会通过Java堆中的ClassLoader将jar中的.class文件加载到metaDataSpace中,并在堆中生成对应的class对象
  • 在执行过程中,会进行一些线程的初始化,因为HotSpot采用的是Java线程与操作系统线程为1:1的线程模型,因此在Linux下会直接调用glibc的pthread_create进行线程创建,并为该线程创建一套栈(内核栈与用户栈),内核栈用于线程陷入内核态时进行使用,而HotSpot对于JVM概念中的Java栈与本地方法栈,则是将JVM栈与本地方法栈二合一,使用用户栈进行实现;具体的代码分析可以参考这篇博客:JVM线程源码浅析-JVM线程如何映射到操作系统线程 - 掘金 (juejin.cn)

二、绕过JVM管理进行内存使用的方式

为什么使用内存要绕过JVM的内存管理(主要是GC)?《深入理解Java虚拟机》第二章的引言我觉得恰到好处,“Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来。”

站在内存使用的角度来讲:1)JVM中一切皆对象,数据的对象存储会带来所谓object overhead,浪费空间;2)如果由JVM来管理缓存,会受到GC的影响,并且过大的堆也会拖累GC的效率,降低吞吐量;并且GC会导致对象移动,改变了对象的地址,对于数据buffer而言即为没有稳定的地址,与一些系统调用不能很好适配

使用Native堆(直接内存、DirectByteBuffer)

Native堆指不由JVM直接管理的C Heap(除了JavaHeap、MetaDataSpace等JVM运行时占用的剩余空间),一般通过UnSafe.allocateMemoryByteBuffer.allocateDirect等navtie方法进行申请,并通过存储在JVM堆中的DirectByteBuffer对象作为对这块内存的引用进行操作;

Java中的NIO类使用native方法申请直接内存,以此避免在JVM堆和native堆中来回复制数据,提高效率;但是从native堆到JVM堆的copy是因为JVM本身机制的限制,因为writeread等系统调用都需要传入读/写buffer的起始地址和buffer count作为参数,这两个参数使得JVM需要进行冗余的内存拷贝:

  • GC机制的限制:因为JVM会进行GC,会导致JVM堆中的buffer(byte[],即HeapByteBuffer)进行移动,所以在Java BIO时需要mark此段内存不能移动,从而影响GC效率;而另一种方式是将byte[] 复制到到C Heap,并通过DirectByteBuffer进行引用,即使发生GC,JVM堆内的DirectByteBuffer发生地址变化也不会影响buffer的地址,比较稳定。因此相比于copy到C Heap,不如直接读写DirectByteBuffer,也就避免了一次多余的内存拷贝。
  • JVM内存使用的限制,JVM规范中byte[]并不一定需要在连续的虚拟地址空间中,但是writeread这类系统调用需要连续的地址空间,但是C Heap中分配的内存可以是连续的。

不过因为JVM是用户进程,对于直接内存JVM使用malloc进行内存申请,因此比一般在堆内申请内存慢,因此一般使用NIO的网络框架都会维护对自身使用的直接内存进行池化,避免频繁申请释放的同时,也是避免内存泄漏。

PS:设置-XX:NativeMemoryTracking=detail,可以通过jcmd pid VM.native_memory detail命令查看直接内存的内存分布

文件读取(Java FileChannel)

对于Kafka这种会使用pageCache进行有序读、追加写的Java应用而言,对于内存中pageCache的使用尤为关键。

  • 当生产者发送生产请求到kafka broker时,broker使用FileChannel.write()(对应pwrite系统调用),将数据按照文件偏移量先写到pageCache中,然后再等待flusher异步线程刷到磁盘中。因为kakfa采用稀疏索引,写入一定量后会使用FileChannel.map()(对应mmap系统调用,用户空间位置在第一张内存图中的MemoryMapping段)生成的MappedByteBuffer对索引文件进行写入;
  • 当消费者发送消费请求到kafka broker时,broker使用FileChannel.transferTo(对应sendFile系统调用),将数据从pageCache传输到broker的Socket buffer,再通过网络传输。

对于kafka这类的系统而言,这些数据也无需拷贝到JVM中去,利用操作系统自身的机制便可以管理的很好;因此一般kafka的服务堆可以设置小一些,将更多的内存分配给pageCache,有更好的吞吐量。

PS:当然不是读文件都一定都会经过pageCache,比如对于Mysql而言,在进行读文件的时候,会设置O_DIRECT绕过pageCache,因为pageCache是以文件为缓存单元进行管理,Mysql中存在一些抽象概念,诸如表空间..,这些抽象概念会用于查询,但与文件并不是一一对应的关系,所以Mysql自己维护了一个缓存池(BufferPool),可以基于自身的抽象概念进行查询。

三、总结

本文主要介绍了从JVM进程角度看JVM内存空间占用的视角;借助Kafka对FileChannel的使用介绍了Java如何使用pageCache,并借助NIO分析了为什么要使用直接内存;本地内存中还有JNI MemoryCodeCache,因为JNI的内容相对较多,后面会单独写。

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

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

相关文章

双十二哪些数码好物值得入手?盘点双十二最值得入手的数码好物

双十二快到了,相信很多人像我一样想趁着年末入手数码产品,但又不知道什么值得入手。最近也听到很多人问,针对这个问题,我来给大家盘点双十二最值得入手的数码好物,有需要的可以当个参考。 一、南卡小音舱蓝牙耳机 推…

怎样批量查询网站是否被搜狗收录?批量查询网站搜狗收录的详细教程

怎样批量查询网站是否被搜狗收录?批量查询网站搜狗收录的详细教程 批量查询网站搜狗收录的的具体操作: 第一步、打开站长工具 第二步、添加需要查询的网站域名 第三步、勾选要查询的功能(勾选搜狗是否收录和搜狗总收录) 第四步、提交查询 第…

手把手教你在Ubuntu22.04 上安装 Vivado、HLS、Vitis 2022.2版本

文章目录1 Vivado22.2 和 HLS 22.2 安装下载安装包执行.bin文件开始安装命令配置启动问题2 Vitis 22.2 安装3 卸载Xilinx我是 雪天鱼,一名FPGA爱好者,研究方向是FPGA架构探索和数字IC设计。欢迎来关注我的B站账号,我将定期更新IC设计教程。 …

手撕红黑树 | 变色+旋转你真的明白了吗?【超用心超详细图文解释 | 一篇学会Red_Black_Tree】

说在前面 我们也很久没有更新数据结构系列了,半年前博主重新深入学习了红黑树这个数据结构,一直想更新呈现给大家,最近也一直没有时间,今天红黑树它来了! 博主为了这篇博客,做了很多准备,试了…

怎么修复老照片?给你推荐这几个修复方法

相信大家的家里都有老照片吧,那在你们翻看这些老照片的时候,有没有发现有些老照片变得有些破旧、泛黄、模糊等情况呢?看到这些情况,大家是不是会很心疼呢?因为这些老照片都充满了各种各样的回忆,根本拍不出…

Docker查看容器的初始启动命令参数的常见几种方式

1.在使用docker容器的过程中,经常需要查看容器启动的命令来看当时启动容器时候所用的参数,如果时间不是很久或者通过history命令就可以很容易的想起或查看到命令,一旦时间过了很久或history被清空那么就无法获取命令,如下所示dock…

cengbox2靶机(hydra爆破、公私钥免密登录)

环境准备 靶机链接:百度网盘 请输入提取码 提取码:zdpr 虚拟机网络链接模式:桥接模式 攻击机系统:kali linux 2021.1 信息收集 1.arp-scan -l探测目标靶机ip 2.nmap -p- -A -T4 192.168.1.107 探测目标靶机开放端口和服务 …

Docker基本使用

1、centos7安装docker engine 参考文档:https://docs.docker.com/engine/install/centos/ (1)卸载之前的docker sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \…

Spring——AOP

Spring中的可插拔组件技术 Spring AOP Spring AOP——Aspect Oriented Programming 面向切面编程AOP 的做法是将通用的、与业务无关的功能抽象封装为切面层切面可配置在目标方法执行前后,做到即插即用 不修改源码对程序功能进行拓展 AoP的关键概念 Spring AoP 与A…

栈与队列3:有效的括号

主要是我自己刷题的一些记录过程。如果有错可以指出哦,大家一起进步。 转载代码随想录 原文链接: 代码随想录 leetcode链接:20. 有效的括号 题目: 给定一个只包括 ‘(’,‘)’,‘{’,‘}’&am…

怎样才能批量查询网站的谷歌PR权重?把手教你批量查询网站谷歌PR权重值

谷歌PR是Google排名运算法则(排名公式)的一部分,用来标识网页的等级/重要性。在计算网站排名时,PageRank会将网站的外部链接数考虑进去。一个网站的外部链接数越多其PR值就越高;外部链接站点的级别越高,网站…

docker安装nginx代理nacos2.1.2版本集群

目录 安装docker最新版本 创建一个docker network,使之固定docker局域ip docker安装mysql主从 配置挂载的my.cnf配置文件 进入mysql主数据库容器命令 登录主数据库创建用于从数据连接主数据的账号密码 输入show master status;查看master数据库状态 在从数据库…

基于训练和推理场景下的MindStudio高精度对比

摘要:MindStudio提供精度比对功能,支持Vector比对能力。本文分享自华为云社区《【MindStudio训练营第一季】MindStudio 高精度对比随笔》,作者:Tianyi_Li。 训练场景下,迁移原始网络 (如TensorFlow、PyTorch) &#x…

[附源码]Python计算机毕业设计SSM家纺商品展示平台(程序+LW)

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

连锁门店进销存软件的用途

门店式经营对于很多经营有道的老板来说是第一步,在规模扩张中,生意越做越大。这时要想拓宽销路,让收益更上一层楼,连锁、分店确实是一种行之有效的方法。 多门店管理经营存在的长久性难点是决策性工作量激增,管理方面…

[附源码]计算机毕业设计勤工俭学管理小程序Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

Multimodal Token Fusion for Vision Transformers

水平太浅,理解不到位。谨慎观看。 多模态token融合,我是语义分割,只看RGB和Depth模态。 1:作者为了解决transformer多输入的问题,对基于transformer视觉任务进行剪枝,为了有效的融合多模态,toke…

Docker(一) ----初始Docker

文章目录前言一、什么是 Docker1.1 Docker 的定义1.2 Docker对于上述问题的解决二、Docker 与虚拟机三、Docker 架构3.1 镜像和容器3.2 Docker 和 Docker Hub3.3 Docker 架构四、安装Docker4.1 卸载 (可选)4.2 安装Docker4.3 启动 Docker4.4 配置镜像加速总结前言 本文章主要是…

艾美捷肝细胞培养基试剂盒说明书

肝细胞培养基是专门为正常人类肝细胞体外培养设计的最适于其生长的培养基,是经灭菌的液体培养基,包含必需和非必需氨基酸、维生素、有机和无机化合物、激素、生长因子、微量矿物质和低浓度胎牛血清(5%)。 艾美捷肝细胞培养基试剂盒为我们的大鼠肝细胞设计…

WIN10商业版64位22H2正式版19045.2251MSDN11月原版镜像

微软表示 Windows 10 是迄今为止最好的 Windows 操作系统。无论你是普通办公用户、游戏玩家还是开发者,Win10 都能带给你目前最先进的功能特性以及使用体验。 其实微软对 Windows 10 版本的命名一直没有什么统一标准,最新的「22H2」是以开发代号命名的。…