2014-04-14 20 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存根(典型的交叉編譯問題)......從這裏我們可以做出很多簡單或非常複雜的假設。

祝你好運!