为什么 Java 使用本机库时使用的内存是 Linux 下 C 程序使用时的 1.5 倍?

发布于 2024-08-19 06:26:12 字数 665 浏览 4 评论 0原文

我用 C 编写了一个库,它消耗大量内存(数百万个小块)。我编写了使用这个库的 ac 程序。我编写了一个使用相同库的java程序。 Java 程序是库周围非常薄的一层。基本上只有一种本机方法被调用,完成所有工作并在几小时后返回。 Java 和本机库之间不再使用 java 调用接口进行进一步的通信。也不存在消耗大量内存的 Java 对象。

所以C程序和Java程序非常相似。整个计算/内存分配发生在本机库内。仍然。执行时,c 程序消耗 3GB 内存。但是Java程序消耗了4.3GB! (顶部报告的 VIRT 量)

我检查了 Java 进程的内存映射(使用 pmap)。图书馆仅使用 40MB。所以 Java 加载的额外库不是原因。

有人对这种行为有解释吗?

编辑:感谢您迄今为止的回答。为了更清楚一点:java 代码除了调用本机库一次之外什么也不做! java 堆是标准大小(也许 60MB)并且不被使用(除了包含 main 方法的一个类和调用本机库的另一个类)。

本机库方法是一种长时间运行的方法,并且执行大量的 malloc 和 free 操作。碎片化也是我自己想到的一种解释。但由于没有活动的 Java 代码,因此 Java 程序和 C 程序的碎片行为应该相同。由于它是不同的,我还假设在 C 程序或 Java 程序中运行时使用的 malloc 实现是不同的。

I've written a library in C which consumes a lot of memory (millions of small blocks). I've written a c program which uses this library. And I've written a java program which uses the same library. The Java program is a very thin layer around the library. Basically there is only one native method which is called, does all the work and returns hours later. There is no further communication between Java and the native library using the java invocation interface. Nor there are Java object which consume a noteworthy amount of memory.

So the c program and the Java program are very similar. The whole computation/memmory allocation happens inside the native library. Still. When executed the c program consumes 3GB of memory. But the Java program consumes 4.3GB! (VIRT amount reported by top)

I checked the memory map of the Java process (using pmap). Only 40MB are used by libraries. So additional libraries loaded by Java are not the cause.

Does anyone have an explanation for this behavior?

EDIT: Thanks for the answers so far. To make it a little bit more clearer: The java code does nothing but invoke the native library ONCE! The java heap is standard size (perhaps 60MB) and is not used (except for the one class containing the main method and the other class invoking the native library).

The native library method is a long running one and does a lot of mallocs and frees. Fragmentation is one explanation I thought of myself too. But since there is no Java code active the fragmentation behavior should be the same for the Java program and the c program. Since it is different I also presume the used malloc implementations are different when run in c program or in Java program.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

甜味拾荒者 2024-08-26 06:26:12

只是猜测:在 JVM 内部运行时,您可能会使用非默认的 malloc 实现,该实现会根据 JVM 的特定需求进行调整,并且会产生比通用 malloc 更多的开销> 在你正常的 libc 实现中。

Just guessing: You might be using a non-default malloc implementation when running inside the JVM that's tune to the specfic needs of the JVM and produces more overhead than the general-purpose malloc in your normal libc implementation.

Spring初心 2024-08-26 06:26:12

对不起各位。错误的假设。

我已经习惯了 Sun Java 实现使用 64MB 作为默认最大堆大小。但我使用openjdk 1.6进行测试。如果未显式指定最大堆大小,Openjdk 将使用一小部分物理内存。就我而言,是四分之一。我用的是4GB的机器。因此四分之一是 1GB。这就是C和Java之间的区别。

遗憾的是这种行为没有任何记录。我在查看openjdk的源代码(arguments.cpp)时发现它:

// If the maximum heap size has not been set with -Xmx,
// then set it as fraction of the size of physical memory,
// respecting the maximum and minimum sizes of the heap.

Sorry guys. Wrong assumptions.

I got used to the 64MB the Sun Java implementations used to use for default maximum heap size. But I used openjdk 1.6 for testing. Openjdk uses a fraction of the physical memory if no maximum heap size was explicitly specified. In my case one fourth. I used a 4GB machine. One fourth is thus 1GB. There it is the difference between C and Java.

Sadly this behavior isn't documented anywhere. I found it looking at the source code of openjdk (arguments.cpp):

// If the maximum heap size has not been set with -Xmx,
// then set it as fraction of the size of physical memory,
// respecting the maximum and minimum sizes of the heap.
纵情客 2024-08-26 06:26:12

Java需要为其堆提供连续的内存,以便它可以分配最大内存大小作为虚拟内存。但是,这不会消耗物理内存,甚至可能不会消耗交换空间。我会检查一下你的常驻记忆增加了多少。

Java need to have continuous memory for its heap so it can allocate the maximum memory size as virtual memory. However, this doesn't consume physical memory and might not even consume swap. I would check how much your resident memory increases by.

〃安静 2024-08-26 06:26:12

您需要考虑不同的因素,尤其是像 Java 这样的语言,Java 在虚拟机上运行,​​垃圾收集由 Java 运行时处理,因为使用 Java 调用接口需要付出相当大的努力(我想)要在本机库中切换或执行本机方法,因为必须有一种方法来分配堆栈上的空间,切换到本机代码,执行本机方法,切换回 Java 虚拟机,也许以某种方式,分配堆栈上的空间堆栈没有被释放 - 这就是我倾向于认为的。

希望这有帮助,
此致,
汤姆.

There are different factors that you need to take into account especially on a language like Java, Java runs on a virtual machine and garbage collection is handled by the Java Runtime, as there is considerable effort (I would imagine) from using the Java Invocation Interface to switch or execute the native method within the native library as there would have to be a means to allocate space on the stack, switch to native code, execute the native method, switch back to the Java virtual machine and perhaps somehow, the space on the stack was not freed up - that's what I would be inclined to think.

Hope this helps,
Best regards,
Tom.

情感失落者 2024-08-26 06:26:12

很难说,但我认为问题的核心在于应用程序中有两个堆需要维护——用于 Java 对象分配的标准 Java 堆(由 JVM 维护)和 C 堆它是通过调用 malloc/free 来维护的。如果没有看到一些代码,很难准确地说出发生了什么。

It is hard to say, but I think at the heart of the problem is that there are two heaps in your application which need to be maintained -- the standard Java heap for Java object allocations (maintained by the JVM), and the C heap which is maintained by calls to malloc/free. It is hard to say what is going on exactly without seeing some code.

夜巴黎 2024-08-26 06:26:12

这是对抗它的建议。

让 C 代码停止使用标准 malloc 调用,并使用 malloc 的替代版本,通过 mmaping /dev/zero 来获取内存。您可以从库中修改 malloc 的实现,也可以自行开发(如果您觉得有足够的能力这样做)。

我强烈怀疑你会发现你的问题在你这样做之后就消失了。

Here is a suggestion for combating it.

Make the C code stop using the standard malloc call, and use an alternate version of malloc that grabs memory by mmaping /dev/zero. You can either modify an implementation of malloc from a library or roll your own if you feel competent enough to do that.

I strongly suspect you will discover that your problem goes away after you do that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文