将Java程序转换为Windows服务 作者:IT168 seasky 2007-09-19

001-配置java服务在windows后台运行 使用 nssm 将jar包或者bat文件注册为 windows 后台服务。 阅读详情

【IT168 专稿】

一、概述

    现在Java语言越来越受到程序员的关注。和Java相关的应用也越来越多。虽然Java是跨平台语言,但在国内有很多的应用都是运行在Windows下的。尤其是一些服务类程序。而一般基于Java的服务类程序都是以控制台方式运行的。这样虽然很直接。但如果服务程序多了,显得很乱。而且要使其在系统启动时运行也比较麻烦。因此,本文将介绍一种可以将Java程序转换为Windows服务的方法。通过这种方法。可以使Java程序象Windows服务程序一样运行。下面就让我们来进行转换吧。

    一般有两种方法可以将Java程序转换为Windows服务:

    1. 使用Windows服务直接在同一个进程运行Java应用程序。(这种方法服务程序无法更好地控制Java程序)。

    2. 在Windows服务程序中建立一个java虚拟机实例(JVM),这个JVM实例和服务程序在同一个上下文中,而且JVM在Windows服务程序的控制之下。

    第一种方法虽然实现起来简单,但这种方法不能很好地控制Java程序。因此,本文使用了第二种方法来运行Java程序。本文将带领读者一步一步地实现所有的内核代码。在实现代码之前,我们需要很好地了解Windows服务和Java本地接口(JNI)的概念和API的使用。

二、使用JVM API模拟Java运行时

    由于Windows任务管理器将所有的Java进程都显示为"Java",因此,我们根本无法通过这种方式区分某一个Java进程。为了给每一个Java应用程序指定一个特殊的名子。我们需要使用JVM API来模拟Java运行时。

    下面先来看看Java运行时(也就是java.exe)在运行时需要些什么。当我们使用java <类名>来运行java程序时,java.exe从系统路径动态装载了一些DLL库。这些Dll如下:

 
1.       java/jdk/jre/bin/client/jvm.dll
这个dll提供了JVM所需要的API。一但我们建立了一个JVM,jvm.dll就会依次装载所需的Dll,这些Dll如下:

2. java/jdk/jre/bin/hpi.dll
3. java/jdk/jre/bin/verify.dll
4. java/jdk/jre/bin/java.dll
5. java/jdk/jre/bin/zip.dll

    下面是java.exe如何处理Dll的过程:
 
1. 装载JVM Dll。
2. 建立一个JVM。
3. 装载指定的Java类。
4. 调用main方法,也就是public static void main (String[] args)。

我们可以使用在jni.h中定义的JNI_CreateJavaVM方法来建立一个JVM实例。我们可
以在JDK的安装目录中找到jni.h。
 

    下面是一个简单的Java程序,在控制台中打印出"Hello World"。

下面是使用JNI来模拟java.exe的例子代码。在这里我们使用动态装载jvm.dll方法,而不是静态绑定jvm.lib。这样会更有弹性,如可以自由地选择java的版本。代码如下:
 
