2008-10-01 13 views
10

Escribo un código JNI en C++ para llamar desde un applet en Windows XP. Pude ejecutar con éxito el applet y cargar y ejecutar la biblioteca JNI, llegando incluso a llamar funciones en otros archivos DLL. Esto funcionó configurando la variable de entorno del sistema PATH para incluir el directorio en el que están todas mis DLL.UnsatisfiedLinkError: no se pudo encontrar el procedimiento especificado

Entonces, el problema es que agrego otra llamada que usa una nueva DLL externa y de repente cuando cargo el biblioteca, se genera un UnsatisfiedLinkError. El mensaje es: 'No se pudo encontrar el procedimiento especificado'. Esto no parece ser un problema con una DLL dependiente faltante, porque puedo eliminar una DLL dependiente y obtener un mensaje diferente sobre DLL dependiente faltante. De lo que he podido encontrar en línea, parece que este mensaje significa que falta una implementación nativa de la función Java de la DLL, pero es extraño que funcione bien sin este bit de código adicional.

¿Alguien sabe lo que podría estar causando esto? ¿Qué tipos de cosas pueden dar un mensaje 'No se pudo encontrar el procedimiento especificado' para un UnsatisifedLinkError?

Respuesta

14

Descubrí el problema. Esto fue una tontería. El mensaje "No se pudo encontrar el procedimiento especificado" para InsatisfiedLinkError indica que no se pudo encontrar una función en el dll raíz o en dll dependiente. La causa más probable de esto en una situación JNI es que la función JNI nativa no se exporta correctamente. Pero esto aparentemente puede ocurrir si se carga una DLL dependiente y esa DLL pierde una función requerida por su principal.

A modo de ejemplo, tenemos una biblioteca llamada input.dll. El orden de búsqueda de DLL es buscar siempre primero en el directorio de la aplicación y en los directorios de PATH. En el pasado, siempre ejecutamos ejecutables desde el mismo directorio que input.dll. Sin embargo, hay otro input.dll en el directorio del sistema de Windows (que está en el medio del orden de búsqueda de DLL). Por lo tanto, al ejecutar esto desde un applet de Java, si incluyo el código descrito anteriormente en el applet, que hace que se cargue input.dll, carga el archivo input.dll desde el directorio del sistema. Debido a que nuestro código está esperando ciertas funciones en input.dll que no están allí (porque es una DLL diferente) la carga falla con un mensaje de error sobre procedimientos faltantes. No porque las funciones JNI se exporten incorrectamente, sino porque se cargó el DLL dependiente incorrecto y no tenía las funciones esperadas en él.

+0

Tuve este problema. libA extrajo libBv2 y libC. Se encontraron tanto libBv2 como libC. El problema era que libC dependía de una versión diferente, libBv1. libBv1 y libBv2 no funcionaron juntos. El cazador de dependencias mostró las bibliotecas, pero no amplié las dependencias de libC. Usé procmon (http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx) para ver las bibliotecas cargadas y fue cuando noté que se cargaba la segunda versión de libB. – codeDr

0

Por lo general, al vincular a otras bibliotecas, debe vincular al archivo .lib correspondiente. Parece que no hace referencia a todos los archivos lib que necesita. Compruebe lo que no está vinculando y asegúrese de agregar su lib a la lista del vinculador.

2

Existe la posibilidad de que la DLL se haya creado utilizando C++ (en lugar de C). a menos que haya tenido cuidado de hacer un extern en el procedimiento, esta es una posible razón.

Intente exportar todas las funciones de la DLL. Si la lista incluye tu función, entonces estás bien.

+0

Abrí la DLL en un explorador PE y comprobé dos veces que las funciones JNI se exportan utilizando el enlace C. También comprobé dos veces, y las firmas de las funciones de JNI tienen el mismo aspecto en el caso en que la DLL se carga sin error y en el caso de que falle. – matt

0

¿Creó la nueva DLL externa usando el procedimiento JNI estándar? Es decir, ¿usando javah y demás? Si es así, entonces no estoy seguro de lo que está mal.

De lo contrario, el procedimiento al que está intentando llamar no se ha exportado (como se menciona en anjanb). Conozco dos formas de exportar funciones: una lista de exportación separada y marcar funciones específicas con __declspec (dllexport).

Can't access variable in C++ DLL from a C app tiene un poco más de información sobre el tema de las DLL.

+0

Estoy usando el procedimiento JNI estándar. Como dije, lo tengo funcionando en algunos casos. Pero cuando agrego este código adicional, de repente deja de funcionar con el error dado. Como se ha señalado, el error indica que la función no se exporta, pero estoy seguro de que las funciones se exportan. – matt

0

Compila tu código de C++ en modo de depuración. Luego inserte el DebugBreak(); declaración donde le gustaría comenzar la depuración. Ejecuta el código java.Cuando se encuentre la instrucción DebugBreak(), aparecerá una ventana emergente con un botón de depuración. Haz click en eso. Dev Studio se abrirá con su programa en código máquina. Haga un doble paso con el depurador dos veces y podrá pasar por encima de su código fuente.

0

Si ha realizado todos los problemas de programación en los manuales y ejemplos de JNI, pero todavía está obteniendo el mismo error de procedimiento faltante, el problema puede ser probablemente en la variable de su ruta de acceso. Hacer los pasos siguientes y ejecute de nuevo:

  1. estar seguro acerca de establecer la variable JAVA_HOME a la carpeta de JDK (no JRE porque JRE doesnt contiene cabecera JNI) Ejemplo: Al panel de configuración variable de entorno definir var: JAVA_HOME val: C: \ archivos de programa \ Java \ jdk1.7.0_11
  2. añadir % JAVA_HOME% \ bin a la ruta variable de

Después de hacer esos pasos, la aplicación puede encontrar el nombre de procedimiento JNI y enlaces a JNI . dll en forma correcta. Por lo tanto, espero que no obtenga este error de procedimiento faltante de nuevo.

Cuestiones relacionadas