win usar registro registra qué puedo por importante forzar ejecutar como archivo java dll java-native-interface loadlibrary

java - usar - regedit dll



Mi código DLL funciona desde un archivo exe, pero no se carga desde Java loadLibrary (2)

He creado un módulo de C ++ para construir en un archivo de biblioteca compartida y luego llamarlo desde Java usando JNI.

Tengo 2 entornos, Windows y Unix, y tengo un programa ejecutable de C ++ y un programa de Java que acabo de compilar para cada entorno.

  • Cuando compilo mi programa tester.exe en Unix y lo ejecuto usando métodos de mi biblioteca (.so), funciona bien.
  • Cuando compilo mi programa Java en Unix y cargo mi biblioteca (.so) con loadLibrary de Java, funciona bien.
  • Cuando compilo mi programa tester.exe en Windows y lo ejecuto usando métodos de mi biblioteca (.dll), funciona bien. Al igual que la versión de Unix.

  • Cuando compilo mi programa Java en Windows y cargo mi biblioteca (.dll) con loadLibrary de Java, falla. Dice Intentar acceder a una dirección no válida.

No puedo entender por qué no funcionará con la biblioteca de carga de Java cuando se ejecuta en Windows, pero funciona en cualquier otro lugar utilizando el mismo código. Si demoro la carga de una DLL dependiente que usa mi biblioteca, entonces mi biblioteca se carga en Java pero no es funcional. Sé que hay un código específico que causa el problema con Java al cargar mi biblioteca, pero no puedo entender por qué mi exe de C ++ no tiene ningún problema con los mismos métodos y bibliotecas.

Mi dll tiene 1 método expuesto que llama a 4 métodos de algunas bibliotecas existentes. Si comento esos 4 métodos, entonces mi dll se carga en Java bien. Sé que es algo que ver con estos métodos de una biblioteca a la que está vinculado dll. ¿Hay algo diferente en cómo Java ve las bibliotecas dependientes? He intentado cargar las bibliotecas dependientes primero, pero uno de los archivos dll que cargo provoca un error de recursión y la pila se desborda.

¿Alguien sabe cómo evitar una DLL que provoca un desbordamiento de pila de un error de recursión? Necesito los métodos, pero no puedo cargarlo con java loadLibrary.

Aquí hay más detalles sobre los archivos involucrados y el mensaje de error real. Agregué un DllMain a mi archivo dll inicial solo para ver qué carga y cuándo. Si compilo ese mismo programa (my_plain_dll_to_call_JNI_DLL) como un archivo exe, todo funciona bien. Si lo compilo y lo cargo desde mi programa Java, esto sucede.

  • myJavaProgram, simplemente llama a System.loadLibrary () para cargar un archivo .dll básico que llama a un método en mi otra DLL que contiene código JNI.
  • my_plain_dll_to_call_JNI_DLL es un dll que creé al vincularlo a mi archivo de biblioteca dll solo para probar la dependencia. Simplemente llama a un método de la otra dll que está llamando al código nativo que necesito.
  • my_JNI_DLL.ll es un archivo dll vinculado a las bibliotecas de programación C ++ existentes a las que necesito acceder desde JNI. Contiene llamadas directas a métodos en bibliotecas de código fuente existentes.

Escribí el nombre del archivo que muestra el texto a la izquierda de cada línea para mostrar en qué capa está la ejecución.

