Ejecutar un archivo .jar como servicio en Windows Server 2019 y evitar el error 0x80004005

¿Tu aplicación Java se detiene al intentar ejecutarse como servicio en Windows Server 2019? Aprende a diagnosticar el error 0x80004005 y a desplegar tu .jar para que arranque en segundo plano, sin necesidad de iniciar sesión, mediante WinSW, NSSM o la propia utilidad sc.exe.

Índice

Resumen del problema

Al registrar un servicio con sc.exe o con un wrapper (WinSW / NSSM) el servicio arranca y se detiene al instante. En el Visor de eventos aparece la excepción:

System.ComponentModel.Win32Exception (0x80004005): The system cannot find the file specified

El código indica que Windows no localiza el binario configurado como binPath —normalmente java.exe— o el propio .jar, por lo que el Administrador de servicios marca el proceso como fallido.

Causas habituales

  • Variable JAVA_HOME mal definida o ausente.
  • %JAVA_HOME%\bin no agregado a PATH.
  • Ruta del .jar con espacios no encerrada entre comillas.
  • Permisos insuficientes de la cuenta de servicio sobre la carpeta que contiene el .jar o sobre el JRE.
  • Timeout de inicio demasiado corto en el wrapper.

Verificación rápida antes de crear el servicio

  1. Asegúrate de que el .jar se ejecuta de forma interactiva:
    java -jar "C:\Apps\MiAplicacion\app.jar"
  2. Comprueba que la versión de Java coincide con la que usó el desarrollador (por ejemplo Java 8 u201 o Java 17 LTS).
  3. Valida que el usuario «Servicio» (o la cuenta dedicada que vas a emplear) tenga acceso de lectura y ejecución en la carpeta de la aplicación.

Cómo corregir las variables de entorno Java

  1. Panel de control → Sistema → Configuración avanzada → Variables de entorno.
  2. Crea o edita JAVAHOME con la ruta del JRE o JDK, p. ej. C:\Program Files\Java\jre1.8.0401.
  3. En PATH, añade: %JAVA_HOME%\bin (sitúalo antes de otras rutas que incluyan Java).
  4. Abre una nueva ventana de PowerShell y comprueba:
    java -version

Si Java responde correctamente y el .jar corre manualmente, ya puedes envolverlo como servicio.

Enfoques para convertir un .jar en servicio

OpciónVentajasLimitaciones
WinSW (Windows Service Wrapper)No requiere instalación; un exe y un xml
Soporta reinicios automáticos, logs rotativos, argumentos complejos
Tiempo de inicio predeterminado 30 s (ajustable)
NSSM (Non‑Sucking Service Manager)Interfaz interactiva para crear servicios
Permite redirigir stdout/stderr a fichero
Proyecto sin releases formales desde 2018, aunque estable
sc.exe + ejecutable propioNo dependes de terceros; usa utilidades nativasNecesitas un wrapper lanzable (Launch4j, JSW, JSL) o un .bat convertido a .exe

Implementación con WinSW (recomendado)

  1. Descarga la versión estable de WinSW (x64) y cópiala en la carpeta de la aplicación.
  2. Renómbrala acorde al servicio: MiServicio.exe.
  3. Crea MiServicio.xml en la misma carpeta:
<service>
  <id>MiServicio</id>
  <name>Mi Servicio Java</name>
  <description>Ejecuta app.jar como servicio.</description>

  <executable>%JAVA_HOME%\bin\java.exe</executable>
  <arguments>-jar "C:\Apps\MiAplicacion\app.jar" --spring.profiles.active=prod</arguments>
  <logpath>C:\Logs\MiServicio</logpath>
  <log mode="roll-by-size">
    <sizeThreshold>10MB</sizeThreshold>
    <keepFiles>5</keepFiles>
  </log>
  <onfailure action="restart" delay="10 sec"/>
</service>
  1. Instala el servicio:
    .\MiServicio.exe install
  2. Configura el arranque automático (opcionalmente retrasado):
    sc config MiServicio start= auto sc config MiServicio delayed-auto= yes
  3. Inícialo y verifica:
    net start MiServicio

¿Qué hace WinSW internamente?

Levanta un proceso hijo con java.exe; captura stdout/stderr; vigila el PID. Si el proceso sale con código distinto de 0, aplica la directiva <onfailure>.

Implementación con NSSM

  1. Descarga nssm.exe y cópialo, por ejemplo, en C:\NSSM.
  2. En PowerShell (Admin):
# Crear el servicio
nssm install MiServicio "C:\Program Files\Java\jre1.8.0_401\bin\java.exe" "-jar" "C:\Apps\MiAplicacion\app.jar"

