winsw 是 windows 服务包装器,使 java 等命令行程序能以原生服务运行;直接用 javaw.exe 无法注册为服务、不响应控制请求。

WinSW 是什么,为什么不是直接用 javaw.exe 启动
WinSW 不是 Java 打包工具,而是一个 Windows 服务包装器——它让任意命令行程序(包括 java.exe)能以原生 Windows 服务方式运行:开机自启、无窗口、受 SCM 管理、支持日志重定向和自动重启。直接用 javaw.exe 启动无法注册为服务,也没法响应服务控制请求(如停止、暂停),Windows 会把它当普通进程处理,一关机就丢。
常见错误现象:Failed to start service: The service did not respond to the start or control request in a timely fashion,多半是因为没配 executable 或主类路径写错,或 JVM 启动太慢没及时返回。
配置 winssw.xml 的关键字段怎么填
WinSW 读取同名的 winssw.xml(或 .yml)来定义服务行为。最易出错的是路径、类路径和 JVM 参数三处:
-
executable必须指向你本地的java.exe绝对路径,比如C:\Program Files\Java\jre1.8.0_361\bin\java.exe;相对路径或仅写java会失败 -
arguments里不要漏-cp或--class-path,JAR 包路径必须是绝对路径,且多个 JAR 用分号(;)隔开(Windows 下不能用冒号) -
serviceaccount默认是 LocalSystem,但若程序要访问网络共享或数据库,常需改成指定域用户,并提前在“本地安全策略→用户权限分配”中赋予Log on as a service权限 - 别忽略
logpath,不设的话日志默认写到%BASE%(即 XML 所在目录),而服务账户可能没写入权限,导致启动无声失败
示例片段:
立即学习“Java免费学习笔记(深入)”;
<service> <id>myapp</id> <name>My Java App</name> <executable>C:\jdk8\bin\java.exe</executable> <arguments>-Xms256m -Xmx512m -cp "D:\app\lib\*;D:\app\myapp.jar" com.example.Main</arguments> <logpath>D:\app\logs</logpath> </service>
安装/卸载服务时权限和路径的坑
WinSW 安装服务本质是调用 Windows SCM API,必须以管理员身份运行命令行——哪怕你已经是管理员组成员,也得右键“以管理员身份运行” CMD 或 PowerShell,否则报 Access is denied。
路径问题更隐蔽:
- XML 文件名必须和 WinSW 可执行文件名一致(如
myapp.exe对应myapp.xml),否则加载失败且无提示 - 所有路径(JAR、logpath、workingdirectory)推荐全用绝对路径,避免依赖当前工作目录;
workingdirectory设错会导致配置文件读不到、资源找不到 - 如果 Java 程序用了相对路径加载配置(如
config/app.properties),务必显式设workingdirectory指向该目录,否则服务启动后路径是C:\Windows\System32
安装命令就是:myapp.exe install,卸载是:myapp.exe uninstall;别手滑打成 myservice.exe install 却配了 myservice.xml ——名字不匹配就静默失败。
服务启动后 Java 进程消失或卡住怎么办
这不是 WinSW 崩溃,而是 JVM 启动流程没按预期完成。WinSW 要求主类的 main 方法不能立即退出,否则服务状态会变成 “Stopped”;同时它不接管标准输出,所以 System.out.println 不会显示在控制台,全靠日志文件。
排查重点:
- 检查
logpath下的myapp.wrapper.log,看是否报ClassNotFoundException或NoClassDefFoundError——通常是-cp漏了依赖 JAR 或路径有空格没加引号 - 如果日志停在 “Starting JVM...” 就不动,大概率是 JVM 参数有问题,比如
-Xmx4g但机器只有 2G 可用内存,或用了不兼容的 GC 参数(如-XX:+UseZGC在 JDK 8 下) - Java 主类必须是“长期运行”的,比如内嵌 Tomcat、Spring Boot 的
SpringApplication.run(),或者自己写个while(true) { Thread.sleep(60000); };千万别写完逻辑就 return
复杂点在于:WinSW 自身不解析 Java 异常堆栈,只记录 JVM 启动过程。真正的问题永远藏在 myapp.log(你的应用日志)或 myapp.wrapper.log 里,而不是 Windows 事件查看器。










