Java app通过JNI调用C++ DLL;如何最好地分配内存?

标签 java c++ memory dll java-native-interface

问题的基本摘要是: 如何最好地优化我的内存分配,为我通过 JNI 访问的 DLL 提供尽可能多的内存?我应该以最小化什么为目标,我应该以什么为最大目标,等等。

系统: 在具有 4 GB RAM 的 32 位系统中将 JBoss 6 作为 Windows 32 服务运行。我确实了解 Java Heap 的内存有最大限制。 JVM 是 JRE1.6.0_26

服务: JBoss 下安装了一个 webapp,它接收来自客户端的请求;每个请求都通过 JNI 调用 C++ 构建的 DLL 以某种方式处理图像文件。

问题: 有时,对于较大的或部分(不是全部)LZW 压缩图像,调用 java 类会收到一条消息,指出 DLL 经历了全局内存耗尽并且未能完成请求的进程。

除了基本的 Windows 进程之外,服务器上没有任何其他 Activity 在运行。

目前JBOSS App Server内存设置如下,但可能超标:

-Xms1024m -Xmx1024m -Xss1024k -XX:MaxPermSize=128m

我正在尝试确定最佳内存设置,以便为 JNI DLL 提供尽可能多的资源,据我所知,JNI 不使用分配给 Java 堆的任何内存。

我已阅读这些内容,但发现它们对回答我的问题没有帮助:

Java JNI : Memory allocation / partitioning

Can jconsole be used to identify memory leaks in JNI C++ objects?

目前提供的两个答案并未解决固有问题。

一周后JBoss服务器的当前内存,JVM参数设置如上(TaskManager指示java.exe进程为750,672k)

Total Memory Pools: 5

Pool: Code Cache (Non-heap memory)

    Peak Usage : init:2359296, used:7317312, committed:7438336, max:50331648
    Current Usage : init:2359296, used:7306496, committed:7438336, max:50331648


        |---------| committed:7.09Mb
        +---------------------------------------------------------------------+
        |/////////| | max:48Mb
        +---------------------------------------------------------------------+
        |---------| used:6.97Mb


Pool: PS Eden Space (Heap memory)

    Peak Usage : init:268500992, used:354811904, committed:354811904, max:355991552
    Current Usage : init:268500992, used:270153472, committed:354091008, max:354156544


        |--------------------------------------------------------------------| committed:337.69Mb
        +---------------------------------------------------------------------+
        |///////////////////////////////////////////////////// || max:337.75Mb
        +---------------------------------------------------------------------+
        |----------------------------------------------------| used:257.64Mb


Pool: PS Survivor Space (Heap memory)

    Peak Usage : init:44695552, used:44694896, committed:78643200, max:78643200
    Current Usage : init:44695552, used:0, committed:1835008, max:1835008


        |---------------------------------------------------------------------| committed:1.75Mb
        +---------------------------------------------------------------------+
        | | max:1.75Mb
        +---------------------------------------------------------------------+
        | used:0b


Pool: PS Old Gen (Heap memory)

    Peak Usage : init:715849728, used:123671968, committed:715849728, max:715849728
    Current Usage : init:715849728, used:104048648, committed:715849728, max:715849728


        |---------------------------------------------------------------------| committed:682.69Mb
        +---------------------------------------------------------------------+
        |////////// | max:682.69Mb
        +---------------------------------------------------------------------+
        |---------| used:99.23Mb


Pool: PS Perm Gen (Non-heap memory)

    Peak Usage : init:16777216, used:91989664, committed:134217728, max:134217728
    Current Usage : init:16777216, used:90956472, committed:90963968, max:134217728


        |----------------------------------------------| committed:86.75Mb
        +---------------------------------------------------------------------+
        |//////////////////////////////////////////////| | max:128Mb
        +---------------------------------------------------------------------+
        |----------------------------------------------| used:86.74Mb

最佳答案

由 JNI 封装的 native 代码分配的内存分配给 JVM 进程,但不受您的 Java 代码控制。它不是堆的一部分,也不能通过 JVM 参数进行调整。基本上,使用 native malloc 分配的任何内容都必须由该 native 代码管理。如果您可以控制正在使用的库,则必须仔细检查并检查资源泄漏。如果将其用于长期存在的过程中,这一点尤其重要。

根据我的经验,最好的方法是通过提取 JVM 公开的 JMX 统计信息来检查您的实际内存使用情况。一旦你知道你的 Java 应用程序消耗了多少内存,你就会更好地了解在哪里设置你的最大堆设置。 Permgen 空间用于类定义等,因此除非您正在执行大量动态类加载,否则您确实不需要太多内存。

虽然您无法调整 JNI 库的可用内存,但调整为堆保留的内存等可能会释放资源供库使用。

正如所料,将堆内存峰值加在一起大约为 1022.19(堆的最大大小)。当堆耗尽时,将启动完整的 GC 运行并回收脏堆。根据您提供的数字,我建议从 Xmx512m 开始。这将为您的 JNI 代码提供喘息的空间。

如果您发现 JVM 由于过多的垃圾收集而崩溃,这意味着您很快就用完了 Java 堆,您可以增加该分配。但是,如果它以足够快的速度消耗 512mb 以引起明显的性能影响,那么任何没有显着增加的东西都不太可能产生很大的影响。这在很大程度上取决于您的程序、它消耗 Java 堆的速度以及完整 GC 运行的效率。

关于Java app通过JNI调用C++ DLL;如何最好地分配内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7700446/

相关文章:

java - 无法通过 selenium 中的 htmlunit 驱动程序运行脚本

c++ - g++ 中是否存在这样的优化?

c++ - val1,val2,val3,val4的值如何计算?

c - 保护分配的内存

c++ - 限制每个进程的物理内存

c++类实例内存布局再一次

java - 如何使用tomcat使用eclipse webtool创建adempiere自定义模板的web ui工作区

java - 如何修复客户端代码以便通过组合实现代码重用?

进行双调排序时出现 java.lang.NoClassDefFoundError

c++ - 想要将结构数组从 perl 脚本传递到 cpp 文件