将Java代码打包为exe文件

豆豆网   技术应用频道   2008年01月09日    社区交流

内容摘要:现在有很多的工具将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;
}

作者:晏斐    责编:豆豆技术应用

正在加载评论...