内容摘要:现在有很多的工具将Java代码打包为exe文件,执行时不需要再编写批处理文件,或者在命令行输入长长的classpath信息,为用户使用提供了很大的方便。这也是很多商业软件常常使用的方法。
现在有很多的工具将Java代码打包为exe文件,执行时不需要再编写批处理文件,或者在命令行输入长长的classpath信息,为用户使用提供了很大的方便。这也是很多商业软件常常使用的方法。
将Java代码打包为exe文件,一般需要两个步骤:
1. 编写本地代码,创建虚拟机,加载并执行Main Class。
2. 将Java代码打包为jar文件,并与本地代码exe文件合并。
下面的代码,会加载jvm.dll,并调用JNI_CreateJavaVM导出函数创建Java虚拟机,得到JNIEnv指针,然后调用FindClass查找Main Class,之后调用GetStaticMethodID方法得到main方法,并执行main方法。代码如下:
#include<windows.h>
#include<jni.h>
//#pragmacomment(linker,"/subsystem:"console"/entry:"mainCRTStartup"")
#pragmacomment(linker,"/subsystem:"windows"/entry:"WinMainCRTStartup"")
typedefjint(JNICALL*JNICREATEPROC)(JavaVM**,void**,void*);
boolsetStream(JNIEnv*env,constchar*pszFileName,constchar*pszMethod);
//启动java虚拟机方法
//boolmain(intargc,char*argv[])
intWINAPIWinMain(HINSTANCEhInst,HINSTANCEhPrevInstance,PSTRszCmdLine,intiCmdShow)
...{
//jvm动态库的路径
constcharszJvmPath[]="d:jdk1.5.0_07jreinserverjvm.dll";
//java虚拟机的启动参数,每个参数写一项,不能合在一起写
intnOptionCount=2;
JavaVMOptionoptions[2];
options[1].optionString="-Xmx256M";
//设置classpath
options[0].optionString="-Djava.class.path=./Test.exe";
JavaVMInitArgsvm_args;
vm_args.version=JNI_VERSION_1_4;
vm_args.options=options;
vm_args.nOptions=nOptionCount;
vm_args.ignoreUnrecognized=JNI_TRUE;
//启动类,注意分割符是/,例如启动类test.JTest应该写成test/JTest
constcharszStartClass[]="com/primeton/test/TestClass";
//启动方法,通常是main函数,你也可以设定成其他函数
constcharszStartMethod[]="main";
//重导向文件
constcharszStdoutFileName[]="stdout.txt";
constcharszStderrFileName[]="stderr.txt";
//java程序的命令行参数
intnParamCount=2;
constchar*szParams[2]=...{"arg1","arg2"};
//加载JVM。
HINSTANCEjvmDll=LoadLibrary(szJvmPath);
if(jvmDll==NULL)
...{
printf("加载JVM动态库错误。%l",::GetLastError());
returnfalse;
}
//查找JNI_CreateJavaVM过程。
JNICREATEPROCjvmCreateProc=(JNICREATEPROC)GetProcAddress(jvmDll,"JNI_CreateJavaVM");
if(jvmCreateProc==NULL)
...{
FreeLibrary(jvmDll);
printf("查找JNI_CreateJavaVM过程错误。%l",::GetLastError());
returnfalse;
}
//创建JVM。
JNIEnv*env;
JavaVM*jvm;
jintr=(jvmCreateProc)(&jvm,(void**)&env,&vm_args);
if(r<0||jvm==NULL||env==NULL)
...{
FreeLibrary(jvmDll);
printf("创建JVM发生错误。");
returnfalse;
}
//重导向stdout,stderr到输出文件
if(!setStream(env,szStdoutFileName,"setOut"))
...{
printf("设置stdout输出文件失败");
returnfalse;
}
if(!setStream(env,szStderrFileName,"setErr"))
...{
printf("设置stderr输出文件失败");
returnfalse;
}
//加载启动类。
jclassserviceClass=env->FindClass(szStartClass);
if(env->ExceptionCheck()==JNI_TRUE||serviceClass==NULL)
...{
env->ExceptionDescribe();
env->ExceptionClear();
FreeLibrary(jvmDll);
printf("加载启动类失败。");
returnfalse;
}
//启动方法
jmethodIDmid=env->GetStaticMethodID(serviceClass,szStartMethod,"([Ljava/lang/String;)V");
if(env->ExceptionCheck()==JNI_TRUE||mid==NULL)
...{
env->ExceptionDescribe();
env->ExceptionClear();
FreeLibrary(jvmDll);
printf("查找启动方法失败。");
returnfalse;
}
//查找String类。
jclassstringClass=env->FindClass("java/lang/String");
if(env->ExceptionCheck()==JNI_TRUE||stringClass==NULL)
...{
env->ExceptionDescribe();
env->ExceptionClear();
FreeLibrary(jvmDll);
printf("查找String类失败。");
returnfalse;
}
jstringjstr;
jobjectArrayargs=0;
args=env->NewObjectArray(2,stringClass,0);
for(inti=0;i<nParamCount;i++)
...{
jstr=env->NewStringUTF(szParams[i]);
if(jstr==0)...{
printf("分配String失败 ");
if(env->ExceptionOccurred())...{
env->ExceptionDescribe();
env->ExceptionClear();
}
returnfalse;
}
env->SetObjectArrayElement(args,i,jstr);
if(env->ExceptionCheck()==JNI_TRUE)
...{
printf("设置参数失败 ");
if(env->ExceptionOccurred())...{
env->ExceptionDescribe();
env->ExceptionClear();
}
returnfalse;
}
}
//调用启动类的启动方法启动Java程序
//env->CallStaticVoidMethod(serviceClass,mid,parameterArray);
env->CallStaticVoidMethod(serviceClass,mid,args);
if(env->ExceptionCheck()==JNI_TRUE)
...{
env->ExceptionDescribe();
env->ExceptionClear();
FreeLibrary(jvmDll);
returnfalse;
}
MSG msg;
while(GetMessage(&msg,NULL,0,0))
...{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
returntrue;
}
//设置输出流的方法
boolsetStream(JNIEnv*env,constchar*pszFileName,constchar*pszMethod)
...{
intpBufferSize=1024;
char*pBuffer=newchar[pBufferSize];
//创建字符串对象。
jstringpathString=env->NewStringUTF(pszFileName);
if(env->ExceptionCheck()==JNI_TRUE||pathString==NULL)
...{
env->ExceptionDescribe();
env->ExceptionClear();
printf("创建字符串失败。");
returnfalse;
}
//查找FileOutputStream类。
jclassfileOutputStreamClass=env->FindClass("java/io/FileOutputStream");
if(env->ExceptionCheck()==JNI_TRUE||fileOutputStreamClass==NULL)
...{
env->ExceptionDescribe();
env->ExceptionClear();
printf("查找FileOutputStream类失败。");
returnfalse;
}
//查找FileOutputStream类构造方法。
jmethodIDfileOutputStreamConstructor=env->GetMethodID(fileOutputStreamClass,"<init>","(Ljava/lang/String;)V");
if(env->ExceptionCheck()==JNI_TRUE||fileOutputStreamConstructor==NULL)
...{
env->ExceptionDescribe();
env->ExceptionClear();
printf("查找FileOutputStream类构造方法失败。");
returnfalse;
}
//创建FileOutputStream类的对象。
jobjectfileOutputStream=env->NewObject(fileOutputStreamClass,fileOutputStreamConstructor,pathString);
if(env->ExceptionCheck()==JNI_TRUE||fileOutputStream==NULL)
...{
env->ExceptionDescribe();
env->ExceptionClear();
printf("创建FileOutputStream类的对象失败。");
returnfalse;
}
//查找PrintStream类。
jclassprintStreamClass=env->FindClass("java/io/PrintStream");
if(env->ExceptionCheck()==JNI_TRUE||printStreamClass==NULL)
...{
env->ExceptionDescribe();
env->ExceptionClear();
printf("查找PrintStream类失败。");
returnfalse;
}
//查找PrintStream类构造方法。
jmethodIDprintStreamConstructor=env->GetMethodID(printStreamClass,"<init>","(Ljava/io/OutputStream;)V");
if(env->ExceptionCheck()==JNI_TRUE||printStreamConstructor==NULL)
...{
env->ExceptionDescribe();
env->ExceptionClear();
printf("查找PrintStream类构造方法失败。");
returnfalse;
}
//创建PrintStream类的对象。
jobjectprintStream=env->NewObject(printStreamClass,printStreamConstructor,fileOutputStream);
if(env->ExceptionCheck()==JNI_TRUE||printStream==NULL)
...{
env->ExceptionDescribe();
env->ExceptionClear();
printf("创建PrintStream类的对象失败。");
returnfalse;
}
//查找System类。
jclasssystemClass=env->FindClass("java/lang/System");
if(env->ExceptionCheck()==JNI_TRUE||systemClass==NULL)
...{
env->ExceptionDescribe();
env->ExceptionClear();
printf("查找System类失败。");
returnfalse;
}
//查找System类设置方法。
jmethodIDsetStreamMethod=env->GetStaticMethodID(systemClass,pszMethod,"(Ljava/io/PrintStream;)V");
if(env->ExceptionCheck()==JNI_TRUE||setStreamMethod==NULL)
...{
env->ExceptionDescribe();
env->ExceptionClear();
printf("查找System类设置方法失败。");
returnfalse;
}
//设置System类的流。
env->CallStaticVoidMethod(systemClass,setStreamMethod,printStream);
if(env->ExceptionCheck()==JNI_TRUE)
...{
env->ExceptionDescribe();
env->ExceptionClear();
printf("设置System类的流失败。");
returnfalse;
}
returntrue;
}
作者:晏斐 责编:豆豆技术应用
- 创建用户后 邮件地址无法及时显示的原因
- Exchange故障排错图解教程
- Exchange 2007的可用性服务
- 使用备份工具保护Exchange 2003
- exchange邮件系统的建立
- 使用移动设备连接Exchange Server 2007
- 教你七个走好IT技术之路的诀窍
- 非标准无线技术的应用优势分析
- 如何使用加密工具保证企业数据安全
- 解析Flash跨站脚本攻击