int InvokeMain() {
       JavaVM *vm;
       JavaVMInitArgs vm_args;
       JavaVMOption options[1];
       jint res;
       JNIEnv *env;
       jclass cls;
       jmethodID mid;
 
       options[0].optionString = CLASS_PATH;
       vm_args.version = JNI_VERSION_1_4;   // 设置JDK的版本
       vm_args.options = options;
       vm_args.nOptions = 1;
       vm_args.ignoreUnrecognized = JNI_FALSE;
 
       //装载jvm.dll
       HINSTANCE handle = LoadLibrary(RUNTIME_DLL);
       if( handle == 0) {
              printf("Failed to load jvm dll %s/n",
                     RUNTIME_DLL);
              return -1;
       }
    // 得到JNI_CreateJVM指针

       createJVM = (CreateJavaVM)GetProcAddress(handle,
                     "JNI_CreateJavaVM");
 
       res = createJVM(&vm, (void **)&env, &vm_args);
       if (res < 0) {
              printf("Error creating JVM");
              return -1;
       }
 
       // 装载指定的类
       cls = env->FindClass(CLASS_NAME);
       if(cls == 0) {
              printf("Exception in thread /"main/"
                     java.lang.NoClassDefFoundError: %s/n",
                            CLASS_NAME);
              return -1;
       }
       //得到main方法
       mid = env->GetStaticMethodID(cls, "main",
              "([Ljava/lang/String;)V");
       if(mid == 0) {
              printf("Exception in thread /"main/"
                     java.lang.NoSuchMethodError: main/n");
              return -1;
       }
 
    // 调用main方法(不传递参数)
       env->CallStaticVoidMethod(cls, mid, 0);
    // 如果程序抛出异常,打印它
       if(env->ExceptionCheck()) {
              env->ExceptionDescribe();
              return -1;
       }
       return 0;
}

    在装载com.test.Hello时,我们必须使用"/"分割符(如com/test/Hello)。还有我们需要理解JNI调用Java方法的格式。如,为了调用void main(String[] args)方法,格式为:([Ljava/lang/String;)V:,"["表示数组;"L<classname>;"描述一个Java对象,V表示这个方法返回void。我们可以从JNI规范得到更多的细节。本文不再详细描述。

   
package com.test; public class Hello{ public static void main(String[] args) { System.out.println("Hello World" ); } }
三、集成JNI和Windows服务API

    为了演示Windows服务的功能,我在这设计了一h个叫Dummy的Java类。这个类在main方法等待一个停止事件。并实现了shutdown方法,在这个方法里设置并调用了stop事件。这将保证main线程安全地退出。在Dummy类中还实现了shutdown钩子,这个钩子主要给java.exe使用。Dummy.java的代码如下:

    
import java.io.* ; public class Dummy { public static Dummy xyz = null; private boolean stopped = false; public static PrintWriter pw; public Dummy() throws IOException { pw = new PrintWriter(new OutputStreamWriter( new FileOutputStream("C://dummy.log")), true); } public void start() { pw.println("started"); while(!stopped) { synchronized(this) { try { wait(); } catch (InterruptedException ie) {} } } pw.println("stopped"); } public void stop() { pw.println("stopping"); synchronized(this) { stopped = true; notifyAll(); } try { Thread.sleep(1000); } catch(Exception ex){} } public static void main(String[] args) { try { xyz = new Dummy(); Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { pw.println("inside shutdown hook"); xyz.stop(); } }); xyz.start(); } catch (Exception ex) {} } public static void shutdown() { xyz.stop(); } }
典型的Windows服务(除了设备驱动服务外)是由服务控制管理器(SCM,也就是众所周知的services.exe进程)按着服务进程创建和管理的。一个单独的进程包含有多个服务。但在本文的例子中一个服务进程只包含一个JVM实例服务。

    我们可以使用如下的API在SCM中安装一个服务:
 
SC_HANDLE schSCManager = OpenSCManager(..),
SC_MANAGER_CREATE_SERVICE);
SC_HANDLE schService = CreateService(..)
 
也可以使用如下的API来卸载Windows服务程序:

SC_HANDLE schSCManager = OpenSCManager(.., SERVICE_ALL_ACCESS);
SC_HANDLE schService = OpenService( schSCManager, ..);
DeleteService(schService)

    为了启动服务,我们需要使用StartServiceCtrlDispatcher来注册ServiceMain函数。这个ServiceMain函数包含了我们的主要功能。在我们的例子中,就是InvokeMain函数。接下来,调用RegisterServiceCtrlHandler(SERVICE_NAME, ServiceHandler);,这个函数注册一个Handler,并从SCM接收响应的命令。为了防止由于JVM崩溃而导致整个服务瘫痪,我们在另外一个线程里调用InvokeMain方法。上面的程序被写在DummyService.cpp中,通过VS2005将其编译成DummyService.exe。上面的代码可以通过点击此处下载

    接下来我们使用如下的命令来安装、启动、停止以及卸载Windows服务:
 
DummyService /i   // 安装服务
net start DummyService    // 启动服务
net stop DummyService    // 停止服务
DummyService /u   // 卸载服务

    上面的程序只是使用了最小的配置。其实要想充分使用JNI,得需要使用很多参数。一般需要至少15至20个配置参数。下面是在定制满足我们需要的程序的配置参数:
 
1. Windows服务参数:
(1) 服务名
(2) 演示名
(3) 描述
     (4) 执行路径
(5) 启动类型(自动/手动)
(6) 在注册中被保存的参数
     (7) 工作目录