Opciones recomendadas

nssm set MiServicio Start SERVICE\AUTO\START
nssm set MiServicio AppDirectory "C:\Apps\MiAplicacion"
nssm set MiServicio AppStdout "C:\Logs\MiServicio\stdout.log"
nssm set MiServicio AppStderr "C:\Logs\MiServicio\stderr.log"

Iniciar

net start MiServicio

Implementación con sc.exe + script .bat

  1. Crea launch.bat:
@echo off
set "JAVAHOME=C:\Program Files\Java\jre1.8.0401"
"%JAVA_HOME%\bin\java.exe" -jar "C:\Apps\MiAplicacion\app.jar"
  1. Convierte el .bat a .exe con launch4j o similar (require .NET 2 runtime).
  2. Registra el servicio:
sc create MiServicio binPath= "C:\Apps\MiAplicacion\launch.exe" start= auto

Ejecución sin iniciar sesión

Un servicio se inicia en la fase de arranque gestionada por el Service Control Manager (SCM), mucho antes de que un usuario interactúe con la consola. No obstante, debes elegir la cuenta de servicio adecuada:

  • LocalSystem: permisos máximos; no recomendado salvo necesidad.
  • Servicio local / Servicio de red: suficientes en la mayoría de los casos.
  • Cuenta de dominio: imprescindible si accedes a recursos compartidos (UNC) o base de datos con autenticación integrada.

Para cambiarla: services.msc → propiedades → Inicio de sesión o con PowerShell:

Set-Service MiServicio -StartupType Automatic
$cred = New-Object System.Management.Automation.PSCredential ("DOMINIO\svc_java", (ConvertTo-SecureString "Contraseña!" -AsPlainText -Force))
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\MiServicio" -Name "ObjectName" -Value $cred.UserName
Contraseña en registro protegido
sc.exe config MiServicio obj= "DOMINIO\svc_java" password= "Contraseña!"

Métodos alternativos al servicio

Tarea programada

  1. Programador de tareas → Nueva tarea.
  2. Disparador: «Al iniciar el sistema».
  3. Acción: java.exe -jar "C:\Apps\MiAplicacion\app.jar".
  4. Marca «Ejecutar con los privilegios más altos».

La ventaja principal es la simplicidad; el inconveniente, la falta de supervisión nativa que sí ofrece el SCM.

Script de inicio de GPO

En entornos de dominio, añade launch.bat en Computer Configuration → Policies → Windows Settings → Scripts (Startup/Shutdown). Recuerda que el script se ejecuta bajo LocalSystem y solo después de que el equipo se una al dominio.

Habilitar reinicio automático y retención de logs

WrapperConfiguraciónResultado
WinSW<onfailure action="restart" delay="15 sec"/>Reintentos ilimitados cada 15 s
NSSMnssm set MiServicio AppExit Default RestartReinicia al salir con código ≠ 0
SCM nativosc failure "MiServicio" reset= 30 actions= restart/60000Tras 60 s reinicia; cuenta fallos por 30 días

Seguridad y buenas prácticas

  • Prueba siempre el .jar en un entorno de preproducción.
  • Asigna NTFS de solo lectura a la carpeta de la aplicación para el usuario del servicio.
  • Ubica los logs fuera de Program Files para no requerir privilegios elevados.
  • Encripta credenciales sensibles con DPAPI o variables de entorno cifradas si tu app las necesita.
  • Audita intentos de inicio de sesión fallidos y excepciones NoClassDefFoundError en el log de la JVM.

Checklist de resolución de problemas

  • ¿El servicio arranca manualmente desde services.msc?
  • Si se detiene, consulta Visor de eventos → Aplicación (filtra por Error).
  • Revisa %SystemRoot%\system32\config\systemprofile\AppData\Local\WinSW si WinSW no crea los logs donde esperas.
  • Ejecuta sc queryex MiServicio para comprobar el PID y el último código de salida.
  • Eleva el nivel de log de Java con -Djava.util.logging.config.file=logging.properties.
  • Asegúrate de que no haya puertos ocupados (usa netstat -ano | findstr :8080).

Conclusión

El error 0x80004005 al crear un servicio Java en Windows Server 2019 suele deberse a rutas incorrectas o a la ausencia de JAVA_HOME. Con WinSW o NSSM puedes encapsular tu .jar en un servicio robusto que se inicia antes de que cualquier usuario inicie sesión, dispone de reinicio automático y genera logs rotativos. Ajustar correctamente las variables de entorno, los permisos NTFS y las opciones de recuperación garantiza que tu aplicación Java permanezca disponible tras cada reinicio del servidor.

Índice