Pregunta

Estoy tratando de usar JNI y obtener java.lang.unsatisfiedlinkError. A diferencia de los otros millones de preguntas que se hacen sobre esto, tengo la lib en mi camino e incluso he visto el cambio de excepción cuando lo elimino. Estoy seguro de que algo está mal con la DLL que he creado, pero no estoy seguro de qué.

Aquí está mi código de clase Java:

package com;

public class Tune {
    static {
        System.loadLibrary("lala");
    }
    public static void main(String[] args) {
        Tune j = new Tune();
        System.out.println("2+6="+j.add(2, 6));
    }
    native public int add(int x,int y);
}

Aquí está la parte resumida de mi archivo de encabezado producido por Javah:

/*
 * Class:     com_Tune
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_Tune_add
  (JNIEnv *, jobject, jint, jint);

Aquí está mi código C ++:

#include <jni.h>
#include <com_Tune.h>

JNIEXPORT jint JNICALL Java_com_Tune_add
  (JNIEnv * env, jobject obj, jint x, jint y) {
    return x+y;
  }

Aquí está la excepción de tiempo de ejecución que obtengo de Eclipse:

Exception in thread "main" java.lang.UnsatisfiedLinkError: com.Tune.add(II)I
    at com.Tune.add(Native Method)
    at com.Tune.main(Tune.java:9)

Leí que la excepción anterior significa que encontró la biblioteca "lala", pero que el método "agregar" aún no está definido. Las únicas cosas que veo diferentes entre mi proyecto y el tutorial son:

  • El mío usa un paquete, en lugar del paquete predeterminado (¿no deberían los tutoriales realmente hacer esto?!?! Vamos, seamos profesionales)
    • El mío tiene un valor de devolución.
    • Moví mi DLL después de que se creó (no creo que esto lo rompa ya que mi ruta está configurada).

¿Cómo es esto posible?

Otra información:

OS: Windows 7
JDK: 1.6.0_31 (para x86, 32 bit jvm)
C ++ IDE: Code :: Blocks (el DLL fue compilado automáticamente por el código :: BLOCKS IDE)
Compilador C ++: Mingw32-G ++ (el compilador GNU C ++)

Tengo jni.h y com_tune.h en c: _ incluir
Tengo lala.dll en c: _ lib

Variables de entorno:
Ruta: c: archivos de programa (x86) nvidia Corporation Physx Common;%CommonProgramFiles% Microsoft Shared Windows Live; C: Archivos de programa (x86) AMD App bin x86_64; c: Archivos de programa (archivos de programa (archivos de programa (archivos ( x86) AMD App bin x86;%Systemroot% System32;%Systemroot%;%Systemroot% System32 Wbem;%Systemroot% System32 WindowsPowershell V1.0 ; C: Archivos de programa (x86) ATI Technologies ati.ace core-static; c: apps;%java_home% bin; c: programas de programa mysql mysql servidor 5.5 bin;%maven_home% bin;%hadoop_install% bin; c: c: Archivos de programa (x86) Microsoft SQL Server 100 Tools Binn ; C: Archivos de programa Microsoft SQL Server 100 Tools Binn ; C: Archivos de programa Microsoft SQL Server 100 DTS Binn ; C: mingw bin; c: archivos de programa (x86) gnuwin32 bin; c: _ path; c: _ lib; c: archivos de programa (x86) Microsoft Visual Studio 10.0 VC bin; c: _ incluir

¿Fue útil?

Solución

Solo adivinar ... ¿Tu DLL depende de otro DLL que no esté en el camino? Los módulos MINGW generalmente dependen de la biblioteca de tiempo de ejecución C específica.

Otros consejos

El problema es con el nombre del compilador que ha generado: Java_com_Tune_add@16

Usa cualquiera de los dos

gcc -Wl,-kill-at

O

gcc -Wl,--add-stdcall-alias

Esto garantizará la generación de Java_Com_Tune_Add

Y luego su llamada de método será exitosa.

Una posible fuente del problema podría ser que compiló el código utilizando un compilador C ++, que utiliza una [convención de llamadas] diferente a C. extern "C" bloque como este:

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jint JNICALL Java_com_Tune_add
...

#ifdef __cplusplus
}
#endif

Tuve el mismo problema y la bandera -wl, -kill-en funcionó para mí.

Intente con el siguiente ejemplo para Windows: (recuerde que el nombre de la clase Java debe ser el mismo que el nombre del archivo correspondiente)

Paso 1. Cree el siguiente archivo Java (P.Java):

class P
{
  static
  {
    // "P" is the name of DLL without ".dll"
    System.loadLibrary ("P");
  }

  public static native void f(int i);

  public static void main(String[] args)
  {
    f(1);
  }
}

Paso 2. Javac P.Java

Paso 3. Javah P

Luego, "Javah" genera el archivo de encabezado "ph"

Paso 4. Cree el archivo "P.Def", incluidas las siguientes dos líneas (este archivo define los símbolos exportados, en este caso el nombre de la función C):

EXPORTS
Java_P_f

Paso 5. Cree su archivo C (PC):

#include "P.h"

JNIEXPORT void JNICALL Java_P_f(JNIEnv *env, jclass c, jint i)
{
  printf("%i\n",i);
}

Paso 6. Dentro de Visual Studio Command Promt, defina las siguientes variables:

establecer java_home = la ruta de JDK

establecer incluir =%incluido%;%java_home% include;%java_home% include win32

Paso 7. Generar DLL:

CL /LD PC P.DEF

Paso 8. Ejecute el programa Java:

Java P

(Nota: P.DLL y P.Class se encuentran en el mismo directorio)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top