Java Service Steward is a new Windows service host for Java applications. It reads the wrapper.conf format used by the Java Service Wrapper, follows the same command line and log format, and is licensed Apache-2.0 OR MIT. I wrote it because the Community Edition of the Java Service Wrapper has no 64-bit Windows build, and I did not want to buy a license or rewrite the service integration of applications that already had working configuration files.
Repository: https://github.com/jayyanez/java-service-steward
What it is
The distribution is two files, wrapper.exe and wrapper.jar. The executable is written in Rust and does the Windows part: it registers the service, launches the JVM, keeps a control channel to it over a loopback socket, restarts it when it exits unexpectedly or stops answering pings, writes and rotates wrapper.log, and handles Service Control Manager requests (stop, pause, resume, custom control codes). The JAR is compiled for Java 8 and contains the launcher classes and a small API. There is no native DLL and no JNI.
It only runs on 64-bit Windows. There is no Unix version.
What is compatible
- Configuration.
wrapper.confwith#include,#encoding,set.VAR=value,%VAR%expansion and numbered properties such aswrapper.java.additional.<n>. Relative paths resolve from the executable's directory, as before. - Command line.
-cruns in a console,-iand-rinstall and remove the service,-tand-pstart and stop it,-qqueries it,-drequests a thread dump. Property overrides on the command line and--pass-through of application arguments work the same way. - Service registration. An installed service's ImagePath calls
wrapper.exe -s <conf>, so an existing registration keeps working. - Log format. Records use the same
LPTMlayout, the same column widths and the sameSIZE,WRAPPERandJVMroll modes, so scripts that parsewrapper.logdo not need changes. - Launchers. A configuration that names the original
SimpleApp,StartStopApporJarApplauncher inwrapper.java.mainclassstarts with the equivalent bundled launcher; the log records the substitution. - Supervision. Start-up, ping and shutdown timeouts, restart throttling, exit-code actions, output filters (restart, shutdown, dump, GC, pause, resume), pause and resume.
- Diagnostics. Thread dumps through
-d, control code 255 or CTRL_BREAK; if the JVM runs with-Xrs, ajcmdbased thread dump instead. On-demand HPROF heap dumps through--heapdumpor control code 254. Each mechanism is detected separately; an unavailable tool produces an error message, not a restart.
Unsupported wrapper.* properties are reported by name in the log and ignored only when ignoring them is safe. Properties whose name contains password, secret, token, key, credential or vault are redacted from the log and are not sent to the JVM.
The full property-by-property table is at https://jayyanez.github.io/java-service-steward/compatibility.html.
What is not compatible
- The original
wrapper.jarandwrapper.dllare not loaded. Java Service Steward only works with its own JAR. - The original Java API is not implemented. An application that imports it has to switch to the project's
StewardandServiceListenerclasses (start, stop, restart, log, control events, start wait hints). Applications that use one of the launchers without touching the API need no source change. - No JMX, no named-pipe backend, no syslog.
- Features that exist only in the Standard or Professional editions of the original are not there.
I built the project without reading the original's source code and without copying its documentation. The interface facts come from the public property and command reference, from my own configuration files and logs, and from observing behaviour from the outside.
Migrating
- Replace
wrapper.exeandwrapper.jarin the installation directory. - Run
wrapper.exe -c wrapper.confonce in a console and read the warnings about unsupported properties. - Start the service as usual.
wrapper.conf and the service registration stay as they are. Going back is copying the two old files over again.
How it is built
The supervisor is a single thread running a crossbeam select! loop over the JVM's output, Service Control Manager requests, protocol events from a reader thread and a 50 ms tick for timeouts. Output lines are capped at 64 KiB. The JVM runs in a Job Object with kill-on-close, so if the host process dies, the JVM and its child processes die with it. The control socket is bound to loopback and the JVM has to present a key it receives on its command line before the host accepts lifecycle messages.
CI runs on Windows with Temurin 8, 21 and 25 and starts real JVMs in the integration tests. Releases are built on GitHub Actions and carry a CycloneDX SBOM and Sigstore provenance attestations, which you can check with gh attestation verify. The executable is not Authenticode-signed yet.
Status
The current version is 0.3.2, so this is pre-1.0. The configuration format, command line, log format and supervision behaviour are meant for production; the Rust and Java APIs may still change between minor versions, and every incompatible change is listed in the changelog.
If you have a wrapper.conf that does not behave the same way under Java Service Steward, that is the most useful issue you can open.
Where to get it
- Releases (zip with
wrapper.exe,wrapper.jar, licences and an example configuration): https://github.com/jayyanez/java-service-steward/releases - crates.io: https://crates.io/crates/java-service-steward.
cargo install java-service-stewardbuildswrapper.exefrom source;wrapper.jarcomes from the release zip or fromscripts/build-java-bridge.ps1with a JDK onPATH. - winget: the package
JayYanez.JavaServiceStewardhas been submitted to the community repository and is waiting for moderator approval. Once it is merged,winget install JayYanez.JavaServiceStewardunpacks the same two files; installing the service is stillwrapper.exe -i wrapper.conf. - Documentation: https://jayyanez.github.io/java-service-steward/
- Repository: https://github.com/jayyanez/java-service-steward
This article was originally published by DEV Community and written by Jay Yanez.
Read original article on DEV Community