2012-09-13 11 views
6

Tengo un problema raro: si mi aplicación se ejecuta durante un tiempo prolongado (> 20 h), entonces a veces obtengo el error NoClassDefFound, parece que JVM decidió que la clase no iba a ser utilizado de todos modos y GCD.Faltan clases si la aplicación se ejecuta durante mucho tiempo

a ser un poco más específico, aquí es un caso de ejemplo:

object ErrorHandler extends PartialFunction[Throwable,Unit] { 
    def isDefinedAt(t: Throwable) = true 
    def apply(e: Throwable) =e match { 
    // ... handle errors 
    } 
} 

// somewhere else in the code... 
try { 
    // ... long running code, can take more than 20 hours to complete 
} catch (ErrorHandler) 

y me da la siguiente excepción:

Exception in thread "main" java.lang.NoClassDefFoundError: org/rogach/avalanche/ErrorHandler$ 

Si ese try/carreras de bloque de captura de pequeñas cantidades de tiempo, todo funciona como se espera

Si alguien está interesado, aquí está el código base de que se trate: Avalanche

necesito señalar que vi este problema y otros similares sólo en Cent OS 5 máquinas, utilizando 6u26 JRE y Scala 2.9.1/2.9.2.

¿Cuál podría ser la causa de este problema?

+4

Intenta ejecutarlo con '-XX: -TraceClassUnloading'. ¿Cuáles son los resultados? http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html – ron

+0

@ron - Lo estoy intentando en este momento, pero llevará algo de tiempo :) Y el archivo de registro es bastante largo y verboso, ¿para qué palabras debo grep para obtener la salida de rastreo? – Rogach

+0

no se puede adivinar con los ojos vendados, pero el nombre de la clase bajo sospecha es un candidato seguro :) – ron

Respuesta

1

Si te quedaste sin memoria tratando de inicializar una clase, ¿crees que verías OutOfMemory o NoClassDef?

//from initialize_impl 
    if (NULL == message) { 
    // Out of memory: can't create detailed error message 
    THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), className); 

Es posible que su código arrojó OOM, entonces no podía cargar el objeto de gestión de excepciones.

Existen, por supuesto, otras posibles condiciones transitorias: la red no funciona y la clase está en una unidad de red; o limpió su directorio de clases durante la prueba. Otra posibilidad es que haya creado su aplicación en un sistema de archivos que no distingue entre mayúsculas y minúsculas y está probando en un sistema de archivos con distinción de mayúsculas y minúsculas con un archivo de clase denominado anómalamente. Por ejemplo, si cambia el objeto "manejador" a "Manejador" sin eliminar *. Clase, aún verá "Manejador.clase". (Pero sospecho que el detalle del mensaje de error incluiría el conflicto de nombres; a menos que sea OOM, por supuesto.)

No he tenido la oportunidad de intentar romper AbstractFileClassLoader; mi especulación anterior sigue:

Vale la pena explicar que Avalanche es una herramienta de compilación, y ejecuta una instancia de scalac para compilar el build.scala a un archivo de clase en memoria que está cargado con AbstractFileClassLoader de scalac, donde "AbstractFile" es la abstracción Dado que cualquiera build.scala se arruina con la configuración de la herramienta, obviamente es esencial que AFCL respete la delegación del cargador de clases. Eso parece cierto, pero me doy cuenta de que no se delegan primero en Parent en getResourceAsStream (como una prueba rápida confirmada). Lo sospechoso es que findClass usa classBytes, que en el fallo llama a super, que es el buen ScalaClassLoader, pero que usa getResourceAsStream para cargar Foo.class. Entonces, llamar a findClass podría devolver una clase desde CL padre (lo cual es incorrecto), aunque eso puede ser discutible si se sabe que el padre ya falló. Debido a que es la mitad de la noche, no puedo sacar una conclusión, pero me gustaría aclarar eso si mi herramienta de construcción se basó en este comportamiento.

No sé qué hay en tu build.scala (o av.scala) que se ejecuta por un día, pero quizás tengas Avalanche (re) cargado por un cargador de clases infantil que funciona mal, y luego cuando lo arroje, CL no puede encontrar Clasificar su ErrorHandler.

+0

Bueno, puede que tenga razón, pero yo observé un comportamiento similar en otras dos situaciones, donde no me metí con los cargadores de clases. Y el tema que une todos esos casos parece ser funciones parciales. – Rogach

+0

No sé casi nada sobre los cargadores de clases, pero se usa 'AbstractFileClassLoader' (creo) solo para cargar esa clase 'Build', y todas las otras clases deben pasar por el cargador de clases predeterminado. ¿O hay algún mecanismo por el cual el cargador de clases hijo pueda comenzar a ser un reemplazo para su padre? – Rogach

Cuestiones relacionadas