Problema
Al ejecutar una aplicación java con GUI se obtiene una traza similar a la siguiente:
may 21, 2019 11:33:53 PM org.bardsoftware.impl.eclipsito.BootImpl$1 uncaughtException
ADVERTENCIA: [uncaughtException]java.awt.HeadlessException
java.awt.HeadlessException
at java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:207)
at java.awt.Window.<init>(Window.java:535)
at java.awt.Frame.<init>(Frame.java:420)
at javax.swing.JFrame.<init>(JFrame.java:218)
at net.sourceforge.ganttproject.GanttSplash.<init>(GanttSplash.java:32)
at net.sourceforge.ganttproject.GanttProject$14.run(GanttProject.java:1008)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:745)
at java.awt.EventQueue.access$300(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:706)
at java.awt.EventQueue$3.run(EventQueue.java:704)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:715)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:218)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:133)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:122)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:118)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:110)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
may 21, 2019 11:33:54 PM net.sourceforge.ganttproject.GPLogger log
INFORMACIÓN: Waiting until main window closes
java.awt.HeadlessException
at java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:207)
at java.awt.Window.<init>(Window.java:535)
at java.awt.Frame.<init>(Frame.java:420)
at javax.swing.JFrame.<init>(JFrame.java:218)
at net.sourceforge.ganttproject.GanttProjectBase.<init>(GanttProjectBase.java:102)
at net.sourceforge.ganttproject.GanttProject.<init>(GanttProject.java:191)
at net.sourceforge.ganttproject.GanttProject$15.run(GanttProject.java:1021)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:745)
at java.awt.EventQueue.access$300(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:706)
at java.awt.EventQueue$3.run(EventQueue.java:704)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:715)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:218)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:133)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:122)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:118)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:110)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
may 21, 2019 11:33:54 PM org.bardsoftware.impl.eclipsito.BootImpl$1 uncaughtException
ADVERTENCIA: [uncaughtException]java.lang.NullPointerException
java.lang.NullPointerException
at net.sourceforge.ganttproject.GanttProject$15.run(GanttProject.java:1046)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:745)
at java.awt.EventQueue.access$300(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:706)
at java.awt.EventQueue$3.run(EventQueue.java:704)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:715)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:218)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:133)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:122)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:118)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:110)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
La salida anterior corresponde al programa GanttProject que se utilizará como ejemplo.
En este caso particular el programa no muestra ninguna interfaz pero queda ejecutandose el proceso java.
La ejecución se realiza en una PC con Ubuntu 14.04
Diagnóstico
El problema está relacionado a la excepción java.awt.HeadlessException:
Thrown when code that is dependent on a keyboard, display, or mouse is called in an environment that does not support a keyboard, display, or mouse.
Se revisa el sistema buscando las JVM instaladas. En ubuntu y debian están
los paquetes default-jre
y default-jre-headless
, los cuales dependen de la
versión de java recomendada para el sistema.
$ dpkg -l 'default-jre*' | grep ^ii
Nota: jre hace referencia a Java Runtime Environment.
Si solo se lista el paquete default-jre-headless
tenemos el Caso 1.
Si no se obtiene ningún paquete puede ocurrir que haya sido instalada directamente una versión particular de la JVM. Para determinar que JVM está instalada en el sistema utilizar
$ dpkg -l '*-jre*' | grep ^ii
Aquí puede suceder que solo se encuentren paquetes con el sufijo
-jre-headless
; este será el Caso 2. También pueden no obtenerse
resultados, Caso 3, o se pueden obtener varias versiones de JVM’s,
teniendose en algunos casos que solo se encuentra instalado el paquete con
sufijo -jre-headless
en lugar de la combinación con sufijo
-jre-headless
/-jre
, a lo que llamaremos Caso 4.
Solución
Caso 1
En este caso si solo está instalado el paquete default-jre-headless
hay que
instalar además el paquete default-jre
, ya que como lo indica su descripción
no se incluye el soporte para aplicaciones gráficas:
$ apt-cache show default-jre-headless | sed -n '/^Description-en:/,/^\S/p'
Description-en: Standard Java or Java compatible Runtime (headless)
This package points to the Java runtime, or Java compatible
runtime recommended for this architecture, which is
openjdk-7-jre-headless for i386.
.
The package is used as dependency for packages not needing a
graphical display during runtime.
Description-md5: d5b4670ac6d3f132e688eb4d6e67965f
La instalación se realiza mediante:
$ sudo apt-get install -V default-jre
Caso 2
En este caso se instaló una JVM particular sin la opción para gráficos, por lo
que se debe incluir el soporte para gráficos. Esto se hace instalando el
paquete con sufijo -jre
.
Como ejemplo si la salida del comando es:
ii openjdk-7-jre-headless:i386 7u121-2.6.8-1ubuntu0.14.04.1 i386 OpenJDK Java runtime, using Hotspot JIT (headless)
Se debe instalar el paquete openjdk-7-jre
Caso 3
Si no se obtuvo ninguna salida esto indica que no se tiene instalada una JVM de
java en el PC. Conviene instalar como se mencionó en el Caso 1 el paquete
default-jre
.
Caso 4
La salida del comando dpkg -l
es similar a la siguiente:
ii openjdk-7-jre-headless:i386 7u121-2.6.8-1ubuntu0.14.04.1 i386 OpenJDK Java runtime, using Hotspot JIT (headless)
ii oracle-java7-jre 7.80-1 all Oracle Java(TM) Runtime Environment (JRE) 7 (architecture independent files)
En este caso se tiene más de una versión de JVM instalada y entra en juego el sistema de alternativas de debian.
Primero hay que saber cual es la versión por defecto en uso:
$ javac --version
o
$ update-alternatives --display java
Aquí puede pasar que la versión en uso por defecto sea la que solo tiene
instalado el -jre-headless
. En ese caso alcanza con instalar la versión
-jre
. En el ejemplo anterior openjdk-7-jre
.
Otra alternativa es que la versión por defecto sea la -jre
(en el caso de
ejemplo oracle-java7-jre
), pero el programa está utilizando la versión
-jre-headless
mediante el uso de JAVA_HOME
o porque utiliza directamente la
ruta del binario java
del paquete -jre-headless
. Las alternativas serían
nuevamente instalar la versión del paquete -jre
(en el ejemplo
openjdk-7-jre
) o configurar el script que ejecuta el programa para que utilice
la versión de java por defecto del sistema.
Lecciones aprendidas
Siempre verificar:
- Si fué instalada una versión por defecto de la JVM (paquetes
default-jre
ydefault-jre-headless
). - Las versiones de la JVM instaladas en el sistema (paquetes
-jre
y-jre-headless
). - La JVM utilizada por el programa.
Varias distribuciones separan la JVM en varios paquetes:
- headless, contiene lo minimo necesario para ejecutar programas java desde la linea de comandos
- completo, que permite ejecutar aplicaciones gráficas
- development (jdk), utilizado para el desarrollo y construcción de programas java.