(8) 存在于每个进程的服务或在单进程中的许多服务
     (9) 和桌面交互的选项(如果服务有一个UI接口)
     (10) 登录用户名和密码(当使用用户帐号或本地系统帐号来运行服务时需要)

2. 和Java应用相关的参数:

(11) jvm.dll的路径
(12) JVM选项(-D, -X)
     (13) 类名
(14) 命令行参数
     (15) 关闭超时

3. 日志参数:

(16) 事件日志和文件日志
(17) 用于重定向输入、输出的参数

    我们可以根据具体的要求选择使用哪些参数。我们可以将这些参数保存在被推荐的注册表的位置:HKLM/System/CurrentControlSet/[Service Name]/Parameters. 中。
四、安全地退出Java程序

    我们首先调用System.exit(0)来退出程序。虽然这个方法同时调用了所有的shutdown钩子,也试着关闭JVM。但它在清除和用于和SCM建立的Windows服务通讯的管道时抛出异常。这些错误信息如下:

System error 109 has occurred.
     The pipe has been ended.
    因此,本文采用了更好的方式来关闭服务,也就是实现shutdown方法,并调用它。我建议在线程中使用public static void shutdown()方法(如果这个方法被实现的话),并设置一定的超时,如20秒。这将防止服务如果shutdown方法未返回而收到未响应的信息。但要保证这个超时比系统超时少,否则SCM将终止我们的服务进程。
 
Java程序到Windows可执行文件的转换工具 本文还有配套的精品资源,点击获取 简介:Jexecreator是一个将Java应用程序封装为Windows可执行文件(.exe)的工具,简化了程序分发并免去了用户安装Java运行环境的步骤。通过这个工具,开发者可以为用户提供无需额外依赖即可运行的程序,增强了用户体验并方便了软件的部署。 1. Java程序封装工具Jexecreator概述 简介 在众多软件... 阅读详情

相关推荐

Java应用程序转换为Windows可执行文件的实践指南

本文还有配套的精品资源,点击获取 简介:将Java程序打包为Windows平台下的.exe可执行文件,是一个解决Java程序在Windows系统上运行依赖Java环境限制的有效工具。本文将探讨使用exe4j等工具将Java程序转换为.exe文件的过程,包括设置主类、配置JRE路径、定制启动界面等关键步骤,同时分析了打包过程的优缺点,如用户便利性的提升以及文件大小和系统依赖性...

weixin_42576186的博客 807

如何将Java项目做成windows服务

部分内容转载于--作者:kevinlifeng java project  我说的是main方法作为程序入口的java工程 制作方案: 1,将Java项目打包成可执行jar文件,如果你用的是myeclipse可以直接导出可执行jar包,如果是eclipse你可以看下怎么导出或者百度 2,制作windowsservice 如下步骤讲解如何制作: 1  下载wrapper-wind

xs_00的博客 4740

将java程序做成windows系统服务

把可执行的jar文件如何做成win下的系统服务

java项目自启动方案——jar包做成服务(Windows版本)

需求: 公司做的很多项目都是属于客户端—服务器形式,在客户端部分运行了属于面向客户的项目jar包,客户端机器就不想服务器那样,经常会避免重启机器的情况,所有让我们的项目能自启动就是个必须的工作。 方案: 1、用.bat脚本,并将脚本文件生成快捷方式,放置在电脑的启动目录下 打开目录快捷键:win+R 输入 shell:startup 2、做成服务(推荐使用这个),电脑重启 服务也会重启 具体方法: 1、.bat脚本文件启动jar包 新建一个文本,编辑内容示例如下,修改文本文件保存格式为.bat, echo

qiaodaima0的博客 3万+

手把手教你将java程序安装成windows服务(源码+教程)

最近工作需要将java程序打包发布,并且能安装成windows服务,而且需要在没有安装jre的机器上运行。研究了一下java service wrapper,在网上找了相关的资料,但是都说得不是很详细,照着做有一定难度。所以我分步总结了一下,做了一个小例子,希望给遇到相同问题的同仁一点帮助。

Java程序快速转换为windows服务运行

Java程序快速转换为windows服务运行

Java程序(jar包)注册为Windows系统服务

不会打jar包的看我上一篇文章。Java程序(jar包)注册为Windows系统服务

zxyhj的博客 2005

SAP FICO 消息号 FAA_POST042 技术清算科目中的余额:分类账 0L,货币 00、RMB、10000.00-

