JavaServiceWrapper将java程序设置为服务
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
JavaServiceWrapper将java程序设置为服务
有时候我们希望我们java写的程序作为服务注册到系统中,Java Service Wrapper(下⾯简称wrapper)是⽬前较为流⾏的将Java程序部署成Windows服务的解决⽅案,本⽂将讨论如何使⽤wrapper把我们的程序打包成WIN服务!
主要作⽤有:
1.打包服务
2.设置JVM参数
3.所有的⽇志可以输出到指定⽂件
0.准备需要注册为服务的程序
public class MapTest {
private static int i;
public static void main(String[] args) {
while (true) {
try {
System.out.println("访问次数:" + i++);
HttpUtil.doGet("/qlqwjy/");
Thread.sleep(2 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
上⾯程序依赖的jar包:
将上⾯程序也打成包:(使⽤eclipse打包或者直接Jdk⾃带的jar打包)
1.下载serviceWrapper包
下载后是⼀个压缩包,解压⽬录如下:
2.开始注册⼀个简单的服务:
1. 准备⼀个⽬录,例如我在桌⾯建了⼀个SW⽬录,并在⾥⾯新建如下结构的⽬录: 接下来全⽂的%EXAMPLE_HOME% 就是我新建的SW⽬录名称
%EXAMPLE_HOME%\
%EXAMPLE_HOME%\bin\
%EXAMPLE_HOME%\conf\
%EXAMPLE_HOME%\lang\
%EXAMPLE_HOME%\lib\
%EXAMPLE_HOME%\mylib\
%EXAMPLE_HOME%\logs\
如下:lang⽬录是存放⽀持其他语⾔的语⾔包,⼀般⽤不到
2. 然后将我们下载的wrapper⽬录下的⽂件拷贝到我们上⾯建的⽬录:
%WRAPPER_HOME%\bin\wrapper.exe -> %EXAMPLE_HOME%\bin\wrapper.exe
%WRAPPER_HOME%\lib\wrapper.jar -> %EXAMPLE_HOME%\lib\wrapper.jar
%WRAPPER_HOME%\lib\wrapper.dll -> %EXAMPLE_HOME%\lib\wrapper.dll
%WRAPPER_HOME%\conf\wrapper.conf -> %EXAMPLE_HOME%\conf\wrapper.conf
将⾃⼰程序打成的包以及⾃⼰程序依赖的包放到mylib:
3.修改配置⽂件 %EXAMPLE_HOME%\conf\wrapper.conf
#java.exe所在位置
mand=C:\Program Files\Java\jdk1.7.0_80\bin\java.exe
#⽇志级别
mand.loglevel=INFO
#主类⼊⼝,第⼀个mainClass是固定写法,是wrapper⾃带的,不可以写成⾃⼰的,如果写成⾃⼰的⼊⼝程序⾃⼰的程序需要实现wrapper的WrapperListener接⼝
#parameter.1是⾃⼰的主程序⼊⼝所在类(从包名开始)
wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp
wrapper.app.parameter.1=MapTest
#依赖的包,第⼀个是wrapper包,第⼆个是⾃⼰打的包以及程序依赖包
wrapper.java.classpath.1=../lib/wrapper.jar
wrapper.java.classpath.2=../mylib/*.jar
#固定写法,依赖的wrapper的包
wrapper.java.library.path.1=../lib
#⽇志⽂件位置
wrapper.logfile=../logs/wrapper.log
#服务名称以及描述信息
wrapper.console.title=Hello World Server
=helloworldserver
wrapper.displayname=Hello World Server
wrapper.description=Hello World Server
注意:
(1)上⾯的主类实际是:org.tanukisoftware.wrapper.WrapperSimpleApp,此类实现了WrapperListener接⼝。
所以如果我们⽤此参数定义⾃⼰的主函数需要实现此接⼝。
实现此接⼝就不⽤wrapper.app.parameter.1作为函数参数了
(2)wrapper.app.parameter.1=MapTest 是将Maptest作为参数传⼊到主函数中,也就是依次作为类WrapperSimpleApp的main(String[] args)函数的参数。
源码如下:
(3)不能⼀次传多个参数,⽣效的始终是第⼀个参数,传第⼆个参数也不会⽣效。
传第⼆个参数或者多个参数是作为MapTest的主函数的参数。
package org.tanukisoftware.wrapper;
import ng.reflect.InvocationTargetException;
import ng.reflect.Method;
import ng.reflect.Modifier;
import org.tanukisoftware.wrapper.WrapperListener;
import org.tanukisoftware.wrapper.WrapperManager;
import org.tanukisoftware.wrapper.WrapperPrintStream;
import org.tanukisoftware.wrapper.WrapperSystemPropertyUtil;
public class WrapperSimpleApp implements WrapperListener, Runnable {
private static WrapperPrintStream m_outInfo;
private static WrapperPrintStream m_outError;
private static WrapperPrintStream m_outDebug;
private Method m_mainMethod;
private String[] m_appArgs;
private boolean m_mainStarted;
private boolean m_mainComplete;
private Integer m_mainExitCode;
private boolean m_ignoreMainExceptions;
private boolean m_startComplete;
protected WrapperSimpleApp(String[] args) {
if (class$org$tanukisoftware$wrapper$WrapperManager == null) {
class$org$tanukisoftware$wrapper$WrapperManager = class$("org.tanukisoftware.wrapper.WrapperManager");
} else {
Class arg9999 = class$org$tanukisoftware$wrapper$WrapperManager;
}
this.m_mainMethod = null;
m_outInfo = new WrapperPrintStream(System.out, "WrapperSimpleApp: ");
m_outError = new WrapperPrintStream(System.out, "WrapperSimpleApp Error: ");
m_outDebug = new WrapperPrintStream(System.out, "WrapperSimpleApp Debug: ");
if (args.length < 1) {
this.showUsage();
WrapperManager.stop(1);
} else {
String mainClassString = args[0];
String mainMethodString = "main";
String[] ar = args[0].split("/");
if (ar.length > 1) {
mainClassString = ar[0];
mainMethodString = ar[1];
}
Class mainClass;
try {
mainClass = Class.forName(mainClassString);
} catch (ClassNotFoundException arg11) {
m_outError.println(WrapperManager.getRes().getString("Unable to locate the class {0} : {1}",
mainClassString, arg11));
this.showUsage();
WrapperManager.stop(1);
return;
} catch (ExceptionInInitializerError arg12) {
m_outError.println(WrapperManager.getRes()
.getString("Class {0} found but could not be initialized due to:", mainClassString));
arg12.printStackTrace(m_outError);
WrapperManager.stop(1);
return;
} catch (LinkageError arg13) {
m_outError.println(WrapperManager.getRes()
.getString("Class {0} found but could not be initialized: {1}", mainClassString, arg13));
WrapperManager.stop(1);
return;
}
try {
this.m_mainMethod = mainClass.getMethod(mainMethodString, new Class[]{String[].class});
} catch (NoSuchMethodException arg9) {
try {
this.m_mainMethod = mainClass.getMethod(mainMethodString, new Class[0]);
} catch (NoSuchMethodException arg8) {
;
}
if (this.m_mainMethod == null) {
m_outError.println(WrapperManager.getRes().getString(
"Unable to locate a public static {2} method in class {0} : {1}", mainClassString, arg9, mainMethodString));
this.showUsage();
WrapperManager.stop(1);
return;
}
} catch (SecurityException arg10) {
m_outError.println(WrapperManager.getRes().getString(
"Unable to locate a public static {2} method in class {0} : {1}", mainClassString, arg10, mainMethodString));
this.showUsage();
WrapperManager.stop(1);
return;
}
int modifiers = this.m_mainMethod.getModifiers();
if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)) {
String[] appArgs = new String[args.length - 1];
System.arraycopy(args, 1, appArgs, 0, appArgs.length);
WrapperManager.start(this, appArgs);
} else {
m_outError.println(WrapperManager.getRes().getString(
"The {1} method in class {0} must be declared public and static.", mainClassString,
mainMethodString));
this.showUsage();
WrapperManager.stop(1);
}
}
}
public void run() {
synchronized (this) {
this.m_mainStarted = true;
this.notifyAll();
}
Object t = null;
try {
if (WrapperManager.isDebugEnabled()) {
m_outDebug.println(WrapperManager.getRes().getString("invoking main method"));
}
try {
this.m_mainMethod.invoke((Object) null, new Object[]{this.m_appArgs});
} catch (IllegalArgumentException arg15) {
this.m_mainMethod.invoke((Object) null, new Object[0]);
} finally {
Thread.currentThread().setPriority(10);
}
if (WrapperManager.isDebugEnabled()) {
m_outDebug.println(WrapperManager.getRes().getString("main method completed"));
}
synchronized (this) {
this.m_mainComplete = true;
this.notifyAll();
return;
}
} catch (IllegalAccessException arg18) {
t = arg18;
} catch (IllegalArgumentException arg19) {
t = arg19;
} catch (InvocationTargetException arg20) {
t = arg20.getTargetException();
if (t == null) {
t = arg20;
}
}
m_outInfo.println();
m_outError.println(WrapperManager.getRes().getString("Encountered an error running main:")); ((Throwable) t).printStackTrace(m_outError);
synchronized (this) {
if (this.m_ignoreMainExceptions) {
if (!this.m_startComplete) {
this.m_mainComplete = true;
this.notifyAll();
}
} else if (this.m_startComplete) {
WrapperManager.stop(1);
} else {
this.m_mainComplete = true;
this.m_mainExitCode = new Integer(1);
this.notifyAll();
}
}
}
public Integer start(String[] args) {
boolean waitForStartMain = WrapperSystemPropertyUtil
.getBooleanProperty(WrapperSimpleApp.class.getName() + ".waitForStartMain", false);
this.m_ignoreMainExceptions = WrapperSystemPropertyUtil
.getBooleanProperty(WrapperSimpleApp.class.getName() + ".ignoreMainExceptions", false);
int maxStartMainWait = WrapperSystemPropertyUtil
.getIntProperty(WrapperSimpleApp.class.getName() + ".maxStartMainWait", 2);
maxStartMainWait = Math.max(1, maxStartMainWait);
int maxLoops;
if (waitForStartMain) {
maxLoops = Integer.MAX_VALUE;
if (WrapperManager.isDebugEnabled()) {
m_outDebug.println(WrapperManager.getRes()
.getString("start(args) Will wait indefinitely for the main method to complete."));
}
} else {
maxLoops = maxStartMainWait;
if (WrapperManager.isDebugEnabled()) {
m_outDebug.println(WrapperManager.getRes().getString(
"start(args) Will wait up to {0} seconds for the main method to complete.",
new Integer(maxStartMainWait)));
}
}
Thread mainThread = new Thread(this, "WrapperSimpleAppMain");
synchronized (this) {
this.m_appArgs = args;
mainThread.start();
Thread.currentThread().setPriority(10);
while (!this.m_mainStarted) {
try {
this.wait(1000L);
} catch (InterruptedException arg10) {
;
}
}
for (int loops = 0; loops < maxLoops && !this.m_mainComplete; ++loops) {
try {
this.wait(1000L);
} catch (InterruptedException arg9) {
;
}
if (!this.m_mainComplete) {
WrapperManager.signalStarting(5000);
}
}
this.m_startComplete = true;
if (WrapperManager.isDebugEnabled()) {
m_outDebug
.println(WrapperManager.getRes().getString("start(args) end. Main Completed={0}, exitCode={1}", new Boolean(this.m_mainComplete), this.m_mainExitCode));
}
return this.m_mainExitCode;
}
}
public int stop(int exitCode) {
if (WrapperManager.isDebugEnabled()) {
m_outDebug.println(WrapperManager.getRes().getString("stop({0})", new Integer(exitCode)));
}
return exitCode;
}
public void controlEvent(int event) {
if (event != 202 || !WrapperManager.isLaunchedAsService() && !WrapperManager.isIgnoreUserLogoffs()) {
if (WrapperManager.isDebugEnabled()) {
m_outDebug.println(WrapperManager.getRes().getString("controlEvent({0}) Stopping", new Integer(event))); }
WrapperManager.stop(0);
} else {
m_outInfo.println(WrapperManager.getRes().getString("User logged out. Ignored."));
}
}
protected void showUsage() {
System.out.println();
System.out.println(WrapperManager.getRes().getString("WrapperSimpleApp Usage:"));
System.out.println(WrapperManager.getRes().getString(
" java org.tanukisoftware.wrapper.WrapperSimpleApp {app_class{/app_method}} [app_arguments]"));
System.out.println();
System.out.println(WrapperManager.getRes().getString("Where:"));
System.out.println(WrapperManager.getRes()
.getString(" app_class: The fully qualified class name of the application to run."));
System.out.println(WrapperManager.getRes()
.getString(" app_arguments: The arguments that would normally be passed to the"));
System.out.println(WrapperManager.getRes().getString(" application."));
}
public static void main(String[] args) {
new WrapperSimpleApp(args);
}
}
4.开始注册服务以及测试
(1)控制台测试
C:\Users\Administrator>cd C:\Users\Administrator\Desktop\SW
C:\Users\Administrator\Desktop\SW>bin\wrapper.exe -c ..\conf\wrapper.conf
wrapper | --> Wrapper Started as Console
wrapper | Java Service Wrapper Community Edition 32-bit 3.5.25
wrapper | Copyright (C) 1999-2014 Tanuki Software, Ltd. All Rights Reserved.
wrapper |
wrapper |
wrapper | Launching a JVM...
wrapper | Java Command Line:
wrapper | Command: "C:\Program Files\Java\jdk1.7.0_80\bin\java.exe" -Djava.library.path="../lib" -classpath "../lib/wrapper.jar;../mylib/commons-logging-1.0.4.jar;../mylib/commons.jar;../my jvm 1 | WrapperManager: Initializing...
jvm 1 | WrapperManager:
jvm 1 | WrapperManager: WARNING - Unable to load the Wrapper''s native library 'wrapper.dll'.
jvm 1 | WrapperManager: The file is located on the path at the following location but
jvm 1 | WrapperManager: could not be loaded:
jvm 1 | WrapperManager: C:\Users\Administrator\Desktop\SW\bin\..\lib\wrapper.dll
jvm 1 | WrapperManager: Please verify that the file is both readable and executable by the
jvm 1 | WrapperManager: current user and that the file has not been corrupted in any way.
jvm 1 | WrapperManager: One common cause of this problem is running a 32-bit version
jvm 1 | WrapperManager: of the Wrapper with a 64-bit version of Java, or vica versa.
jvm 1 | WrapperManager: This is a 64-bit JVM.
jvm 1 | WrapperManager: Reported cause:
jvm 1 | WrapperManager: C:\Users\Administrator\Desktop\SW\lib\wrapper.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
jvm 1 | WrapperManager: System signals will not be handled correctly.
jvm 1 | WrapperManager:
jvm 1 | 访问次数:0
jvm 1 | log4j:WARN No appenders could be found for logger (org.apache.http.impl.conn.BasicClientConnectionManager).
jvm 1 | log4j:WARN Please initialize the log4j system properly.
jvm 1 | 访问次数:1
jvm 1 | 访问次数:2
jvm 1 | 访问次数:3
(2)将程序注册为服务:
bin\wrapper.exe -i ..\conf\wrapper.conf
结果:
wrapper | Hello World Server service installed.
(3)启动服务:
net start helloworld
或者:
bin\wrapper.exe -t ..\conf\wrapper.conf
启动之后我们回看到程序输出在logs\wrapper.log⽂件内:
(4)停⽌服务
net stop helloword
或者
bin\wrapper.exe -p ..\conf\wrapper.conf
(5)删除服务
sc delete helloword
或者
bin\wrapper.exe -r ..\conf\wrapper.conf
-----------上⾯是在系统有Java环境的情况下的设置,现在假设我们不存在Java运⾏环境,也就是没有JRE与JDK:-------------(1)拷贝java安装⽬录下的JRE(包含bin⽬录和相关lib)⽬录到上⾯的⽬录%EXAMPLE_HOME%,如下:
jre⽬录下:
(2)修改配置⽂件,利⽤我们上⾯的jre⽬录下的jar包和bin\java.exe
#java.exe所在位置
mand=../jre/bin/java.exe
#⽇志级别
mand.loglevel=INFO
#主类⼊⼝,第⼀个mainClass是固定写法,是wrapper⾃带的,不可以写成⾃⼰的,如果写成⾃⼰的⼊⼝程序⾃⼰的程序需要实现wrapper的WrapperListener接⼝wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp
#parameter.1是⾃⼰的主程序⼊⼝所在类(从包名开始)
wrapper.app.parameter.1=MapTest
#依赖的包,第⼀个是wrapper包,第⼆个是⾃⼰打的包以及程序依赖包
wrapper.java.classpath.1=../jre/lib/*.jar
wrapper.java.classpath.2=../lib/wrapper.jar
wrapper.java.classpath.3=../mylib/*.jar
#固定写法,依赖的wrapper的包
wrapper.java.library.path.1=../lib
#⽇志⽂件位置
wrapper.logfile=../logs/wrapper.log
#服务名称以及描述信息
wrapper.console.title=Hello World Server
=helloworldserver
wrapper.displayname=Hello World Server
wrapper.description=Hello World Server
(3)安装服务与测试与上⾯⼀样:
C:\Users\liqiang\Desktop\xxx\SW>bin\wrapper.exe -c ..\conf\wrapper.conf
wrapper | --> Wrapper Started as Console
wrapper | Java Service Wrapper Community Edition 32-bit 3.5.25
wrapper | Copyright (C) 1999-2014 Tanuki Software, Ltd. All Rights Reserved.
wrapper |
wrapper |
wrapper | Launching a JVM...
wrapper | Java Command Line:
wrapper | Command: "..\jre\bin\java.exe" -Djava.library.path="../lib" -classp
arsets.jar;../jre/lib/deploy.jar;../jre/lib/javaws.jar;../jre/lib/jce.jar;../jre
/lib/jsse.jar;../jre/lib/management-agent.jar;../jre/lib/plugin.jar;../jre/lib/r
apper.jar;../mylib/commons-logging-1.0.4.jar;../mylib/commons.jar;../mylib/httpc
r;../mylib/httpmime-4.3.1.jar;../mylib/log4j-1.2.12.jar" -Dwrapper.key="408rjGp1
.jvm.port.min=31000 -Dwrapper.jvm.port.max=31999 -Dwrapper.pid=336144 -Dwrapper.
y="wrapper" -Dwrapper.arch="x86" -Dwrapper.cpu.timeout="10" -Dwrapper.jvmid=1 or
p MapTest
jvm 1 | WrapperManager: Initializing...
jvm 1 | WrapperManager:
jvm 1 | WrapperManager: WARNING - Unable to load the Wrapper''s native librar
jvm 1 | WrapperManager: The file is located on the path at the foll
jvm 1 | WrapperManager: could not be loaded:
jvm 1 | WrapperManager: C:\Users\liqiang\Desktop\xxx\SW\bin\..\li
jvm 1 | WrapperManager: Please verify that the file is both readabl
jvm 1 | WrapperManager: current user and that the file has not been
jvm 1 | WrapperManager: One common cause of this problem is running
jvm 1 | WrapperManager: of the Wrapper with a 64-bit version of Jav
jvm 1 | WrapperManager: This is a 64-bit JVM.
jvm 1 | WrapperManager: Reported cause:
jvm 1 | WrapperManager: C:\Users\liqiang\Desktop\xxx\SW\lib\wrapp
MD 64-bit platform
jvm 1 | WrapperManager: System signals will not be handled correctl
jvm 1 | WrapperManager:
jvm 1 | 访问次数:0
jvm 1 | log4j:WARN No appenders could be found for logger (org.apache.http.im
jvm 1 | log4j:WARN Please initialize the log4j system properly.
jvm 1 | 访问次数:1
wrapper | CTRL-C trapped. Shutting down.
wrapper | <-- Wrapper Stopped
C:\Users\liqiang\Desktop\xxx\SW>bin\wrapper.exe -i ..\conf\wrapper.conf
wrapperm | Hello World Server service installed.
C:\Users\liqiang\Desktop\xxx\SW>java
'java' 不是内部或外部命令,也不是可运⾏的程序
或批处理⽂件。
C:\Users\liqiang\Desktop\xxx\SW>javac
'javac' 不是内部或外部命令,也不是可运⾏的程序
或批处理⽂件。
为了验证我们的服务是使⽤的jre⽬录下的JDK,我们可以将jre⽬录删掉进⾏测试,或者是将配置⽂件中jre\lib的引⼊注释掉进⾏测试。
现在我们将jre⽬录删掉,启动服务报错如下:
在wrapper.log中查看到的⽇志⽂件如下:
⾄此我们实现了简单的有JRE与⽆JRE两种情况的注册服务,实际没有JRE环境的时候我们只需要将我们的JRE附到⽬录中并且在wrapper.conf中指明所在路径即可。
补充1.:上⾯配置会导致JVM不断重启,需要加JVM参数以及设置,同时设置服务开机启动:并且使⽤⼀变量记住我们的项⽬路径;修改wrapper.conf并且删掉服务重新添加:
#定义了⼀个根路径,注意set和.之间没有空格,下⾯就可以⽤%basePath%取此变量
set.basePath=C:\Users\liqiang\Desktop\xxx\SW
#java.exe所在位置
mand=%basePath%/jre/bin/java.exe
#⽇志级别
mand.loglevel=INFO
#主类⼊⼝,第⼀个mainClass是固定写法,是wrapper⾃带的,不可以写成⾃⼰的,如果写成⾃⼰的⼊⼝程序⾃⼰的程序需要实现wrapper的WrapperListener接⼝wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp
#parameter.1是⾃⼰的主程序⼊⼝所在类(从包名开始)
wrapper.app.parameter.1=MapTest
#依赖的包,第⼀个是wrapper包,第⼆个是⾃⼰打的包以及程序依赖包
wrapper.java.classpath.1=../jre/lib/*.jar
wrapper.java.classpath.2=../lib/wrapper.jar
wrapper.java.classpath.3=../mylib/*.jar
#固定写法,依赖的wrapper的包
wrapper.java.library.path.1=../lib
#⽇志⽂件位置
wrapper.logfile=../logs/wrapper.log
#服务名称以及描述信息
wrapper.console.title=Hello World Server
=helloworldserver
wrapper.displayname=Hello World Server
wrapper.description=Hello World Server
wrapper.jmx=false
wrapper.on_exit.0=SHUTDOWN
wrapper.on_exit.default=RESTART
wrapper.ntservice.interactive = true
#服务开机启动
wrapper.ntservice.starttype=AUTO_START
wrapper.tray = true
wrapper.java.monitor.deadlock = true
wrapper.java.monitor.heap = true
wrapper.java.monitor.gc.restart = true
# Java Heap 初始化⼤⼩(单位:MB)
wrapper.java.initmemory=128
# Java Heap 最⼤值(单位:MB)
wrapper.java.maxmemory=128
C:\Users\liqiang\Desktop\xxx\SW>bin\wrapper.exe -r ..\conf\wrapper.conf
wrapperm | Hello World Server service removed.
C:\Users\liqiang\Desktop\xxx\SW>bin\wrapper.exe -c ..\conf\wrapper.conf
wrapper | --> Wrapper Started as Console
wrapper | Java Service Wrapper Community Edition 32-bit 3.5.25
wrapper | Copyright (C) 1999-2014 Tanuki Software, Ltd. All Rights Reserved. wrapper |
wrapper |
wrapper | Launching a JVM...
wrapper | Java Command Line:
wrapper | Command: "C:\Users\liqiang\Desktop\xxx\SW\jre\bin\java.exe" -Xms128
-classpath "../jre/lib/alt-rt.jar;../jre/lib/charsets.jar;../jre/lib/deploy.jar;
;../jre/lib/jfr.jar;../jre/lib/jfxrt.jar;../jre/lib/jsse.jar;../jre/lib/manageme
e/lib/resources.jar;../jre/lib/rt.jar;../lib/wrapper.jar;../mylib/commons-loggin
b/httpclient-4.3.1.jar;../mylib/httpcore-4.3.jar;../mylib/httpmime-4.3.1.jar;../
P7sqJIaMu25Avke" -Dwrapper.port=32000 -Dwrapper.jvm.port.min=31000 -Dwrapper.jvm rapper.version="3.5.25" -Dwrapper.native_library="wrapper" -Dwrapper.arch="x86"
id=1 org.tanukisoftware.wrapper.WrapperSimpleApp MapTest
jvm 1 | WrapperManager: Initializing...
jvm 1 | WrapperManager:
jvm 1 | WrapperManager: WARNING - Unable to load the Wrapper''s native librar
jvm 1 | WrapperManager: The file is located on the path at the foll
jvm 1 | WrapperManager: could not be loaded:
jvm 1 | WrapperManager: C:\Users\liqiang\Desktop\xxx\SW\bin\..\li
jvm 1 | WrapperManager: Please verify that the file is both readabl
jvm 1 | WrapperManager: current user and that the file has not been
jvm 1 | WrapperManager: One common cause of this problem is running
jvm 1 | WrapperManager: of the Wrapper with a 64-bit version of Jav
jvm 1 | WrapperManager: This is a 64-bit JVM.
jvm 1 | WrapperManager: Reported cause:
jvm 1 | WrapperManager: C:\Users\liqiang\Desktop\xxx\SW\lib\wrapp
MD 64-bit platform
jvm 1 | WrapperManager: System signals will not be handled correctl
jvm 1 | WrapperManager:
jvm 1 | 访问次数:0
wrapper | CTRL-C trapped. Shutting down.
jvm 1 | log4j:WARN No appenders could be found for logger (org.apache.http.im
jvm 1 | log4j:WARN Please initialize the log4j system properly.
wrapper | <-- Wrapper Stopped
C:\Users\liqiang\Desktop\xxx\SW>bin\wrapper.exe -i ..\conf\wrapper.conf
wrapperm | Hello World Server service installed.
如果我们想检测JVM参数可以⽤jps+jmap监测即可:
C:\Users\liqiang>jps
505668 Jps
504320 WrapperSimpleApp
487768
C:\Users\liqiang>jmap -heap 504320
Attaching to process ID 504320, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.80-b11
using thread-local object allocation.
Parallel GC with 4 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 134217728 (128.0MB)
NewSize = 1310720 (1.25MB)
MaxNewSize = 17592186044415 MB
OldSize = 5439488 (5.1875MB)
NewRatio = 2
SurvivorRatio = 8
PermSize = 21757952 (20.75MB)
MaxPermSize = 85983232 (82.0MB)
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 34603008 (33.0MB)
used = 9710016 (9.26019287109375MB)
free = 24892992 (23.73980712890625MB)
28.06119051846591% used
From Space:
capacity = 5242880 (5.0MB)
used = 0 (0.0MB)
free = 5242880 (5.0MB)
0.0% used
To Space:
capacity = 5242880 (5.0MB)
used = 0 (0.0MB)
free = 5242880 (5.0MB)
0.0% used
capacity = 89653248 (85.5MB)
used = 0 (0.0MB)
free = 89653248 (85.5MB)
0.0% used
PS Perm Generation
capacity = 22020096 (21.0MB)
used = 6630336 (6.32318115234375MB)
free = 15389760 (14.67681884765625MB)
30.110386439732142% used
3336 interned Strings occupying 269976 bytes.
补充2:我们可以⽤上⾯的service wrapper的bin包中的bat⽂件进⾏安装服务: (将上⾯安下载解压后的wrapper-windows-x86-32-3.5.25\bin中的⽂件复制到我们的%EXAMPLE_HOME%\bin⽬录下)
我们只需要点击上⾯的bat⽂件即可实现上⾯的操作。
*************************
下载解压之后只需要将⾃⼰程序打的包以及依赖包放到mylib⽬录下,修改conf\wrapper.conf⽂件中下⾯两处
set.basePath=C:\Users\liqiang\Desktop\xxx\SW #替换为⾃⼰的⽬录
#parameter.1是⾃⼰的主程序⼊⼝所在类(从包名开始)
wrapper.app.parameter.1=MapTest #替换为⾃⼰的程序⼊⼝
然后点击bin⽬录的TestWrapper.bat测试即可
**************************
3.将log4j⽇志与servicewrapper⽇志进⾏整合
开发环境下⼀切正常。
⽤JavaServiceWrapper部署到服务器上之后,发现log⽂件没有⽣成。
同时在wrapper的log中有两⾏log4j的错误信息:
log4j:WARN No appenders could be found for logger (com.xxxxx).
log4j:WARN Please initialize the log4j system properly.
查找了⼀番,最后发现在wrapper.conf中加⼊⼀⾏,硬性指明log4j的配置⽂件就OK了:
wrapper.java.additional.1=-Dlog4j.configuration=file:../conf/log4j.properties
StackOverflow上有⼈回答类似的问题,⽤的⽅法是
wrapper.java.additional.1=-Dlog4j.configuration=../config/log4j.properties
但是我这样测试没成功。
不知道是不是和版本有关。
(1) 测试代码:
package serviceWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MapTest {
private static Logger log = LoggerFactory.getLogger(MapTest.class);
public static void main(String[] args) {
int times = 0;
while (true) {
try {
Thread.sleep(3 * 1000);
} catch (InterruptedException e) {
}
try {
int i = 1 / 0;
} catch (Exception e) {
log.error("error[{}] by / 0 ", times++, e);
}
}
}
}
(2)测试代码打成包并⼀起复制到mylib⽬录下:
依赖的jar包以及⾃⼰打的包:
(3)⽬录结构:
(4)bin⽬录与上⾯⼀样,jre也⼀样,lang也⼀样,lib也⼀样,logs也⼀样,mylib在(2)中换过,将log4j.properties⽂件复制到conf⽬录下:
log4j.properties⽂件:
log4j.rootLogger=info,A,B
log4j.appender.A=org.apache.log4j.ConsoleAppender
yout=org.apache.log4j.PatternLayout
yout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n
log4j.appender.B=org.apache.log4j.RollingFileAppender
log4j.appender.B.File=E:\\test.log
log4j.appender.B.MaxFileSize=10MB
log4j.appender.B.MaxBackupIndex=5
yout=org.apache.log4j.PatternLayout
yout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n
(5)修改wrapper.conf⽂件:
#定义了⼀个根路径,注意set和.之间没有空格,下⾯就可以⽤%basePath%取此变量
set.basePath=C:\Users\liqiang\Desktop\logTest
#java.exe所在位置
mand=%basePath%/jre/bin/java.exe
#主类⼊⼝,第⼀个mainClass是固定写法,是wrapper⾃带的,不可以写成⾃⼰的,如果写成⾃⼰的⼊⼝程序⾃⼰的程序需要实现wrapper的WrapperListener接⼝wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp
#parameter.1是⾃⼰的主程序⼊⼝所在类(从包名开始),⽣效的始终是第⼀个参数
wrapper.app.parameter.1=serviceWrapper.MapTest
wrapper.app.parameter.2=MapTest
# Java Classpath配置,必须从序号"1"开始,添加新的jar包后序号递增
#JRE的包
wrapper.java.classpath.1=../jre/lib/*.jar
#wrapper.jar
wrapper.java.classpath.2=../lib/wrapper.jar
#⾃⼰的包以及程序依赖包
wrapper.java.classpath.3=../mylib/*.jar
#固定写法,依赖的wrapper的包
wrapper.java.library.path.1=%basePath%/lib
#⽇志⽂件位置
wrapper.logfile=../logs/wrapper.log
# 控制台信息输出格式
wrapper.console.format=PM
# ⽇志⽂件输出格式
wrapper.logfile.format=LPTM
# ⽇志⽂件⽇志级别
wrapper.logfile.loglevel=INFO
#服务名称以及描述信息
wrapper.console.title=Hello World Server
=helloworldserver
wrapper.displayname=Hello World Server
wrapper.description=Hello World Server
wrapper.jmx=false
wrapper.on_exit.0=SHUTDOWN
wrapper.on_exit.default=RESTART
wrapper.ntservice.interactive = true
#服务开机启动
wrapper.ntservice.starttype=AUTO_START
wrapper.tray = true
wrapper.java.monitor.deadlock = true
wrapper.java.monitor.heap = true
wrapper.java.monitor.gc.restart = true
# Java Heap 初始化⼤⼩(单位:MB)
wrapper.java.initmemory=128
# Java Heap 最⼤值(单位:MB)
wrapper.java.maxmemory=128
# 32/64位选择,true为⾃动选择
wrapper.java.additional.auto_bits=TRUE
#附加参数即为java命令可选参数,如下所⽰:
#设置log4J⽇志⽂件位置
wrapper.java.additional.1=-Dlog4j.configuration=file:../conf/log4j.properties
注意: 附加参数 wrapper.java.additional.1即为java命令可选参数(可⽤于指定JVM参数与指定垃圾收集器组合),如下所⽰:
C:\Users\liqiang>java
⽤法: java [-options] class [args...]
(执⾏类)
或 java [-options] -jar jarfile [args...]
(执⾏ jar ⽂件)
其中选项包括:
-d32 使⽤ 32 位数据模型 (如果可⽤)
-d64 使⽤ 64 位数据模型 (如果可⽤)
-server 选择 "server" VM
-hotspot 是 "server" VM 的同义词 [已过时]
默认 VM 是 server.
-cp <⽬录和 zip/jar ⽂件的类搜索路径>
-classpath <⽬录和 zip/jar ⽂件的类搜索路径>
⽤ ; 分隔的⽬录, JAR 档案
和 ZIP 档案列表, ⽤于搜索类⽂件。
-D<名称>=<值>
设置系统属性
-verbose:[class|gc|jni]
启⽤详细输出
-version 输出产品版本并退出
-version:<值>
需要指定的版本才能运⾏
-showversion 输出产品版本并继续
-jre-restrict-search | -no-jre-restrict-search
在版本搜索中包括/排除⽤户专⽤ JRE
-? -help 输出此帮助消息
-X 输出⾮标准选项的帮助
-ea[:<packagename>...|:<classname>]
-enableassertions[:<packagename>...|:<classname>]
按指定的粒度启⽤断⾔
-da[:<packagename>...|:<classname>]
-disableassertions[:<packagename>...|:<classname>]
禁⽤具有指定粒度的断⾔
-esa | -enablesystemassertions
启⽤系统断⾔
-dsa | -disablesystemassertions
禁⽤系统断⾔
-agentlib:<libname>[=<选项>]
加载本机代理库 <libname>, 例如 -agentlib:hprof
另请参阅 -agentlib:jdwp=help 和 -agentlib:hprof=help
-agentpath:<pathname>[=<选项>]
按完整路径名加载本机代理库
-javaagent:<jarpath>[=<选项>]
加载 Java 编程语⾔代理, 请参阅 ng.instrument
-splash:<imagepath>
使⽤指定的图像显⽰启动屏幕
有关详细信息, 请参阅 /technetwork/java/javase/documentation
(6)点击bin⽬录下的TestWrapper.bat测试控制台:
logs\wrapper.log⽂件内容如下:
E:\test.log⽂件内容如下:
log4j⽣成的⽇志⽂件与wrapper.logs⽂件的内容⼏乎⼀样,只是格式不⼀样。
⾄此完成与log4j的整合,其实与log4j整合也简单,就是在配置⽂件下⾯加⼀⾏引⼊log4j.properties⽂件的位置
wrapper.java.additional.1=-Dlog4j.configuration=file:../conf/log4j.properties
4.将tomcat注册为服务:设置tomcat服务开机启动,还是在没有JRE的环境下进⾏:(公司集成部署系统可以采⽤这种⽅式) 1.新建⼀⽬录,解压⼀个全新的tomcat,在%TOMCAT%⽬录下新建⼀个servicewrapper⽬录:
2.将⾃⼰的项⽬解压之后放在webapps⽬录下(这⾥采⽤⽬录解压部署,参考:
3.与上⾯部署⼀样将所需要的⽂件拷贝到servicewrapper⽬录下:。