使用jni CALL在本机代码中进行Segfault

时间:2014-04-25 07:28:29

标签: java multithreading java-native-interface thread-safety native

我的本​​机C代码中存在段错误。

我的程序中有一个包含4thread的线程池,每个都执行一个新的MyObject() 在MyObject中我有

   public class MyObject{

        private final float[] pmt = new float[50];
private final float[] cond = new float[10];
private final float[][] don = new float[3][200000];
private final float[][] abaque = new float[2][100];
private final double[][] res = new double[3][200000];

    private native int trade_OM(float[] pmt, float[][] abaque, float[][] don, float[] cond, double[][] res, int[] flag);

     protected void callNative() {
       trade_OM(pmt, abaque, don, cond, res, flag);
     }

     static {
  System.loadLibrary("myDLL");
     }
    }

当一个线程空闲时,如果另一个任务到达,则该线程再次执行一个新的MyObject()并调用本机方法。

在新的MyObject()调用6或7后,我有一个段错误。

**在solaris上我使用truss **:

 /16:    lwp_sigmask(SIG_SETMASK, 0xFFBFFEFF, 0x0000FFF7) = 0xFFBFFEFF [0x0000FFFF]
 /15:    time()                                          = 1398686601
 /17:    llseek(11, 0, SEEK_CUR)                         = 5887547
 /15:    open("Trade.log", O_RDWR|O_APPEND|O_CREAT, 0666) = 8
 /17:    llseek(11, 0, SEEK_CUR)                         = 5887547
 /15:    fstat64(8, 0xACFFD5B0)                          = 0
 /17:    close(11)                                       = 0
 /15:    fstat64(8, 0xACFFD458)                          = 0
 /17:    time()                                          = 1398686601
 /15:    ioctl(8, TCGETA, 0xACFFD53C)                    Err#25 ENOTTY
 /18:        Incurred fault #6, FLTBOUNDS  %pc = 0xFE27E498
 /18:          siginfo: SIGSEGV SEGV_MAPERR addr=0x8682F278
 /15:    write(8, " 1 3 : 0 3 : 2 1   -   1".., 43)      = 43
 /18:        Received signal #11, SIGSEGV [caught]
 /18:          siginfo: SIGSEGV SEGV_MAPERR addr=0x8682F278
 /15:    lseek(8, 0, SEEK_END)                           = 5887590
 /17:    open("Trade.log", O_RDWR|O_APPEND|O_CREAT, 0666) = 9
 /15:    llseek(8, 0, SEEK_CUR)                          = 5887590
 /17:    fstat64(9, 0xAB7FD4B0)                          = 0
 /15:    llseek(8, 0, SEEK_CUR)                          = 5887590

我需要同步C代码吗?或用C做线程?

我尝试使用(* env) - > MonitorEnter和(* env) - > MonitorExit但同样的问题。

如果我只使用一个线程启动相同的程序,我没有问题,没有内存泄漏。

这是C代码:

 #include <stdio.h>
 #include <stdlib.h>
 #include "CTrade.h" 
 #include "../trace.h" 
 #include "../commun.h" 


  JNIEXPORT jint JNICALL      Java_fr_edf_mpv2_serveurcalcul_castor_transverse_traitement_transformation_courbe_TrtNRC_trade_1OM
  (JNIEnv *env, jobject obj, jfloatArray pmtPar, jobjectArray abqPar, jobjectArray donPar, jfloatArray    condPar, jobjectArray resPar, jintArray flagPar)
{
        float ** don0 = NULL ; // Pour pouvoir desallouer les elements Java
        float ** abq0 = NULL ; // Pour pouvoir desallouer les elements Java
 int err = 0 ;
 jfloat *pmt;// [SIZE_PMT] ; //parametres
 jfloat * abq ;//[SIZE_ABQ_2][SIZE_ABQ_1] ;  // abaques
 jfloat *cond;//[SIZE_COND] ; //Conditions
 jfloat * don ;//[SIZE_DON_2][SIZE_DON_1] ;  // Donnees
 jfloat * res ;//[SIZE_RES_2][SIZE_RES_1] ;  // Resultats
 int *flag ; //[SIZE_FLAG]  ;            // Retour Erreur
 int iFlag=0 ;
 SetLogFileName("Trade.log") ;
 ZTrace(" On est dans Trade.c");
 //
 // Init parametre : pmt
 //


 if((err = GetTableauFloat("pmt", env, pmtPar, & pmt))== 0)
 {
     //
     // Init parametre : abq
     //
     if((err = GetMatriceFloat("abq", env, abqPar,  & abq0, & abq)) == 0)
     {
         //
         // Init parametre : cond
         //
         if((err = GetTableauFloat("cond", env, condPar, & cond)) == 0)
         {
             //
             // Init parametre : don
             //
             if((err = GetMatriceFloat("don", env, donPar, & don0, & don)) == 0)
             {
                 //
                 // Allocation du tableau resultat
                 //
                 ZTrace("Allocation res") ;
                 if((err = AllocationMatriceFloat("res", env, resPar, & res)) == 0)
                 {
                     //
                     // Allocation du tableau flag
                     //
                     if((err = AllocationTableauInt("flag", env, flagPar, & flag)) == 0)
                     {
                        //here i have a Fortran Call that i remove because problem exist without this call          
                         if((err = TransfertTableauInt("flag", env, flagPar, flag)) == 0)
                         {
                                                                                               if((err = TransfertMatriceFloat("res", env, resPar, res)) == 0)
                             {
                             }
                         }
                         ZTrace("Libere Flag") ;
                         free(flag) ;
                     }
                     ZTrace("Libere res") ;
                     free(res) ;
                 }
                 ZTrace("Libere don");
                 free(don) ;
                 if(don0)
                     FreeMatriceFloat(env, donPar, don0) ;
             }
             (*env)->ReleaseFloatArrayElements(env, condPar, cond, JNI_ABORT) ;
         }
         ZTrace("Libere abq");
         free(abq);
         if(abq0)
             FreeMatriceFloat(env, abqPar, abq0) ;
     }
    (*env)->ReleaseFloatArrayElements(env, pmtPar, pmt, JNI_ABORT) ;
 }


return err;
 }

