2011-03-14 17 views
5

Tengo una aplicación Java que llama a muchos métodos nativos diferentes de una aplicación heredada a través de JNI. Pero JVM se bloquea con un volcado de pila en lugares aleatorios, fuera de cualquier llamada JNI. A veces se cuelga durante el GC, a veces durante la carga de clases y otros lugares. Sospecho que uno o más métodos nativos corrompen el almacenamiento dinámico de JVM o alguna otra estructura de datos. Necesito saber qué llamada es esta, para poder arreglar la implementación nativa.Cómo depurar problemas de corrupción del montón de JNI?

El uso de la herencia es una DLL de 3 ª parte para la que no tengo ni fuentes de información de símbolos. Para hacerlo invocable desde Java, construí una DLL contenedora que usa convenciones de llamadas JNI.

La solución perfecta sería una opción JVM extendida que obliga JVM para comprobar automáticamente la integridad del montón y sus otras estructuras de datos después de cada llamada JNI.

¿Conoce algo que puede ayudar?

P.S. Por favor, no me diga que construya un zócalo o capa de tubería entre JVM y la aplicación heredada, porque nuestros requisitos no lo permiten. Se trata de la detección de errores, no del diseño de la arquitectura.

+0

Asumo que sabes sobre '-Xcheck: jni'? – Erik

+0

Sí, pero gracias por preguntar. – fernacolo

+0

Tengo el mismo problema, si esto ayuda:/Tengo una gran cantidad de datos que viajan a través de JNI, y ocasionalmente obtengo una dirección y datos de paquetes corruptos. Atornilla toda la simulación, y es realmente molesto. –

Respuesta

5

Debido Salí de respuestas y no pude encontrar una solución preparada por mí mismo, terminó la construcción de un proceso de caja de arena en C++ puro sólo para identificar el problema. Mi aplicación Java crea una instancia del proceso de espacio aislado con ProcessBuilder y luego se comunica con él usando stdin y stdout. En lugar de JVM, es la caja de arena la que realmente carga y llama a la DLL heredada. Luego supervisé el proceso de la zona de pruebas con Application Verifier de Microsoft, que encontró un problema de corrupción de memoria: hubo una llamada que pasaba un búfer más pequeño de lo esperado. Después de identificar esto, acabo de aumentar la longitud del byte [] utilizado como buffer en la aplicación Java, y ahora JVM puede realizar llamadas directas a DLL sin usar sandbox.

En general, perdió casi 10 días, porque la JVM no tiene una opción para verificar montón después de cada llamada JNI. Pero al menos ahora si alguien encuentra un bloqueo, podemos depurarlo rápidamente usando el sandbox.

Cuestiones relacionadas