Java int[ ] 数组是如何在 JVM 内部实现的?
Posted
技术标签:
【中文标题】Java int[ ] 数组是如何在 JVM 内部实现的?【英文标题】:How Java int[ ] array is implemented inside JVM? 【发布时间】:2014-04-10 11:12:06 【问题描述】:我试图了解 JVM 如何在内部实现原始类型数组,例如 int []
我的问题分为两部分:
1 - 它在内部使用 ByteBuffer 吗?我在哪里可以找到源代码,然后可能根据我的需要进行更改(以制作我自己的修改后的 JVM)。
2 - 有没有办法欺骗javac
不使用int []
的内置实现,而是使用类路径-cp
中的库提供的实现?这可能吗?如何实现?
我的动机是在 JVM 外部的内存中声明此 int []
(使用 allocateDirect()
)并从本机 JNI 代码外部访问它。这应该避免内存复制开销。
-B
【问题讨论】:
【参考方案1】:int[] 是原始类型。 ByteBuffer 可能基于 int[] 但相反的情况肯定不正确。它几乎肯定是一个字对齐的连续内存块,在该块的每个字中存储 32 位值。有几个JVM是开源的,如果你真的想看代码,你可以去看看,但它会是高级的东西。
没有简单的方法可以做到这一点。
听起来您正在尝试以非常复杂的方式做某事。最好描述您正在尝试解决的实际问题,而不是通过尝试解决该问题来询问问题。
【讨论】:
我正在使用 MPJ Express(Java 中的 MPI 实现),它使用内部缓冲层来缓冲用户数据。问题在于这种缓冲。在高端互连(Infiniband)上,将数据复制到内部缓冲层会显着降低性能,即与原生 C MPI 实现(如 MVAPICH 或 Open MPI)相比带宽相对较低。所以我想绕过这个缓冲层,直接访问用户数据而不改变API(用户程序)。 @Bibrak 你用System.arraycopy
复制数据吗?
@AlexeiKaigorodov 但它不会复制吗?我想做一个零拷贝
@Bibrak System.arraycopy
比 for()
循环快得多。先试试看,如果还是瓶颈,再找其他办法。
@AlexeiKaigorodov 实际上 MPJ Express 在传输之前使用ByteBuffer
作为内部存储,asIntBuffer
是从ByteBuffer
检索IntBuffer
并将数据从用户int []
打包到其中src,使用IntBuffer
put(int[] src, int offset, int length)
的标准API函数。优化就在那里。但我只是想去掉这个内部缓冲,直接在 JNI 中访问用户 int []
。【参考方案2】:
您可以使用 sun.misc.Unsafe 来分配和访问原始共享内存,而不是使用 Java IntBuffer 或 JNI。这很危险,但它绝对是从 Java 和其他进程访问共享内存的最快方式。
不安全方法的有用指南是here。
【讨论】:
sun.misc.Unsafe
确实提供了分配本机内存的选项,但问题仍然存在,因为用户数组(普通、普通、原始数组)并未在本机隐式分配。
对。它是 Java 数组的替代方案,可以更轻松地与其他进程进行互操作。虽然如果你可以做一些非常不安全的诡计来让 JVM 相信它可以作为具有标准语法的 int[] 数组访问,我不会感到惊讶 - int[] 的内存中标头非常简单。嗯……
你的意思是有一个自定义的 JVM 吗?
不需要自定义JVM;可以使用 Unsafe 进行任意内存突变。其中一些突变使您可以创建具有与 Java 数组相同的布局、堆外的结构。唯一的问题是您是否可以采用该结构并将其转换为“适当的”int []。我有点相信这是可能的,但我还没有尝试过。以上是关于Java int[ ] 数组是如何在 JVM 内部实现的?的主要内容,如果未能解决你的问题,请参考以下文章