我正在尝试使用JNI来调用c中定义的函数。这真的很奇怪,因为当我运行我的java程序时,有时会遇到一个错误,而其他时候会遇到另一个错误。他们来了:

     82 [main] java (5556) C:\Windows\system32\java.exe: *** fatal error - cygheap base mismatch detected - 0x612708F0/0x17FF08F0.
This problem is probably due to using incompatible versions of the cygwin DLL.
Search for cygwin1.dll using the Windows Start->Find/Search facility
and delete all but the most recent version.  The most recent version *should*
reside in x:\cygwin\bin, where 'x' is the drive on which you have
installed the cygwin distribution.  Rebooting is also suggested if you
are unable to find another cygwin DLL.
java.lang.UnsatisfiedLinkError: C:\cygwin\home\Juli▒n\Pruebas_JNI\Caracterizacion.dll: Se realiz▒ un acceso no v▒lido a la ubicaci▒n de memoria
        at java.lang.ClassLoader$NativeLibrary.load(Native Method)
        at java.lang.ClassLoader.loadLibrary1(Unknown Source)
        at java.lang.ClassLoader.loadLibrary0(Unknown Source)
        at java.lang.ClassLoader.loadLibrary(Unknown Source)
        at java.lang.Runtime.loadLibrary0(Unknown Source)
        at java.lang.System.loadLibrary(Unknown Source)
        at Main.<clinit>(Main.java:6)
Exception in thread "main"


Exception in thread "main" java.lang.UnsatisfiedLinkError: Main.caracterizar()[F
        at Main.caracterizar(Native Method)
        at Main.main(Main.java:10)

我认为我做对了所有事情,甚至认为似乎我做得还没有。

这是我的C函数
/*
 * File:   main.c
 * Author: OCARDONAM
 * Created on 14 de enero de 2013, 11:46 AM
 */
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <jni.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_statistics.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_linalg.h>
#include "sizedata.h"
#include "elementary_math_vec.h"
#include "contar.h"
#include "media.h"
#include "Main.h"


JNIEXPORT jfloatArray JNICALL Java_Main_caracterizar (JNIEnv *env, jclass class) {
    //variables
    int n_fil, n1, n2, i;
    char *filename;
    //features names
    double m,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11;//,F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11;
    //load signal and define its size
    filename = "reg_test.txt";
    tamano(filename, &n1, &n2);
    n_fil = n1-2;

    gsl_vector * v = gsl_vector_alloc (n_fil);
    {
        FILE * f = fopen (filename, "r");
        gsl_vector_fscanf (f, v);
        fclose (f);
    }


    // statistics features in time domain
    double data[n_fil],tmp[n_fil];
    for (i = 0; i < n_fil; i++)
    {
        data[i] = gsl_vector_get(v,i);
    }

    //centered data
    m = gsl_stats_mean(data, 1, n_fil);
    for (i = 0; i < n_fil; i++) {
        data[i] = data[i]-m;
        gsl_vector_set(v,i,data[i]);
    }
    T1 = gsl_stats_mean(data, 1, n_fil);  //mean
    T2 = gsl_stats_sd_m(data, 1, n_fil, T1); //standard deviation
    T3 = gsl_blas_dnrm2(v)/sqrt(n_fil);//RMS
    T4 = gsl_stats_skew(data, 1, n_fil); //skewness
    T5 = gsl_stats_kurtosis(data, 1, n_fil) + 3; //kurtosis
    T6 = ch_T6(data,n_fil);
    T7 = ch_T7(data,n_fil); //absolute maximum
    T8 = T7/T3; //Crest Factor
    T9 = T7/T6;
    T10 = ch_T10(data,n_fil,T3);//Shape Factor
    T11 = ch_T11(data,n_fil,T7);


    //print a vector

    jfloat res[1000];
    jfloatArray jres;

    for (i = 0; i < n1-2; i++) {
        res[i] = (jfloat) gsl_vector_get(v, i);
    }
    gsl_vector_free (v);

    (*env)->SetFloatArrayRegion(env, jres, 0, n1-2, res);
    return jres;
}

这是我用来调用它的Java代码:
public class Main {

    public native float[] caracterizar();

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

    public static void main(String args[]) {
        float ans[] = (new Main()).caracterizar();

        for (int i=0 ; i<ans.length ; i++)
            System.out.println(ans[i]);
    }
}

另外,这是我用来编译和链接c程序的内容:
gcc -D__int64="long long" -c -I/cygdrive/c/Program\ Files/Java/jdk1.7.0_11/include/ -I/cygdrive/c/Program\ Files/Java/jdk1.7.0_11/include/win32/ -o Main.o Main.c

链接:
gcc -shared -L/usr/local/lib -o Caracterizacion.dll Main.o -lgsl -lgslcblas -lm

我不确定错误在哪里。我已经测试了其他JNI程序,并且它们运行良好,所以我认为问题在于我包含gsl库的方式。

我希望你能帮助我。谢谢

最佳答案

除非您确实希望将程序链接到cygwin库,否则请勿使用cygwin GCC。如果需要,还必须将cygwin dll打包到您的软件包中。

如果您希望它在Windows上运行,请使用mingw编译器(也有Cygwin软件包,但它将创建cygwin独立的二进制文件。)或MSVC项目。除非Java启用了cygwin,否则它将无法理解cygwin路径,但是您的本机代码可以。这将变得非常困惑。除非您知道自己需要它,否则请使用cygwin进行脚本编写,但使用mingw-gcc作为编译器来制作二进制文件或使用Min Lin的studio项目。

07-24 19:20
查看更多