1

我正在尝试使用 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 库的方式。

我希望你能帮助我。谢谢

4

2 回答 2

3

不要使用 cygwin GCC,除非你真的想让你的程序链接到 cygwin 库。如果您需要它,您还必须将 cygwin dll 打包到您的包中。

如果您希望它在 Windows 上运行,请使用 mingw 编译器(Cygwin 也有包,但它会创建 cygwin 独立的二进制文件。)或 MSVC 项目。除非 Java 启用了 cygwin,否则它不会理解 cygwin 路径,但您的本机代码会。那会变得非常混乱。除非你知道你需要它,否则使用 cygwin 编写脚本,但使用 mingw-gcc 作为编译器来制作二进制文件或使用 Min Lin 的工作室项目。

于 2013-04-10T11:59:51.113 回答
1

我的猜测是您的 gsl 库可能已编译并链接到不同版本的 cygwin。而且你的main.c代码是用你当前版本的cygwin编译的,有冲突。你可以试试这些:

  1. 使用当前的 cygwin 环境重建您的 gsl。
  2. 链接到 gsl 的静态库。
  3. 使用msvc,gsl可以在msvc上编译,我有visual studio的解决方案,可以制作静态库或者动态库。
于 2013-04-10T09:51:14.503 回答