2012-01-09 26 views
5

Para un proyecto, necesitamos una forma de ejecutar scripts de usuario que pueden venir con archivos JAR adjuntos con clases adicionales.¿Cómo puedo probar la unidad GC?

¿Cuáles son mis opciones cuando quiero escribir un par de pruebas para asegurarme de que las secuencias de comandos normales no dejen nada colgando?

Necesito saber específicamente: ¿Están todas las clases de los JAR adjuntos "descargadas"?

Nota: No estoy buscando la solución 100% súper hermética que funciona en todas las versiones de Java de 1.0 a 7. En este momento, solo necesito ser mejor que "No tengo ni idea".

+0

Por qué iban a ser descargados? ¿Quiere decir que sus instancias serán GCed, es decir, el código y las bibliotecas de las secuencias de comandos del usuario no tienen pérdidas de memoria? ¿Los estás cargando con un nuevo cargador de clases? –

+0

Sí. Lo que me gustaría es una forma de preguntarle al GC "¿podrías GC esta instancia en este momento?" O tal vez "dime cuántas referencias existen para la instancia' foo' "¿Cómo lo hacen los profilers? –

Respuesta

3

La mejor opción posible es asegurarse de que sus frascos cargados sean cargados por un cargador de clases específico, y luego descartar ese cargador de clases (después de descartar todos los objetos).

En cuanto a la prueba unitaria de la descarga, si va con esta opción, necesita extender su marco de prueba y cargadores de clases personalizados para tener un indicador de "crear cargador de clases bajo demanda". Luego, cargue la clase una vez con la bandera encendida, descarte el cargador de clases e intente cargar la clase nuevamente con la bandera apagada. Si la clase realmente no es alcanzable, el segundo intento arrojará una excepción de clase no encontrada. A continuación, ajusta sus pruebas unitarias para pasar si entran en la excepción, y fallan si logran golpear la línea después del segundo intento de carga.

Si está dispuesto a utilizar más que las herramientas de Java puro, un contenedor OSGi podría ser una consideración. La mayoría de las implementaciones de contenedores OSGi establecidas prueban explícitamente la descarga de clases.

+0

+1 para la segunda opción.Para estar 100% seguro (que sé que no es el requisito), probablemente necesitaría ejecutar el cargador de clases con un administrador de seguridad (para garantizar que los scripts no crearan hilos, etc.). –

+0

@Sean Reilly, gracias. Las otras opciones se convirtieron en ruido, así que moví el mensaje más cerca de la parte superior. –

+0

El punto de la pregunta parece ser que Aaron ya está haciendo lo que describes en tu primer párrafo, pero como no puedes descartar explícitamente los objetos de Java, él quiere una forma de comprobar si realmente está sucediendo implícitamente, o si hay una fuga. –

3

No trataría de probar esta unidad. En cambio, ejecutaba la JVM con -XX: -TraceClassUnloading y miraba para ver si las clases en cuestión aparecían en la salida de rastreo.

1

Esto depende completamente de la forma en que permita que se ejecuten las secuencias de comandos. ¿Tienen acceso a las clases del resto de la aplicación?

La forma típica de perder memoria en Java es tener una referencia estática. Una referencia estática solo es estática dentro del ClassLoader de la clase que lo contiene. Por lo tanto, si carga sus scripts de usuario utilizando un ClassLoader, puede administrarse usted mismo (y debe hacerlo de todos modos), entonces las referencias (estáticas o no) en el interior serán eligables para GC tan pronto como lo haga su propio cargador de clases.

La única forma en que podrían evitar esto, es agregar una referencia a uno de sus objetos en uno de los suyos. Entonces debes ser muy cuidadoso con la API que expones. Otra forma es si hicieran una referencia estática a su clase en una clase de otro ClassLoader.

No veo una manera de automatizar completamente las pruebas para esto. Pero supongo que podrías rastrear la descarga de clases con cualquier perfilador decente.

2

Parece que lo que quiere probar es que los scripts de manguera no tienen un classloader leak.

Para hacer eso, me gustaría crear un WeakReference a la ClassLoader utilizado para cargar dicho JAR, a continuación, ejecutar la secuencia de comandos, a continuación, llamar System.gc() y después assertNull(reference.get())

+0

una alternativa podría ser crear una instancia de URLClassLoader por JAR y usarla para cargar las clases. Trash it (set to null) una vez hecho. – aishwarya

+1

@aishwarya: esa no es una "alternativa" en absoluto. No puedes "destruir" objetos de Java. Establecer la referencia a nulo solo permite que el objeto sea basura si no hay otras referencias. Lo que describo es cómo probar que el objeto * fue * realmente basura recolectada. Los cargadores de clases son notoriamente difíciles de eliminar porque una referencia a un objeto de cualquiera de las clases cargadas ocultas en una colección en alguna parte es suficiente para evitar que el cargador de clases y todas las clases cargadas a través de él sean recolectadas. –

Cuestiones relacionadas