thread solucion caused java jvm noclassdeffounderror classnotfoundexception

solucion - java.lang.noclassdeffounderror minecraft



¿Qué podría causar una repentina ClassNotFoundException en un proceso de larga ejecución? (2)

El seguimiento de la pila nos dice que se trata de procesar anotaciones y no está conectado con la carga de la clase para ejecutar el código. Parece que el procesador de anotación intenta resolver el valor de un miembro de anotación a través del ClassLoader del elemento anotado.

En otras palabras, tiene una anotación con un valor de tipo de clase como @Foo(xyz=ABC.class) y una clase o miembro anotado con este constructo, pero la clase ABC no se puede alcanzar a través del ClassLoader del elemento anotado en el tiempo de ejecución.

Esto no entra en conflicto con el hecho de que esta clase ya se ha cargado a través de otro ClassLoader .

Tenemos un servicio web muy pequeño (menos de 1K de líneas de código) administrado por Jetty. El servicio funcionó siempre bien incluso durante nuestra fase de prueba de estrés. Sin embargo, después de 13 días de tiempo de actividad, experimentamos una excepción ClassNotFoundException en dos nodos el mismo día.

Lo extraño es que la clase que no se encontró ya estaba allí (es parte de la rutina de inicio y se utilizó constantemente para atender solicitudes anteriores) . De hecho, simplemente reiniciar el proceso resolvió el problema. Ambos nodos están en máquinas separadas y son independientes entre sí. No dependen de recursos externos, excepto en una conexión JMS.

No pude encontrar información relevante al buscar en Google esto, ya que la mayoría de los problemas informados están relacionados con clases faltantes en la ruta de clase al iniciar el proceso de Java, que no es nuestro caso. Sospechamos que podría haber una pérdida de memoria que de alguna manera corrompió la memoria JVM, sin embargo, esto no puede explicar por qué ocurrió el mismo problema en dos nodos al mismo tiempo. Hemos estado realizando pruebas intensivas de esfuerzo durante los últimos cinco días conectando un monitor JVM y un analizador de fugas de memoria, y todo parece estar bien. Para estas pruebas disminuimos la memoria de proceso de 2GB a 512MB.

Detalles:

  • Utilizando Java HotSpot (TM) 64-Bit Server VM (compilación 16.3-b01, modo mixto)
  • Utilizando jetty-runner-8.1.0.RC5.jar
  • Línea de cmd original: java -Xmx2048M -jar embarcadero-corredor-8.1.0.RC5.jar --port 5000 webapp.war
  • Intel Xeon E5-2680 8 núcleos (x2) + 16 GB de RAM
  • Red Hat Enterprise Linux 6
  • Algunos marcos en uso: JBoss Resteasy, Spring IoC, Guava.

¿Pueden contribuir con ideas sobre qué podría hacer que la JVM "olvide" repentinamente la existencia de una clase previamente cargada y no pueda volver a cargarla?

Caused by: java.lang.ClassNotFoundException: com.a.b.c.SomeClass at java.net.URLClassLoader$1.run(URLClassLoader.java:202) ~[na:1.6.0_37] at java.security.AccessController.doPrivileged(Native Method) ~[na:1.6.0_37] at java.net.URLClassLoader.findClass(URLClassLoader.java:190) ~[na:1.6.0_37] at java.lang.ClassLoader.loadClass(ClassLoader.java:306) ~[na:1.6.0_37] at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) ~[na:1.6.0_37] at java.lang.ClassLoader.loadClass(ClassLoader.java:247) ~[na:1.6.0_37] at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:424) ~[na:na] at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:377) ~[na:na] at java.lang.Class.forName0(Native Method) ~[na:1.6.0_37] at java.lang.Class.forName(Class.java:247) ~[na:1.6.0_37] at sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:95) ~[na:1.6.0_37] at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:107) ~[na:1.6.0_37] at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:31) ~[na:1.6.0_37] at sun.reflect.annotation.AnnotationParser.parseSig(AnnotationParser.java:370) ~[na:1.6.0_37] at sun.reflect.annotation.AnnotationParser.parseClassValue(AnnotationParser.java:351) ~[na:1.6.0_37] at sun.reflect.annotation.AnnotationParser.parseMemberValue(AnnotationParser.java:280) ~[na:1.6.0_37] at sun.reflect.annotation.AnnotationParser.parseAnnotation(AnnotationParser.java:222) ~[na:1.6.0_37] at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:69) ~[na:1.6.0_37] at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:52) ~[na:1.6.0_37] at java.lang.reflect.Field.declaredAnnotations(Field.java:1014) ~[na:1.6.0_37] at java.lang.reflect.Field.getDeclaredAnnotations(Field.java:1007) ~[na:1.6.0_37]

Editar:

Alguien me mencionó que al usar montajes NFS bajo Win, podría suceder que la JVM decida descargar una clase y luego volver a cargarla cuando sea necesario. Si en el medio de este proceso la conexión NFS se rompió, el identificador del archivo no será válido y la carga volverá a fallar con una pila stacktrace similar. En nuestro caso, estamos usando Linux y todos los archivos involucrados están en el mismo montaje, que es un disco duro local. Solo por el bien de hacer más pruebas, me he CD''d en el directorio temporal de Jetty y he eliminado manualmente uno conocido por una clase de servicio específica. Si la JVM la descarga y luego intenta volver a cargarla desde el directorio de clases, fallará. Si bien esto no explica el problema original, podría poner más información sobre la mesa ...


Esto es lo que está sucediendo:

  1. Cuando el servicio se inicia utilizando el cmd detallado anteriormente, Jetty crea un subdirectorio bajo "/ tmp", que contiene las clases y los recursos de la aplicación cargados por la JVM.
  2. Después de un período de inactividad (en nuestro escenario específico, entre 13 y 20 días), ese directorio desaparece. Como resultado, la JVM no puede cargar el archivo. Todavía no sabemos con precisión si la JVM descargó la clase antes de este error, o por qué intentó volver a leer el archivo * .class. Sería interesante buscar en el código fuente y aprender sobre esto, pero eso no está en nuestra lista de tareas pendientes a corto plazo.
  3. El simple hecho de reiniciar Jetty provocó la recreación de los directorios perdidos y el servicio se activó nuevamente.

Una buena pista que tuvimos es que algunas personas informaron sobre un problema similar al cargar recursos en JAR sobre NFS en Windows (si la conectividad de red se pierde por un breve momento, los manejadores de NFS se vuelven inválidos y la JVM falla con un error similar). Este no es nuestro caso (/ tmp es el almacenamiento local), pero bastante similar.

Gracias a todos por su ayuda.