java - JNI% 1 no es una aplicación Win32 válida
dll 64bit (1)
Finalmente lo descubrí.
En primer lugar, algo estaba mal con Cygwin64. El uso de un compilador de C de 64 bits diferente eliminó el error no válido de la aplicación win32.
En segundo lugar, la firma del método de mi archivo JNITest.c era incorrecta. Debería haber sido:
Java_jnitest_JNITest_doHello
En lugar de
Java_jnitest_Main_doHello
¡Después de cambiar eso, funciona!
Estoy ejecutando Netbeans en Windows 8 de 64 bits, con JDK 1.7_25 (64 bits), siguiendo las instrucciones para el Beginning JNI con NetBeans ( https://netbeans.org/kb/docs/cnd/beginning-jni- linux.html )
Las instrucciones son para Linux, pero el principio es el mismo para Windows, creo (generando un archivo .dll en lugar de .so, usando Win32 incluido en el JDK, etc.)
Tengo instalado Cygwin64 y Cygwin32. Utilizando Cygwin64, puedo generar una DLL de 64 bits desde mi proyecto C / C ++ Dynamic Library. Sin embargo, cuando llamo a System.load ("ruta / a / JNITest.dll"), obtengo:
Exception in thread "main" java.lang.UnsatisfiedLinkError: C:/Users/Andrew/Documents/NetBeansProjects/JNITestLib/dist/JNITest.dll: %1 is not a valid Win32 application
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary1(ClassLoader.java:1957)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1882)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1843)
at java.lang.Runtime.load0(Runtime.java:795)
at java.lang.System.load(System.java:1061)
at jnitest.JNITest.main(JNITest.java:8)
Java Result: 1
Por lo que sé, este suele ser el caso cuando se carga una aplicación de 64 bits en una máquina virtual de 32 bits, pero mi netbeans.conf apunta a una JVM de 64 bits.
Además, cuando uso la versión de 32 bits de Cygwin para compilar y ejecutar, obtengo
Can''t load IA 32-bit .dll on a AMD 64-bit platform
Estoy bastante seguro de que estoy generando correctamente el archivo DLL, solo es una simple impresión de HelloWorld para seguir el tutorial de JNI. Soy muy nuevo en JNI y C, por lo que no estoy seguro de dónde comenzar la depuración. Lo mejor que he hecho es probar los archivos DLL de 32 y 64 bits, y me he asegurado de que mi compilador de C (Cygwin) sea de 64 bits y mi JVM también.
¡Agradecería cualquier idea!
Editar: Aquí están los archivos incluidos
=== Java (JNITest.java) ===
package jnitest;
public class JNITest {
public static void main(String[] args) {
System.out.println("JVM: " + System.getProperty("sun.arch.data.model"));
System.load("C://Users//Andrew//Documents//NetBeansProjects//JNITestLib//dist//JNITest.dll");
new JNITest().doHello();
}
public native void doHello();
}
=== Cabecera javah generada (jnitest_JNITest.h) ===
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class jnitest_JNITest */
#ifndef _Included_jnitest_JNITest
#define _Included_jnitest_JNITest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: jnitest_JNITest
* Method: doHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_jnitest_JNITest_doHello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
=== C (JNITest.c) ===
#include <jni.h>
#include "jnitest_JNITest.h"
JNIEXPORT void JNICALL Java_jnidemojava_Main_nativePrint
(JNIEnv *env, jobject obj)
{
printf("/nHello World from C/n");
}
Editar:
El problema parece ser con la DLL, ya que puedo cargar otras DLL de 64 bits sin problemas. Pensé que Cygwin podría ser el problema, así que cambié mi compilador a MinGW-w64. Recopiló bien, y la biblioteca carga, pero ahora recibo una nueva excepción:
Exception in thread "main" java.lang.UnsatisfiedLinkError: jnitest.JNITest.doHello()V
at jnitest.JNITest.doHello(Native Method)
at jnitest.JNITest.main(JNITest.java:10)
Java Result: 1
Un poco más de excavación encontró que el error se produce cuando ClassLoader lee libs.size () aquí:
// Invoked in the VM class linking code.
static long findNative(ClassLoader loader, String name) {
Vector<NativeLibrary> libs =
loader != null ? loader.nativeLibraries : systemNativeLibraries;
synchronized (libs) {
int size = libs.size();
for (int i = 0; i < size; i++) {
NativeLibrary lib = libs.elementAt(i);
long entry = lib.find(name);
if (entry != 0)
return entry;
}
}
return 0;
}
Editar: ¡RESPUESTAS!
Finalmente lo descubrí.
En primer lugar, algo estaba mal con Cygwin64. El uso de un compilador de C de 64 bits diferente eliminó el error no válido de la aplicación win32.
En segundo lugar, la firma del método de mi archivo JNITest.c era incorrecta. Debería haber sido:
Java_jnitest_JNITest_doHello
En lugar de
Java_jnitest_Main_doHello
¡Después de cambiar eso, funciona!
(aunque no puedo responder mi propia pregunta por otras 6 horas ... así que dum de dum)