Sto lavorando su un vecchio programma java che include una libreria nativa con chiamate Fortran.perdita di memoria java con codice nativo
Quindi, ho Java che chiama C tramite JNI, quindi chiama Fortran.
In produzione ci sono un errore di memoria come:
allocazione di memoria Native (malloc) non è riuscito a destinare 120000 byte per jfloat in C: \ BUILD_AREA \ jdk6_37 hotspot \ src \ share \ \ vm \ prim \ jni.cpp
Sospetto che si tratti di una perdita di memoria.
Sono nuovo in azienda, e mi piacerebbe lavorare su linux ma mi fanno lavorare su Windows :( In produzione stiamo usando il file .so perché siamo su solaris, e io uso DLL su Windows (logico.)
In primo luogo, ho provato a riprodurre il problema di produzione, quindi ho creato un test unitario che carica la DLL e chiama la classe java che chiama il metodo nativo molte volte Quando l'ho fatto, ho visto con processExplorer.exe che la memoria è cresciuta fino a 2 MB ogni 2 secondi e ho un'eccezione come nella produzione
Sono felice di aver riprodotto correttamente il problema, e ho potuto dire che il problema è venuto dal codice C o Fortran.
Successivamente, ho cercato di rimuovere la chiamata a Fortran, e la mia Java solo chiamato C (senza Fortran, questo test mi ha permesso di vedere se il problema veniva dalla C o Fortran.)
E il risultato è stato che la memoria non si è mossa! Freddo! Potrei dire che non ho avuto alcun problema con malloc/free in C.
Così, ho deciso di imparare un po 'di Fortran a guardare attraverso il codice. :)
Ho imparato che in Fortran possiamo usare le parole chiave allocate e deallocate per giocare con la memoria. E il mio codice non contiene queste parole chiave. :(
Dopo tutto questo, qualcuno mi dia l'accesso su Solaris per lanciare il mio test JUnit che chiama Java-> JNI-> C => Fortran e di utilizzare la .so invece di DLL.
E sorpresa - la memoria non si mosse !!! non ho alcun problema sotto Solaris o RedHat
sono bloccato perché il problema esiste sulla produzione, ma non riesco a riprodurre chiaramente :(
..Perché vedo una differenza tra DLL e SO? Il codice (java/C/Fortran) è esattamente lo stesso perché sono io a compilarlo.
Come posso indagare di più?
Ho provato a fare un dump della memoria in Windows in cui ho riprodotto il problema, ma non vedo nulla.
Il problema è nella jvm? Oppure il problema può essere nell'oggetto passato a C tramite JNI?
Grazie mille per avermi aiutato con questo problema.
Info: Sto utilizzando Windows 7 64bit
PS: Sono francese, quindi scusate il mio inglese. Cerco di fare del mio meglio ogni volta. ;)
Ecco l'intestazione f codice 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
e dopo il metodo:
JNIEXPORT jint JNICALL Java_TrtModlin_modlin_1OM
(JNIEnv * env, jobject obj,
jfloatArray pmtPar,
jobjectArray abaquePar, jobjectArray donPar, jfloatArray condPar, jobjectArray resPar, jintArray flagPar)
{
codice, e la chiamata al metodo per FORTRAN
#ifndef unix
modlin_OM(pmt, abaque, don, cond, res, & iFlag) ;
#else
modlin_om_(pmt, abaque, don, cond, res, & iFlag) ;
#endif
Come ho detto prima, provo la chiamata a C rimuovendo queste righe e t La memoria non è cresciuta :(Eseguo un test rimuovendo una riga con free (someVar) e la memoria cresce perché free non è fatto in questo caso. Ecco perché concludo che il mio C era ok con Free/Malloc.
E avete la fonte di questi collegamenti C per entrambe le piattaforme (Unix e Windows)? – fge
sì ho il sorgente ma è lo stesso per Windows o Unix, lo aggiungo alla fine della mia domanda (se vuoi tutto il sorgente, posso darti se vuoi) –
quale compilatore fortran? – Peter