草庐IT

原生 C 和 Fortran 代码的 Java 内存泄漏

coder 2024-04-02 原文

我正在开发一个旧的 java 程序,其中包含一个带有 Fortran 调用的 native 库。

所以,我有 Java 通过 JNI 调用 C,然后调用 Fortran。

在生产中我们有一个内存不足的错误,比如:

Native memory allocation (malloc) failed to allocate 120000 bytes for jfloat in C:\BUILD_AREA\jdk6_37\hotspot\src\share\vm\prims\jni.cpp

我怀疑是内存泄漏。

我是公司的新人,我想在 Linux 上工作,但他们让我在 Windows 上工作:( 在生产环境下,我们使用 .so 文件,因为我们在 solaris 上,而我在 Windows 上使用 DLL(合乎逻辑。)

首先,我尝试重现生产问题。于是,我创建了一个单元测试,加载DLL,多次调用调用native方法的java类。 当我这样做时,我看到 processExplorer.exe 内存每 2 秒增长到 2MB。我在生产中有异常(exception)。

我很高兴我成功地重现了这个问题,我可以说这个问题来自 C 或 Fortran 代码。

接下来,我尝试删除对 Fortran 的调用,而我的 java 只调用了 C(没有 Fortran,此测试允许我查看问题是来自 C 还是 Fortran。)

结果就是内存不动了!凉爽的!我可以说我对 C 中的 malloc/free 没有任何问题。

所以,我决定学习一点 Fortran 语言来查看代码。 :)

我了解到在 Fortran 中我们可以使用 allocate 和 deallocate 关键字来使用内存。而我的代码不包含这些关键字。 :(

在这一切之后,有人允许我访问 Solaris 以启动调用 Java->JNI->C=>Fortran 的 junit 测试并使用 .so 而不是 DLL。

令人惊讶的是——内存没有移动!!!我在 Solaris 或 RedHat 下没有任何问题。

我被卡住了,因为生产中存在问题,但我无法清楚地重现它。 :(

为什么我看到 DLL 和 SO 之间的区别?代码 (java/C/Fortran) 完全相同,因为是我编译的。

我怎样才能调查更多?

我尝试在重现问题的 Windows 下进行内存转储,但我没有看到任何东西。

是jvm的问题吗?还是问题出在通过 JNI 传递给 C 的对象中?

非常感谢你帮我解决了这个问题。

信息:我使用的是 Windows 7 64 位

PS:我是法国人,所以请原谅我的英语。我每次都尽力而为。 ;)

这是 C 代码的标题:

    #ifndef unix 
       __MINGW_IMPORT void modlin_OM(float pmt[], float abaque[][], float don[][], float cond[], float res[][], int flag[]) ; 
    #else 
       extern void modlin_om_(float * pmt, float * abaque, float * don, float * cond, float * res, int * flag) ; 
    #endif

在方法之后:

   JNIEXPORT jint JNICALL Java_TrtModlin_modlin_1OM
     (JNIEnv * env, jobject obj, 
 jfloatArray pmtPar, 
 jobjectArray abaquePar, jobjectArray donPar, jfloatArray condPar, jobjectArray resPar,  jintArray flagPar)
   {

一些代码,以及 Fortran 的方法调用

   #ifndef unix
      modlin_OM(pmt, abaque, don, cond, res, & iFlag) ;
   #else
modlin_om_(pmt, abaque, don, cond, res, & iFlag) ;
   #endif

正如我之前所说,我通过删除这些行来测试对 C 的调用并且内存没有增长 :( 我通过删除带有 free(someVar) 的行进行测试并且内存增长,因为在这种情况下没有完成 free . 这就是为什么我得出结论,我的 C 可以使用 Free/Malloc。

最佳答案

分析一个内存问题总是很复杂。根据我的经验,有两种方法:

1) 你尝试重现。这假设您有源代码和根本原因的想法。 2) 您观察生产崩溃:频率、与其他事件的相关性等。

这可以帮助确定是否是内存泄漏(它可能是业务负载下的高消耗......)

在您的具体情况下,我注意到以下几点:

  1. 代码在不同操作系统上的行为可能不同。 Java 代码(JVM 错误)非常罕见。它经常出现在 native 代码中(例如,忘记关闭 ZIP 会在 Linux 上导致内存泄漏,但在 Windows 上不会...)

  2. 在您的 C 头文件 (*.h) 中:abaque、don 和 res 在 Windows 上是“float * *”,在 Unix 上是“float *”。这可能是您的 C header 中的错误,或者这意味着 C 实现不期望根据操作系统使用相同的参数类型(这对我来说很奇怪...)

在第二种情况下,您在 Windows(不是目标)上编译 C 头文件这一事实可以解释您没有生成正确的 JNI stub (典型的交叉编译问题)...从这里我们可以做出很多假设,简单或非常复杂...

祝你好运!

关于原生 C 和 Fortran 代码的 Java 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23059753/

有关原生 C 和 Fortran 代码的 Java 内存泄漏的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  3. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  4. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  5. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  6. ruby-on-rails - Ruby 中的内存模型 - 2

    ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序

  7. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  8. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  9. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  10. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

随机推荐