vuelve veo problema porque mis los intentarlo hashtags guardaron funcionan cambios aparezco aparecen java static initialization noclassdeffounderror

java - veo - ¿Por qué NoClassDefFoundError causado por un error de inicialización de campo estático?



porque no veo mis hashtags en instagram (4)

Aquí hay una interesante pregunta de java.

El siguiente programa Java simple contiene un campo estático inicializado por un método de forma estática. En realidad, fuerzo el método que calcula el valor intiailize para generar una NullPointException. Cuando accedo a un campo estático de este tipo, se generará un NoClassDefFoundError. Parece que la VM trata la clase no está completa.

Pero cuando accedo a la Clase, todavía está disponible;

¿Alguien sabe por qué?

class TestClass { public static TestClass instance = init(); public static TestClass init() { String a = null; a.charAt(0); //force a null point exception; return new TestClass(); } } class MainClass { static public void main(String[] args) { accessStatic(); // a ExceptionInInitializerError raised cause by NullPointer accessStatic(); //now a NoClassDefFoundError occurs; // But the class of TestClass is still available; why? System.out.println("TestClass.class=" + TestClass.class); } static void accessStatic() { TestClass a; try { a = TestClass.instance; } catch(Throwable e) { e.printStackTrace(); } } }


Cuando accedo a dicho campo estático, se generará un NoClassDefFoundError. Parece que la VM trata la clase no está completa.

Eso es correcto ...

Pero cuando accedo a la Clase, todavía está disponible.

Sí.

El cargador de clases no ha intentado eliminar la clase dañada porque:

  • sería difícil de hacer,
  • Sería extremadamente difícil hacerlo de forma segura .
  • dejaría la JVM en un estado en el que una aplicación podría fácilmente perder mucho tiempo cargando y recargando repetidamente el código roto, y
  • las especificaciones dicen (o al menos implican) que no debería; ver otras respuestas para más detalles.

Para entrar en un estado donde esta inconsistencia es visible, su aplicación tiene que detectar ClassDefNotFoundError (o una superclase) e intentar recuperarse de ella. Es un hecho bien documentado que las excepciones de Error generalmente no son recuperables; es decir, si intenta recuperarse, la JVM puede terminar en un estado inconsistente. Eso es lo que ha sucedido aquí ... con respecto a las clases que se estaban cargando / inicializando.


La respuesta a tales preguntas generalmente está (§12.4.2) en algún lugar de las especificaciones ... (§12.4.2)

¿Qué pasa cuando se inician las clases?

Los pasos 1-4 no están relacionados con esta pregunta. El paso 5 aquí es lo que desencadena la excepción:

5 . Si el objeto Clase está en un estado erróneo, la inicialización no es posible. Libere el bloqueo en el objeto Clase y lance un NoClassDefFoundError.

6-8 continuar la inicialización, 8 ejecuta los inicializadores, y lo que generalmente sucede es en el paso 9:

9 . Si la ejecución de los inicializadores se completa normalmente, entonces bloquee este objeto de clase, etiquételo como completamente inicializado, notifique a todos los hilos en espera, libere el bloqueo y complete este procedimiento normalmente.

Pero tenemos un error en el inicializador así que:

10 . De lo contrario, los inicializadores deben haberse completado abruptamente lanzando alguna excepción E. Si la clase de E no es Error o una de sus subclases, cree una nueva instancia de la clase ExceptionInInitializerError, con E como argumento, y use este objeto en su lugar de E en el siguiente paso. Pero si no se puede crear una nueva instancia de ExceptionInInitializerError porque se produce un OutOfMemoryError, en su lugar use un objeto OutOfMemoryError en lugar de E en el siguiente paso.

Sí, vemos un ExceptionInInitializerError b / c de la excepción de puntero nulo.

11 . Bloquee el objeto Clase, etiquételo como erróneo, notifique a todos los hilos en espera, libere el bloqueo y complete abruptamente este procedimiento con la razón E o su reemplazo según lo determinado en el paso anterior. (Debido a una falla en algunas implementaciones tempranas, se ignoró una excepción durante la inicialización de la clase, en lugar de causar un ExceptionInInitializerError como se describe aquí).

Y luego la clase está marcada como errónea, por eso obtenemos la excepción del paso 5 la segunda vez.

La parte sorprendente es la tercera impresión que muestra que TestClass.class en MainClass en realidad contiene una referencia a un objeto Class físico.

Probablemente porque TestClass todavía existe, simplemente está marcado como erróneo. Ya ha sido cargado y verificado.


Sí, normalmente es por eso que se NoClassDefFoundError . Se llama malvado , eso es todo. Debería haber sido nombrado como "clase de excepción fallida de inicio" o algo así.

Debido al nombre engañoso, los programadores de Java que obtuvieron este error desperdiciaron cientos de años humanos tratando de averiguar por qué no se puede encontrar la clase.

Cuando vea esta excepción, debe revisar el registro hacia arriba e intentar averiguar la causa raíz cuando la clase no pudo iniciar.