为什么本机库在使用java时使用的内存量是Linux下的C-Programm使用量的1.5倍?

我用C编写了一个消耗大量内存(数百万个小块)的库。 我已经写了使用这个库的ac程序。 而且我写了一个使用相同库的java程序。 Java程序是库周围的一个非常薄的层。 基本上只有一种被称为的本地方法,做所有的工作,并在几小时后返回。 Java和使用java调用接口的本地库之间没有进一步的通信。 也没有消耗值得注意的内存的Java对象。

所以c程序和Java程序非常相似。 整个计算/内存分配发生在本地库内部。 仍然。 c程序执行时消耗3GB的内存。 但Java程序消耗4.3GB! (VIRT金额由上方报告)

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

有没有人有这种行为的解释?

编辑 :感谢迄今为止的答案。 为了使它更清晰一点:java代码除了调用本地库ONCE ! java堆是标准大小(可能是60MB),不能使用(除了包含main方法和调用本地库的其他类之外)。

本地库方法是一个长期运行的方法,并做了很多malloc和释放。 碎片是我自己也想到的一个解释。 但是由于没有Java代码活动,Java程序和c程序的碎片行为应该是相同的。 由于它不同,我还假定在c程序或Java程序中运行时使用的malloc实现是不同的。

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

对不起大家。 错误的假设。

我已经习惯了64MB的Sun Java实现用于默认最大堆大小。 但我使用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. 

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

有几个不同的因素需要考虑,特别是在像Java这样的语言中,Java在虚拟机上运行,​​垃圾回收由Java运行时处理,因为使用Java调用接口在本地库中切换或执行本地方法,因为必须有一种方式来分配栈上的空间,切换到本地代码,执行本地方法,切换回Java虚拟机,或者以某种方式,堆栈没有被释放 – 这就是我想要的。

希望这有助于,最好的问候,汤姆。

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

这是一个打击它的建议。

使用标准malloc调用停止C代码,并使用mmap ing /dev/zero抓取内存的替代版本的malloc。 你可以从库中修改一个malloc的实现,或者如果你觉得自己有足够的能力,就可以自己修改一下。

我强烈怀疑你会发现你的问题消失后,你这样做。