Ejecuté el mismo programa con IBM JVM (arroja más información sobre 'kill -QUIT'). Los fotogramas en el volcado de subprocesos explican el comentario de Tom Hawkin:
Cambié el nombre de Main a StaticBlockShutdownHook. Como puede ver a continuación, un bloqueo de inicialización interno (monitor) ha sido retenido por el hilo principal durante la ejecución del bloque estático() y el hilo de Shutdown Hook está esperando ser notificado en este monitor.
3XMTHREADINFO "main" J9VMThread:0x0000000110F5FE00, j9thread_t:0x000000011014E500, java/lang/Thread:0x0700000000002330, state:CW, prio=5
3XMTHREADINFO1 (native thread ID:0x5A10083, native priority:0x5, native policy:UNKNOWN)
3XMTHREADINFO3 Java callstack:
4XESTACKTRACE at java/lang/Object.wait(Native Method)
4XESTACKTRACE at java/lang/Object.wait(Object.java:196)
4XESTACKTRACE at java/lang/Thread.join(Thread.java:616)
4XESTACKTRACE at java/lang/ApplicationShutdownHooks.run(ApplicationShutdownHooks.java:91)
4XESTACKTRACE at java/lang/Shutdown.runHooks(Shutdown.java:101)
4XESTACKTRACE at java/lang/Shutdown.sequence(Shutdown.java:145)
4XESTACKTRACE at java/lang/Shutdown.exit(Shutdown.java:190)
4XESTACKTRACE at java/lang/Runtime.exit(Runtime.java:101)
4XESTACKTRACE at java/lang/System.exit(System.java:279)
4XESTACKTRACE at StaticBlockShutdownHook.<clinit>(StaticBlockShutdownHook.java:11)
4XESTACKTRACE at java/lang/J9VMInternals.initializeImpl(Native Method)
4XESTACKTRACE at java/lang/J9VMInternals.initialize(J9VMInternals.java:200(Compiled Code))
3XMTHREADINFO "Thread-5" J9VMThread:0x0000000112C5AF00, j9thread_t:0x0000000112BE01C0, java/lang/Thread:0x07000000000D0380, state:CW, prio=5
3XMTHREADINFO1 (native thread ID:0x23B00BD, native priority:0x5, native policy:UNKNOWN)
3XMTHREADINFO3 Java callstack:
4XESTACKTRACE at java/lang/Object.wait(Native Method)
4XESTACKTRACE at java/lang/Object.wait(Object.java:167(Compiled Code))
4XESTACKTRACE at java/lang/J9VMInternals.initialize(J9VMInternals.java:130(Compiled Code))
4XESTACKTRACE at StaticBlockShutdownHook$1.run(StaticBlockShutdownHook.java:7)
La sección "monitores" muestra que los bloqueos son de la clase Principal. El J9VMINternals.initializeImpl() parece ser un método nativo que toma el bloqueo del objeto Class.
1LKMONPOOLDUMP Monitor Pool Dump (flat & inflated object-monitors):
2LKMONINUSE sys_mon_t:0x0000000110FF38D0 infl_mon_t: 0x0000000110FF3910:
3LKMONOBJECT [email protected]/0x07000000000DB7E0: <unowned>
3LKNOTIFYQ Waiting to be notified:
3LKWAITNOTIFY "Thread-5" (0x0000000112C5AF00)
2LKMONINUSE sys_mon_t:0x0000000112687AA0 infl_mon_t: 0x0000000112687AE0:
3LKMONOBJECT [email protected]/0x07000000000D0398: <unowned>
3LKNOTIFYQ Waiting to be notified:
3LKWAITNOTIFY "main" (0x0000000110F5FE00)
Dado que la variable estática es definitiva, parece absurdo que necesite acceder a la clase. Gracias por la referencia Main.a. –
@Anderw Si fuera una constante en tiempo de compilación, entonces se copiará en el archivo de clase. Tal como está, la referencia al objeto particular necesita ser copiada en tiempo de ejecución. En general, con Java funciona de la manera más simple posible (¿esperarías que el comportamiento cambiara si no fuera final o si viniera después del bloque estático?). (El Modelo de memoria de Java (JMM) sí permite algunas suposiciones sobre los campos de instancia final. No estoy seguro acerca de los campos estáticos finales). –