Java中的久负盛名的页面/物理内存

Eth*_*man 0 java paging x86 operating-system memory-management

我的目标是确保在连续的物理内存中分配在java中分配的数组.我遇到的问题是,除非我分配一个非常大的数组,否则分配数组的页面在物理内存中往往不是连续的.

我的问题是:

  • 为什么一个非常大的数组确保在物理内存中连续的页面?
  • 有没有办法确保跨物理内存分配数组,这不涉及使数组真的很大?
  • 如何在不测量缓存命中/缓存未命中的情况下,如何判断Java对象/阵列所在的页面或物理地址?

我不是在寻找答案,问我为什么要在java中这样做.我知道C会"解决我的问题",而且我反对java的基本性质.不过我有充分的理由这样做.

答案无法保证始终有效.我正在寻找大部分时间都有效的答案.创造性的,开箱即用的答案的额外点,没有合理的Java程序员会写.可以特定于平台(x86 32位64位).

MSa*_*ers 6

不可以.物理上连续的内存需要与操作系统直接交互.大多数应用程序,包括JVM只能获得几乎连续的地址.并且JVM无法向您提供从OS获得的内容.

此外,你为什么要这样?如果您正在设置DMA传输,那么您可能正在使用除Java之外的技术.

一点背景:

在可更换的DIMM模块上,现代PC中的物理内存通常是灵活的.它的每个字节都有一个物理地址,因此引导期间的操作系统会确定哪些物理地址可用.事实证明,不直接使用这些地址会使应用程序变得更好.相反,所有现代CPU(及其缓存)都使用虚拟地址.有一个到物理地址的映射表,但这不需要完整 - 通过使用未映射到物理地址的虚拟地址来启用交换到磁盘.每个进程有一个表,具有不完整的映射,从而获得了另一种灵活性.如果进程A有一个映射到物理地址X的虚拟地址,但进程B没有,那么进程B就无法写入物理地址X,我们可以认为该内存对于进程A是独占的.显然为了安全起见,操作系统必须保护对映射表的访问,但所有现代操作系统都可以.

映射表在页面级别工作.页面或物理地址的连续子集被映射到虚拟地址的连续子集.开销和粒度之间的权衡导致4KB页面是常见的页面大小.但是由于每个页面都有自己的映射,因此不能假设超出该页面大小的连续性.特别是,当页面从物理内存中被逐出,交换到磁盘并恢复时,最终可能会在新的物理内存地址处结束.程序没有注意到,因为虚拟地址没有改变,只有OS管理的映射表.

  • 对不起,你错了,你的问题没有任何证据.缓存命中与虚拟/物理无关,因为它们旨在解析虚拟内存中的地址.页表确定物理和虚拟内存之间的映射.在x86上,它在Ring 0上管理.JVM在Ring 3中运行,而tehrefore根本无法改变它. (2认同)

Tom*_*ine 5

鉴于垃圾收集器在(逻辑)内存中移动对象,我认为您会不走运。

关于你能做的最好的事情是使用ByteBuffer.allocateDirect。这(通常)不会被 GC 移动到(逻辑)内存中,但它可能会移动到物理内存中,甚至可以分页到磁盘。如果你想要任何更好的保证,你将不得不点击操作系统。

话虽如此,如果您可以将页面大小设置为与堆一样大,那么所有数组都必须在物理上连续(或换出)。