SAP FICO 消息号 FAA_POST042 技术清算科目中的余额:分类账 0L,货币 00、RMB、10000.00-

我好像病了的博客 2142

java程序做成windows服务

1、使用已经过封装的iaservice.exe 将Java程序做成windows服务: 2、iaservice.exe 默认配置文件iaservice.xml,注意:iaservice.exe和iaservice.xml必须放在同一文件夹下; 3、iaservice.exe 下载地址 iaservice.xml 文件配置如下: <configuration> <id...

wutongyuWxc的博客 1430

使用python对创芯科技CANalyst-II分析仪进行二次开发(详细教程)

使用python对创芯科技CANalyst-II分析仪进行二次开发

ningqingzy的博客 1万+

基于555定时器的D类功放设计:从PWM原理到无反馈电路实践

D类功放(数字功放)是一种高效率的音频放大技术,其核心原理是脉冲宽度调制(PWM)。它将输入的模拟音频信号转换为一系列高速开关的脉冲,通过控制功率开关管(如MOSFET)的通断,再经低通滤波器还原放大后的音频。相比传统AB类功放,其转换效率通常超过90%,显著降低了热能损耗。这项技术在追求高能效和小型化的现代音频设备中价值凸显,广泛应用于有源音箱、汽车音响和便携式设备。本文聚焦于一种独特的实现方案:以经典的555定时器芯片为核心,构建一个无整体负反馈的D类功放。通过剖析其PWM调制器、FET电压-电流转换级

weixin_30162121的博客 226

将JAVA程序做成WINDOWS服务的方法

有很多时间需要将JAVA的SERVER程序放在WINDOWS平台上,有很多时候JAVA程序以WINDOWS中的命令提示符模式运行,还有很多时候,如果不小心点到命令提示符模式的黑黑的窗口内容,会将这个窗口变成“选中”状态,将JAVA程序此时将暂停运行!还有很多的原因,我们希望把JAVA程序变成WINDOWS后台运行,在启动时自动启动的WINDOWS服务。在反复经受过几次这种需求后,我发现了一个比较简

guyu520的专栏 1437

基于因果推理的LLM去毒:精准定位注意力头实现高效干预

在大型语言模型(LLM)的部署与应用中,模型安全与可控性是核心挑战之一。传统方法如全参数微调成本高昂,且可能损害模型通用能力。本文聚焦于一种基于因果推理的精准干预技术,其原理在于利用因果发现算法定位Transformer模型中与“毒性”输出存在强因果关联的特定注意力头。该技术通过分析注意力头的激活模式与生成文本毒性分数之间的因果关系,识别出关键责任单元,而非依赖传统的相关性分析。其技术价值在于实现了轻量级、高可解释性的模型行为修正,能以极低的参数改动代价有效降低模型在敏感话题上的有害输出。在应用场景上,该方

weixin_32667439的博客 315

java系统服务_java程序在windows系统作为服务程序运行

Java程序很多情况下是作为服务程序运行的,在Un*x 平台下可以利用在命令后加“&”把程序作为后台服务运行,但在Windows下看作那个Console窗口在桌面上,你是否一直担心别的同时把你 的Console窗口关闭?是否怀念用VC写的Win32服务程序?翻开JBOSS、Tomcat的发布包,发现他们都使用了一个Open source——Java Service Wrapper。用Jav...

weixin_34125314的博客 448

聚类技术:发展历史、主要分类与重要论文解析

在数据挖掘和机器学习的广袤领域中,聚类作为一种强大的无监督学习技术,一直扮演着至关重要的角色。它能够帮助我们从海量的数据中发现隐藏的模式和结构,将相似的数据对象归为一类,从而为进一步的分析和决策提供有价值的信息。

qq_48131648的博客 2631

将Java程序注册成系统服务

试试Java Service Wrapper这个工具吧,你可以从这个网站上面下载你喜欢的版本:http://wrapper.tanukisoftware.org/ ,Java Service Wrapper提供了适合市面上流行的操作系统的版本。 使用Wrapper将Java程序注册成系统服务有三种方式可供选择: 第一种是使用WrapperSimpleApp 这个帮助类来运行你的程序

ligiwen1的博客 1073

PoP(Package on Package)封装技术探讨