Trace.c仅用于创建文件的封装方法并在其中写入

commun.c包含分配数组的方法

 int GetMatriceFloat(LPCSTR nomTab, JNIEnv *env, jobjectArray donPar, float * ** don, float ** donFor)
 {
int ind, jnd, sizeDon, sizeDon1 ;

 sizeDon = (*env)->GetArrayLength(env, donPar);
 ZTrace("Size %s = %d", nomTab, sizeDon) ;
 if((* don = (jfloat **)calloc(sizeDon, sizeof(jfloat *))))
 {
     //
     // Init matrice don
     //
     for(ind = 0 ; ind < sizeDon ; ind ++)
     {
         jfloatArray donPari = (jfloatArray) (*env)->GetObjectArrayElement(env, donPar, ind);
         sizeDon1 = (*env)->GetArrayLength(env, donPari);
         ZTrace("Size1 %s = %d", nomTab, sizeDon1) ;
         (* don)[ind] = (jfloat *) (*env)->GetFloatArrayElements(env, donPari, NULL);
         if((* don)[ind] == NULL)
         {
             ZTrace("Erreur -23") ;
             return -23;/* exception occurred */
         }
     }

     if((* donFor = calloc(sizeDon1 * sizeDon, sizeof(float))) == NULL)
     {
         ZTrace("Erreur -22") ;
         return -22 ;
     }
     for(ind = 0 ; ind < sizeDon ; ind ++)
     {
         for(jnd = 0 ; jnd < sizeDon1 ; jnd ++)
         {
             * (* donFor + jnd * sizeDon + ind) = (* don)[ind][jnd] ;
             if((* don)[ind][jnd] != 0.0)
                 ZTrace("%s[%d][%d] = %g", nomTab, jnd, ind, (* don)[ind][jnd]) ;
         }
     }
     //free(don) ;
     return 0 ;
 }
 else
 {
    ZTrace("Erreur -24") ;
  return -24 ;
 }
 }

 int FreeMatriceFloat(JNIEnv *env, jobjectArray donPar, float ** don)
 {
 int ind, sizeDon ;
 sizeDon = (*env)->GetArrayLength(env, donPar);
 for(ind = 0 ; ind < sizeDon ; ind ++)
 {
     jfloatArray donPari = (jfloatArray) (*env)->GetObjectArrayElement(env, donPar, ind);
     (*env)->ReleaseFloatArrayElements(env, donPari, don[ind], JNI_ABORT);

 }
 free(don) ;
 }

如果你在getmatricefloat或其他东西的调用中看到某些内容让我知道;)如果不是我可以发布其他函数TransfertMatriceFloat / AllocationMatriceFloat / TransfertMatriceInt等...以查看问题是否在其中

感谢提前

1 个答案:

答案 0 :(得分:0)

调用任何非线程安全的代码都有可能导致无法预料的问题 您的症状和旁路修复大声尖叫您的本机代码不是 线程安全的。

在你的情况下,因为你肯定知道100ms延迟阻止了 操作系统看到分段违规,至少应该

remove the delay 

并更改

private native int myMethod(float[][] test, float[] tutu);

synchronized private native int myMethod(float[][] test, float[] tutu);

防止并发执行您的本机代码。