JVM 为大对象分配内存时需要连续的内存空间,这个内存空间指的是逻辑上连续的内存空间吧?
在物理内存中对象有可能被拆分开分配到物理不连续的空间中吗?
如果 Java 堆逻辑连续的空间物理上并不连续,那么垃圾回收的过程中,由复制算法和标记-整理算法得到的空闲内存是不是也是逻辑上连续,物理上不一定连续?
JVM 运行时数据区是不是对物理内存的一部分的封装?如果是封装,那么逻辑内存与物理内存之间是不是存在一个映射关系?维护这个映射关系的开销不会很大么?为什么不要求物理连续呢?
1
hello2060 2020-11-07 11:51:23 +08:00 via iPhone
没研究过这么高深的问题,既然 java 里都是指针,为啥必须连续空间?你一个对象创建出来只是把成员初始化了,这时候成员还不一定指向任何有意义的东西呢,连续空间有啥用
|
2
vk42 2020-11-07 11:53:42 +08:00 3
物理地址一般对用户态程序是不可见的,至于虚拟地址到物理地址映射是 OS 维护的事,JVM 没必要多管闲事
|
3
zhao1014 OP @hello2060 可是 jvm 分配大对象内存要求连续空间,指针指向的是对象所占内存空间的起始地址,也就是第一个字节的地址,再通过对象的类型得知该对象所需空间具体大小然后顺序读取内存
|
4
noe132 2020-11-07 12:04:18 +08:00 1
应用程序没有权限直接操作物理内存的,操作的都只是虚拟内存,内存分配是 OS 的工作。至于怎么分配,怎么映射,又多大开销,《操作系统》欢迎你
|
7
zhao1014 OP @noe132 你说的虚拟内存是不是虚拟存储器,本质上是存储在磁盘上,只在需要的时候才会被读取到内存里?
|
10
secondwtq 2020-11-07 12:20:39 +08:00 via iPhone 1
“维护这个映射关系的开销不会很大么”
这个开销由硬件承担。可能有其他的方案,但是现在主流硬件都针对这个优化,已经形成了路径依赖 |
11
julyclyde 2020-11-07 12:22:41 +08:00 1
应用程序看不到物理内存的地址空间
所以讨论在物理地址空间是否连续根本就是个 NULL 问题 |
12
BrettD 2020-11-07 12:31:18 +08:00 via iPhone 1
物理内存映射是操作系统内核管的事情,JVM 只管到逻辑地址
|
13
hello2060 2020-11-07 12:31:58 +08:00 1
@zhao1014 虚拟内存应该只是一个虚拟的东西,他映射到实际存储数据的地方,可以在内存上也可以在磁盘里。
我前面的回答其实和你问的不是一回事。但是比如说一个飞机对象,包含 100 个乘客对象,也就是飞机对象有 100 个乘客对象的 reference, 这些 reference 可以是在连续空间里的(不管实际存储位置是不是连续的),但是具体每一个乘客对象,完全可以在不连续的位置上(这个更不可能要求实际存储位置是连续的,因为每个乘客对象都是独立的,完全可以在不同的时间地点被创建)再到飞机对象被销毁的时候,乘客对象完全可能还继续存在着,要求物理连续没有意义啊。--- 如果我说的不是你问的,你可以忽略嘿嘿 |
15
mejee 2020-11-07 12:39:45 +08:00 1
这里的连续地址,指的是虚拟内存的连续,而不是物理内存的连续。可以理解为虚拟内存统一受 JVM 管理,当分配大对象时候,需要在虚拟内存地址中,找到连续的内存(因为 JVM 管理虚拟内存,所以虚拟内存也是有碎片化使用的)
|
16
misaka19000 2020-11-07 12:43:13 +08:00 2
学学操作系统吧。。。CPU 有一个部件叫做 MMU,用来管理物理内存页。
或者看我之前写的文章 https://www.nosuchfield.com/2018/11/23/Program-compilation-linking-loading-and-running/ 中第四部“装载”中介绍的过程 |
17
Jooooooooo 2020-11-07 12:53:51 +08:00 1
你可以研究下操作系统虚拟内存和物理内存的映射管理.
|
18
zhao1014 OP @misaka19000 感谢,发现了一个错别字,
“但其实每个旅行图手中的地图都是不一样的,这个地图保证客人绝对不会找到一个已经被别人使用的房间”旅行图→旅行团 |
19
misaka19000 2020-11-07 13:42:05 +08:00
@zhao1014 #18 感谢,已经修改
|
20
nightwitch 2020-11-07 14:40:56 +08:00 1
推荐去看 csapp 的第九章:虚拟内存,关键词:页表,换页和 page fault 。
对应用程序来说内部见到的地址都是虚拟的,由虚拟地址往物理地址的映射这部分是由操作系统和硬件 mmu+tlb 单元来控制的。 |
21
winglight2016 2020-11-07 17:57:52 +08:00 1
JVM 里的对象不需要“连续内存空间”,lz 恐怕是以为所有和某个对象相关的数据都放在连续的内存地址中(假设不区分是物理地址还是 JVM 的虚拟地址),但是并不是这样,一个 java Object 只需要声明就好了(我记得只需要 52 个字节),具体的数据是存在堆栈内存中的。
如果 lz 是专注 java 开发,那么是没必要了解 OS,先研究一下 JVM 吧。 |
22
systemcall 2020-11-07 19:02:14 +08:00 1
应用程序能够访问到的都是“虚拟内存”
硬盘上的是“页面文件”而不是“虚拟内存”,这 2 个不是一回事 一般的应用程序是拿不到“物理内存”的地址的。虚拟内存是硬件实现的(现在是 CPU 里面的 MMU 之类的部分来做),一般的应用是看不到这些东西的 Intel 这几年牙膏倒吸的漏洞,就和 Intel 的 MMU 的缺陷有关系,感兴趣的话可以看看 另外,现在的 SSD 也是映射过的。NAND 闪存非常容易有坏块,而且还要做均衡磨损、垃圾回收等一系列的事情。操作系统里可以看到的 LBA 和 SSD 内部 NAND Flash 上的位置不是一一对应的,而是由 SSD 主控负责映射。如果 SSD 有 DRAM 缓存的话,DRAM 用来存放映射表 不用担心效率问题,因为是专门的硬件来完成。针对内存的一些性能测试,也在一定程度上反映了这套系统的性能 |
23
irytu 2020-11-07 19:38:33 +08:00 via iPhone
虚拟内存 物理地址都存在每个进程的页表 page table 里面 安全、好管理、也有利于简化一些内存相关的操作
|
24
zhao1014 OP @winglight2016 我是看了深入理解 java 虚拟机中垃圾回收方面的东西才有了这种想法,比如说:
使用复制算法留下的空间是规整的,标记清除算法会产生大量碎片空间,此时 jvm 会维护一个空闲列表来记录空闲内存,在为对象分配内存时选取足够大的连续空间。 所以才有了对“连续空间”的一些疑问 |
25
zhao1014 OP @systemcall 今天了解了一下关于存储器的知识:“内存与磁盘的动态交换。操作系统将正在使用的部分保存在内存中,其他部分留在磁盘,在需要时再从磁盘中读取,不用的数据再返回给磁盘。”
我感觉虚拟存储器好像跟大家说的虚拟内存不是一回事,虚拟存储器就是我们使用 Windows 系统时可以设置的虚拟内存,大家提到的“虚拟内存”似乎是对物理内存的一种封装?本质上是一层逻辑?我这样想是对的吗? |
26
zclHIT 2020-11-07 20:33:05 +08:00 1
赞一下楼主,之前自己也没有仔细思考过这个问题,看了大家的讨论才恍然大悟,不说了我也去翻《操作系统》去了。。。
|
27
Huelse 2020-11-07 21:25:03 +08:00
段页式内存管理,这个是操作系统维护的,而且有专门的寄存器来映射地址
这个是操作系统中内存管理的基础 |
28
DOLLOR 2020-11-07 21:55:20 +08:00 1
外行人眼中:
虚拟内存=页面文件 计算机专业里: 虚拟内存=物理内存+页面文件(linux 下叫交换区) 由此可见,所谓的虚拟内存,是对多种存储介质的一层封装。 对应用程序来说,它们都是在虚拟内存里工作的,并不需要关心自己到底在物理内存里还是页面文件里。至于决定它们要运行在物理内存里还是页面文件里,那时操作系统的工作。 如果你使用的是 win10 、win8 操作系统,可以打开任务管理器->性能标签->内存,仪表盘下面有个“已提交”,表现为类似 数字 A / 数字 B 形式。这里体现的就是虚拟内存(计算机专业里)的使用状态,数字 A 是已分配给程序的虚拟内存,数字 B 虚拟内存总大小——大致就是你的内存+设置的页面文件大小。 生活中常常看到有人抱怨,“明明可用内存还有那么多,系统却提示内存不足了”,那是因为他们只留意物理内存还有可用空间,但实际上 windows 是根据虚拟内存(上述的“已提交”)来判断内存不足的,这时候就要通过增大页面文件大小,才能缓解“内存不足”。 |
29
mejee 2020-11-07 22:09:43 +08:00
@winglight2016 需要连续空间的。比如数组。或者成员变量比较多的对象,需要的空间也大一些
|
31
quanjw 2020-11-07 22:52:16 +08:00
《程序员的自我修养—链接、装载与库》 emmm 其实我也没看完,但是你这个问题 我有看到过解释
|
32
winglight2016 2020-11-08 11:08:57 +08:00
|
33
systemcall 2020-11-08 12:15:09 +08:00 via Android 1
@zhao1014 虚拟内存不仅仅是含有物理内存,还有页面文件,甚至有些地址根本没分配内存
而且,如果是 32 位的 Windows,进程空间只有 2G,这 2G 也没有都分页,也只有一部分页在物理内存。一些文章介绍的很详细。 |
34
m30102 2020-11-08 14:00:53 +08:00
听过 4k 对齐吗? mmu 管理的最小单位就是 4k
|
35
Junzhou 2020-11-08 20:52:21 +08:00
看来你跟我一样,操作系统的知识都还给老师了。
|
36
xx6412223 2020-11-09 09:46:39 +08:00
任何进程的内存都可以是物理不连续的,或者说不连续才是正常情况。不是面试想了解 jvm 还是建议先看 Linux 内存管理
|
38
xingguang 2020-11-09 11:03:15 +08:00
本来物理内存是否连续和逻辑内存是否连续就没关系的
|