为什么 Java 堆可以处于物理上不连续的内存空间?

2020-11-07 11:47:11 +08:00
 zhao1014

JVM 为大对象分配内存时需要连续的内存空间,这个内存空间指的是逻辑上连续的内存空间吧?

在物理内存中对象有可能被拆分开分配到物理不连续的空间中吗?

如果 Java 堆逻辑连续的空间物理上并不连续,那么垃圾回收的过程中,由复制算法和标记-整理算法得到的空闲内存是不是也是逻辑上连续,物理上不一定连续?

JVM 运行时数据区是不是对物理内存的一部分的封装?如果是封装,那么逻辑内存与物理内存之间是不是存在一个映射关系?维护这个映射关系的开销不会很大么?为什么不要求物理连续呢?

5455 次点击
所在节点    Java
38 条回复
winglight2016
2020-11-07 17:57:52 +08:00
JVM 里的对象不需要“连续内存空间”,lz 恐怕是以为所有和某个对象相关的数据都放在连续的内存地址中(假设不区分是物理地址还是 JVM 的虚拟地址),但是并不是这样,一个 java Object 只需要声明就好了(我记得只需要 52 个字节),具体的数据是存在堆栈内存中的。

如果 lz 是专注 java 开发,那么是没必要了解 OS,先研究一下 JVM 吧。
systemcall
2020-11-07 19:02:14 +08:00
应用程序能够访问到的都是“虚拟内存”
硬盘上的是“页面文件”而不是“虚拟内存”,这 2 个不是一回事
一般的应用程序是拿不到“物理内存”的地址的。虚拟内存是硬件实现的(现在是 CPU 里面的 MMU 之类的部分来做),一般的应用是看不到这些东西的
Intel 这几年牙膏倒吸的漏洞,就和 Intel 的 MMU 的缺陷有关系,感兴趣的话可以看看
另外,现在的 SSD 也是映射过的。NAND 闪存非常容易有坏块,而且还要做均衡磨损、垃圾回收等一系列的事情。操作系统里可以看到的 LBA 和 SSD 内部 NAND   Flash 上的位置不是一一对应的,而是由 SSD 主控负责映射。如果 SSD 有 DRAM 缓存的话,DRAM 用来存放映射表
不用担心效率问题,因为是专门的硬件来完成。针对内存的一些性能测试,也在一定程度上反映了这套系统的性能
irytu
2020-11-07 19:38:33 +08:00
虚拟内存 物理地址都存在每个进程的页表 page table 里面 安全、好管理、也有利于简化一些内存相关的操作
zhao1014
2020-11-07 20:10:56 +08:00
@winglight2016 我是看了深入理解 java 虚拟机中垃圾回收方面的东西才有了这种想法,比如说:
使用复制算法留下的空间是规整的,标记清除算法会产生大量碎片空间,此时 jvm 会维护一个空闲列表来记录空闲内存,在为对象分配内存时选取足够大的连续空间。

所以才有了对“连续空间”的一些疑问
zhao1014
2020-11-07 20:23:54 +08:00
@systemcall 今天了解了一下关于存储器的知识:“内存与磁盘的动态交换。操作系统将正在使用的部分保存在内存中,其他部分留在磁盘,在需要时再从磁盘中读取,不用的数据再返回给磁盘。”

我感觉虚拟存储器好像跟大家说的虚拟内存不是一回事,虚拟存储器就是我们使用 Windows 系统时可以设置的虚拟内存,大家提到的“虚拟内存”似乎是对物理内存的一种封装?本质上是一层逻辑?我这样想是对的吗?
zclHIT
2020-11-07 20:33:05 +08:00
赞一下楼主,之前自己也没有仔细思考过这个问题,看了大家的讨论才恍然大悟,不说了我也去翻《操作系统》去了。。。
Huelse
2020-11-07 21:25:03 +08:00
段页式内存管理,这个是操作系统维护的,而且有专门的寄存器来映射地址

这个是操作系统中内存管理的基础
DOLLOR
2020-11-07 21:55:20 +08:00
外行人眼中:
虚拟内存=页面文件

计算机专业里:
虚拟内存=物理内存+页面文件(linux 下叫交换区)

由此可见,所谓的虚拟内存,是对多种存储介质的一层封装。
对应用程序来说,它们都是在虚拟内存里工作的,并不需要关心自己到底在物理内存里还是页面文件里。至于决定它们要运行在物理内存里还是页面文件里,那时操作系统的工作。

如果你使用的是 win10 、win8 操作系统,可以打开任务管理器->性能标签->内存,仪表盘下面有个“已提交”,表现为类似 数字 A / 数字 B 形式。这里体现的就是虚拟内存(计算机专业里)的使用状态,数字 A 是已分配给程序的虚拟内存,数字 B 虚拟内存总大小——大致就是你的内存+设置的页面文件大小。

生活中常常看到有人抱怨,“明明可用内存还有那么多,系统却提示内存不足了”,那是因为他们只留意物理内存还有可用空间,但实际上 windows 是根据虚拟内存(上述的“已提交”)来判断内存不足的,这时候就要通过增大页面文件大小,才能缓解“内存不足”。
mejee
2020-11-07 22:09:43 +08:00
@winglight2016 需要连续空间的。比如数组。或者成员变量比较多的对象,需要的空间也大一些
zhao1014
2020-11-07 22:35:21 +08:00
@DOLLOR 感谢!
quanjw
2020-11-07 22:52:16 +08:00
《程序员的自我修养—链接、装载与库》 emmm 其实我也没看完,但是你这个问题 我有看到过解释
winglight2016
2020-11-08 11:08:57 +08:00
@mejee 你说的是那种原生类型的数组吧,那种 element 都不是对象,连续存储就比较方便,但是也依然可以分开存储。

@zhao1014 对象不需要连续存储不代表一定要分开存储,也不代表 JVM 全部不需要连续存储。而且 JVM 维护的空闲内存列表和运行时产生的内存分配略有不同,JVM 是负责 java 程序和 OS 之间的交互层,所以 java 内部的内存管理和 OS 的内存没什么直接的关系。所以,连续内存最大的好处在于提高存储效率,减少读写时间,然而因为 GC 机制,内存碎片化难以避免。
systemcall
2020-11-08 12:15:09 +08:00
@zhao1014 虚拟内存不仅仅是含有物理内存,还有页面文件,甚至有些地址根本没分配内存
而且,如果是 32 位的 Windows,进程空间只有 2G,这 2G 也没有都分页,也只有一部分页在物理内存。一些文章介绍的很详细。
m30102
2020-11-08 14:00:53 +08:00
听过 4k 对齐吗? mmu 管理的最小单位就是 4k
Junzhou
2020-11-08 20:52:21 +08:00
看来你跟我一样,操作系统的知识都还给老师了。
xx6412223
2020-11-09 09:46:39 +08:00
任何进程的内存都可以是物理不连续的,或者说不连续才是正常情况。不是面试想了解 jvm 还是建议先看 Linux 内存管理
zhao1014
2020-11-09 10:58:18 +08:00
@xx6412223 虽然是为了应对面试,但还是想理解清楚 XD,会继续深入学习的
xingguang
2020-11-09 11:03:15 +08:00
本来物理内存是否连续和逻辑内存是否连续就没关系的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/722646

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX