2014-04-14 21 views
5

我正在使用一个包含带有Fortran调用的本机库的旧Java程序。使用本机代码的java内存泄漏

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

在生产中,我们有一个出像存储器错误的:

本机的存储器分配(malloc的)未能分配用于jfloat 120000个字节在C:\ BUILD_AREA \ jdk6_37 \热点\ SRC \共享\ VM \ prims \ jni.cpp

我怀疑这是内存泄漏。

我是新来的公司,我想在linux上工作,但他们让我在Windows上工作:( 正在生产中我们使用.so文件,因为我们在solaris上,而我在Windows上使用DLL (逻辑)

首先,我尝试重现生产问题,于是我创建了一个加载DLL的单元测试,并调用多次调用本地方法的java类 当我这样做时,我看到用processExplorer.exe表示内存每2秒增长到2MB,而且我有例外,就像在制作中那样。

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

接下来,我试图删除调用Fortran和我的Java只叫C(无Fortran语言,这个测试允许我看看问题是否是从C或Fortran的到来。)

,结果是记忆没有动!凉!我可以说我在C中没有任何malloc/free的问题。

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

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

这一切后,有人给我在Solaris上获得启动我的JUnit测试调用Java的> JNI-> C => Fortran和使用。所以,而不是DLL的。

和惊喜 - 内存没有移动!!!我在Solaris或RedHat下没有任何问题

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

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

我该如何调查更多?

我试图做一个内存转储下的窗口,我重现了这个问题,但我什么也没看到。

在jvm中是否存在问题?或者问题可以在通过JNI传递给C的对象中?

非常感谢您帮助我解决这个问题。

信息:我使用Windows 7 64位

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

这里是报头F的C代码:

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 

#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 

,并且该方法后

正如我之前所说,我通过删除这些行来测试对C的调用,并且t他的记忆力没有增长:(我测试通过删除一行免费(someVar)和内存增长,因为免费在这种情况下没有完成。这就是为什么我得出结论说我的C和Free/Malloc一致。

+1

你是否有这两种平台(Unix和Windows)的C绑定的来源? – fge

+0

是的,我有源,但它是相同的Windows或UNIX,我在我的问题结束时添加它(如果你想所有的来源,我可以给你,如果你想) –

+0

哪个fortran编译器?我们使用的是 – Peter

回答

1

分析内存故障总是很复杂。根据我的经验有两种方法:

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

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

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

  1. 的代码的行为可以在不同的操作系统不同。 Java代码(JVM bug)非常少见。在本地代码中经常出现这种情况(例如,忘记关闭ZIP会导致Linux上的内存泄露,但不会在Windows上)...

  2. 在您的C头(* .h)中:abaque,don和res是在Windows上'float * *'和在Unix上'float *'。这可能是一个错误在你的C头文件,或者这意味着C实现不希望依赖于操作系统相同的参数类型(即怪我...)

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

祝你好运!