c:/java myJavaProgram myJavaProgram: Java Static Method Entry. myJavaProgram: Java Calling System.loadLibrary(my_plain_dll_to_call_JNI_DLL) my_JNI_DLL.dll: Entering DllMain my_JNI_DLL.dll: DLL_PROCESS_ATTACH my_plain_dll_to_call_JNI_DLL: DLL_PROCESS_ATTACH my_plain_dll_to_call_JNI_DLL: DLL_THREAD_ATTACH my_plain_dll_to_call_JNI_DLL: DLL_THREAD_DETACH my_plain_dll_to_call_JNI_DLL: DLL_PROCESS_DETACH myJavaProgram: my_plain_dll_to_call_JNI_DLL Loaded! myJavaProgram: Java Static Method Exit. myJavaProgram: Entering Main(). my_plain_dll_to_call_JNI_DLL: In call_my_JNI_DLL_method my_JNI_DLL.dll: In my_JNI_DLL_method my_JNI_DLL.dll: Entering my_JNI_DLL_CheckEnvironmentVariables() my_JNI_DLL.dll: Exiting my_JNI_DLL_CheckEnvironmentVariables my_JNI_DLL.dll: Calling StartExistingNativeCode. # # A fatal error has been detected by the Java Runtime Environment: # # Internal Error (0xc0fb007e), pid=7500, tid=7552 # # JRE version: 6.0_21-b06 # Java VM: Java HotSpot(TM) Client VM (17.0-b16 mixed mode, sharing windows-x86 ) # Problematic frame: # C [KERNELBASE.dll+0x9673] # # An error report file with more information is saved as: # C:/hs_err_pid7500.log # # If you would like to submit a bug report, please visit: # http://java.sun.com/webapps/bugreport/crash.jsp # The crash happened outside the Java Virtual Machine in native code. # See problematic frame for where to report the bug. # my_plain_dll_to_call_JNI_DLL: DLL_PROCESS_DETACH my_JNI_DLL.dll: Entering DllMain my_JNI_DLL.dll DLL_PROCESS_DETACH

Actualización He reducido el problema a una biblioteca de administración de memoria que está vinculada desde otra dll que usa mi programa. La DLL que utiliza es sh33w32.dll, se llama SmartHeap y es por una compañía llamada Microquil, creo. Tengo la versión 3.3, y cuando Java LoadLibrary intenta cargar esa dll, falla. No estoy seguro de lo que podría hacer para que java maneje esa biblioteca. Debe tener algo que ver con el área de memoria a la que Java puede acceder, en comparación con las ventanas que permiten acceder a un exe. El archivo exe no tiene problemas con la biblioteca SmartHeap, pero Java no me permitirá usarlo. ¿Alguna idea o experiencia tratando con esto? He intentado eliminar la biblioteca vinculada al compilar las otras bibliotecas, pero luego fallan las llamadas normales en el código que normalmente funcionan.

Información adicional encontrada La función que está en la dll que no se carga en java se llama MemRegisterTask. Es de un producto llamado SmartHeap de Microquill. Aquí está la documentación que encontré sobre esta función. Creo que esta asignación de memoria es lo que hace que Java no pueda cargarla.

MemRegisterTask inicializa la biblioteca SmartHeap. En la mayoría de las plataformas, no necesita llamar a MemRegisterTask porque SmartHeap se iniciará solo cuando realice la primera llamada.

SmartHeap mantiene un recuento de referencia de registro para cada tarea o proceso. Cada vez que llama a MemRegisterTask, este recuento de referencia se incrementa. Si su última llamada a SmartHeap ocurre antes de que su aplicación esté lista para terminar, puede llamar a MemUnregisterTask para terminar SmartHeap. MemUnregisterTask reduce el recuento de referencias de registro en uno: cuando el recuento es cero, SmartHeap liberará la memoria asignada por SmartHeap y el estado de depuración asociado con la tarea o el proceso actual.


Cualquier cosa útil en el archivo de registro hs_err ... Por lo general, hay un backtrace de pila, etc. señalando algo.

¿También intentaste ejecutar java.exe (con parámetros que ejecutan una prueba que carga el material) dentro del depurador?

Desde el rastreo anterior, uno puede ver que la carga parece funcionar bien (el resultado del rastreo sugiere que dllentrypoint / dllmain ha sido aumentado por usted).

La secuencia en la carga es la siguiente:

  1. carga dependiente dlls
  2. cargar dll en sí
  3. llame al dllentrypoint / dllmain w / process attach

Así que esto ya está más allá de cargar la DLL.

¿Ha comprobado si está utilizando los tiempos de ejecución de debug / release de Windows? La depuración puede chocar con el lanzamiento: Java es el lanzamiento, es probable que su ejemplo de ejecución sea el mismo que su compilación dll.


Parece una convención de llamadas o una falta de coincidencia de tamaño de tipo para mí. Cada compilador de Windows C tiene su propio conjunto de peculiaridades, y los encabezados JNI de Windows asumen (una versión reciente de) Microsoft Visual C ++. Mire detenidamente las advertencias: la pérdida de precisión es una mala señal.

Por ejemplo, __int64 es específico de __int64 . __int64 averiguar cuál es el nombre del tipo de entero de 64 bits en Borland C y __int64 a __int64 antes de incluir jni.h