PoP(Package on Package)封装技术摘要 PoP是一种3D封装技术,通过垂直堆叠已完成封装的器件(如SoC+DRAM)实现高密度集成,典型应用于智能手机等空间受限场景。其核心优势包括:节省主板面积(垂直堆叠)、优化高速信号完整性(短互连路径)、提升供应链灵活性(独立测试与选型)。PoP结构分为底封装(通常为Flip-Chip BGA的SoC)和顶封装(如FBGA存储芯片),通过焊球阵列互连,一次回流焊完成组装。

sinat_15150363的博客 376

如何把JAVA程序做成Windows服务,并开机运行

怎么把jar文件做成系统服务,比较多的解决方案是使用 wrapper-windows 这个软件包。这个软件包的强大之处是能把jre环境也给打进去,这个服务可以正常运行在根本没有jre环境即就没有安装JDK的机器上。 1 下载wrapper-windows-x86-32-3.2.3版本,并解压。里面包含 bin, conf ,doc, jdoc lib, logs, src 7个文件夹。

qq_17839177的博客 2538

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Java程序 注册为 Windows 服务

(1)制作WINDOWS EXE程序       java做成window的exe程序或者服务程序实在是吃饱撑的,有点变态,但是如果你不想起在一台服务器的后台程序,被哪个笨蛋不小心给关了,或者人家把进程中的java给杀了,那就有必要照着下面我说的方法去做了:      borland不公开的一个使用技巧,能够通过jbuilder来制作exe文件来启动java文件。jbuilder并不支...

yanguz的专栏 896

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

把java类变成 Windows NT服务的3中方法(使用 Java Serivce Wrapper)

最近制作小叮咚的时候,需要机器启动后自动运行小叮咚 , 所以就想仿照Tomcat那样把java类变成一个服务来运行.于是找到了 Java Service Wrapper .下面就是一些我要用到的地方.把java类变成 Windows NT服务的3中方法(使用 Java Serivce Wrapper) 集成 Java Service Wrapper 的三种方法:1 使用 WrapperSimple

我要去桂林-田春峰 3779

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

使java程序变成windows service

Java编写服务的准备1、作为本地化的实现,实现NT服务的Java程序当然不是100%纯Java,单靠标准类库是无法实现我们的编写NT服务的目的,所以MS提供了一套SDK for Java(本文采用的是Microsoft SDK for Java 4.0),提到了如何利用MS提供的扩展类库和相应的工具,实现符合Windows平台需要的程序。其中包括了实现NT服务的所需要的类库API框架以及将J

1397

【无标题】java程序作为Windows服务

该工具必须定期运行,因此它是一项服务的主要候选对象(即使公务员完全忘记这项任务,这也将使上传成为可能,此外,重复的手动上传是浪费时间)。在我的例子中,长时间运行的部分是一个预定的执行器,但是它也可以运行一个服务于web接口的jetty服务。尽管有许多关于这个主题的帖子和stackoverflow答案,但我仍然花了很多时间,因为一些小的警告和一个很少有人拥有的重要先决条件——拥有一个捆绑的JRE,这样就没有人需要下载和安装JRE(这会不必要地使安装过程变得复杂,并且目标受众不一定精通技术)。

dwrfff的博客 709

java生成windows服务_如何从java应用程序创建windows服务

慕仰8121524带着ApacheCommonsDaemon您现在可以有一个自定义的可执行文件名和图标!您也可以得到一个自定义Windows托盘显示器与您自己的名字和图标!我现在使用自己的名字和图标(prunsrv.exe)运行我的服务,系统托盘监视器(prunmgr.exe)也有我自己的自定义名称和图标!下载ApacheCommonsDaemon二进制文件(您需要prunsrv.exe和prun...

weixin_32073733的博客 310

java系统服务_把你做的Java程序变成Windows系统服务。

最近买了一台机器做个source服务器和异地的几个朋友一起做点东西玩玩。但是由于用的是电信的ADSL,所以地址是动态的,每天机器自动重起的时候就会变化。于是我就用3322的域名绑定,但是3322提供的windows更新dns的客户端运行时不是作为系统服务运行的,所以没有用户登录时它是没有运行的,所以还是没有解决问题。后来下了一个Windows Resource Kit Tools(这个工具wind...

weixin_39673002的博客 293
上一篇: java存储过程调用(sqlsever数据库)
下一篇: 在static块和static方法中如何获取当前类及如何获取当前正在执行的方法
javaokay
博客等级 码龄20年 6粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值