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.arraycopyfor() 循环快得多。先试试看,如果还是瓶颈,再找其他办法。 @AlexeiKaigorodov 实际上 MPJ Express 在传输之前使用ByteBuffer 作为内部存储,asIntBuffer 是从ByteBuffer 检索IntBuffer 并将数据从用户int [] 打包到其中src,使用IntBufferput(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 内部实现的?的主要内容,如果未能解决你的问题,请参考以下文章

为啥java虚拟机jvm要把byte和short的运算都转为int

JVM内幕:Java虚拟机详解

JVM内幕:Java虚拟机详解

JVM之Java虚拟机详解

JVM内幕:Java虚拟机详解

int[] 和 Integer[] 数组 - 有啥区别?