将Java代码打包为exe文件

将Java代码打包为exe文件

将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>
//#pragma comment( linker, "/subsystem:"console" /entry:"mainCRTStartup"" ) 
#pragma  comment( linker, "/subsystem:"windows" /entry:"WinMainCRTStartup"" ) 

typedef jint (JNICALL *JNICREATEPROC)(JavaVM **, 
void  **,  void  *);
bool  setStream(JNIEnv *env,  const  char * pszFileName,  const  char * pszMethod);
// 启动 java 虚拟机方法

//bool main(int argc,char *argv[])
int  WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInstance,PSTR szCmdLine,  int  iCmdShow)
... {
    
//jvm 动态库的路径
     const  char  szJvmPath[] = "d:/jdk1.5.0_07/jre/bin/server/jvm.dll";
    
    
//java  虚拟机的启动参数,每个参数写一项,不能合在一起写
     int  nOptionCount = 2;
    JavaVMOption options[2];
    options[1].optionString = "-Xmx256M";
    
    
// 设置 classpath
    options[0].optionString = "-Djava.class.path=./Test.exe";
    
    JavaVMInitArgs vm_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
     const  char  szStartClass[] = "com/primeton/test/TestClass";
    
    
// 启动方法,通常是 main 函数,你也可以设定成其他函数
     const  char  szStartMethod[] = "main";
    
    
// 重导向文件
     const  char  szStdoutFileName[] = "stdout.txt";
    
const  char  szStderrFileName[] = "stderr.txt";
    
    
//java 程序的命令行参数
     int  nParamCount = 2;
    
const  char  *szParams[2] =  ... {"arg1","arg2"};
    
    
// 加载 JVM
    HINSTANCE jvmDll = LoadLibrary(szJvmPath);
    
if  (jvmDll == NULL)
    
... {
        printf("
加载 JVM 动态库错误。 %l", ::GetLastError());
        
return  false ;
    }
    
    
// 查找 JNI_CreateJavaVM 过程。
    JNICREATEPROC jvmCreateProc = (JNICREATEPROC)GetProcAddress(jvmDll, "JNI_CreateJavaVM");
    
if  (jvmCreateProc == NULL)
    
... {
        FreeLibrary(jvmDll);
        printf("
查找 JNI_CreateJavaVM 过程错误。 %l", ::GetLastError());
        
return  false ;
    }
    
    
// 创建 JVM
    JNIEnv *env;
    JavaVM *jvm;
    jint r = (jvmCreateProc)(&jvm, (
void  **)&env, &vm_args);
    
if  (r < 0 || jvm == NULL || env == NULL)
    
... {
        FreeLibrary(jvmDll);
        printf( "
创建 JVM 发生错误。 ");
        
return  false ;
    }
    
    
// 重导向 stdout, stderr 到输出文件
     if  (!setStream(env, szStdoutFileName, "setOut"))
    
... {
        printf("
设置 stdout 输出文件失败 ");
        
return  false ;
    }
    
    
if  (!setStream(env, szStderrFileName, "setErr"))
    
... {
        printf("
设置 stderr 输出文件失败 ");
        
return  false ;
    }
    
    
// 加载启动类。
    jclass serviceClass = env->FindClass(szStartClass);
    
if  (env->ExceptionCheck() == JNI_TRUE || serviceClass == NULL)
    
... {
        env->ExceptionDescribe();
        env->ExceptionClear();
        FreeLibrary(jvmDll);
        printf("
加载启动类失败。 ");
        
return  false ;
    }
    
    
// 启动方法
    jmethodID mid = env->GetStaticMethodID(serviceClass, szStartMethod , "([Ljava/lang/String;)V");
    
if  (env->ExceptionCheck() == JNI_TRUE || mid == NULL)
    
... {
        env->ExceptionDescribe();
        env->ExceptionClear();
        FreeLibrary(jvmDll);
        printf("
查找启动方法失败。 ");
        
return  false ;
    }
    
    
    
    
// 查找 String 类。
    jclass stringClass = env->FindClass("java/lang/String");
    
if  (env->ExceptionCheck() == JNI_TRUE || stringClass == NULL)
    
... {
        env->ExceptionDescribe();
        env->ExceptionClear();
        FreeLibrary(jvmDll);
        
        printf("
查找 String 类失败。 ");
        
return  false ;
    }
    
    
    
    jstring jstr;
    jobjectArray args = 0;
    
    args = env->NewObjectArray(2, stringClass, 0);
    
for  ( int  i=0; i<nParamCount; i++)
    
... {
        jstr = env->NewStringUTF(szParams);
        
if  (jstr == 0)  ... {
            printf("
分配 String 失败 ");
            
if  (env->ExceptionOccurred())  ... {
                env->ExceptionDescribe();
                env->ExceptionClear();
            }
            
            
return  false ;
        }
        
        env->SetObjectArrayElement(args, i, jstr);
        
if  (env->ExceptionCheck() == JNI_TRUE)
        
... {
            printf("
设置参数失败 ");
            
if  (env->ExceptionOccurred())  ... {
                env->ExceptionDescribe();
                env->ExceptionClear();
            }
            
return  false ;
        }
    }
    
    
    
    
// 调用启动类的启动方法启动 Java 程序
    //env->CallStaticVoidMethod(serviceClass, mid, parameterArray);
    env->CallStaticVoidMethod(serviceClass, mid, args);
    
    
if  (env->ExceptionCheck() == JNI_TRUE)
    
... {
        env->ExceptionDescribe();
        env->ExceptionClear();
        FreeLibrary(jvmDll);
        
return  false ;
    }
    
    MSG  msg ;
    
while  (GetMessage (&msg, NULL, 0, 0))
    
... {
        TranslateMessage (&msg) ;
        DispatchMessage (&msg) ;
    }
    
return  true ;
    
}

// 设置输出流的方法

bool  setStream(JNIEnv *env,  const  char * pszFileName,  const  char * pszMethod)
... {
    
int  pBufferSize = 1024;
    
char * pBuffer =  new  char [pBufferSize];
    
    
// 创建字符串对象。
    jstring pathString = env->NewStringUTF(pszFileName);
    
if  (env->ExceptionCheck() == JNI_TRUE || pathString == NULL)
    
... {
        env->ExceptionDescribe();
        env->ExceptionClear();
        printf("
创建字符串失败。 ");
        
return  false ;
    }
    
    
// 查找 FileOutputStream 类。
    jclass fileOutputStreamClass = env->FindClass("java/io/FileOutputStream");
    
if  (env->ExceptionCheck() == JNI_TRUE || fileOutputStreamClass == NULL)
    
... {
        env->ExceptionDescribe();
        env->ExceptionClear();
        printf("
查找 FileOutputStream 类失败。 ");
        
return  false ;
    }
    
    
// 查找 FileOutputStream 类构造方法。
    jmethodID fileOutputStreamConstructor = env->GetMethodID(fileOutputStreamClass, "<init>", "(Ljava/lang/String;)V");
    
if  (env->ExceptionCheck() == JNI_TRUE || fileOutputStreamConstructor == NULL)
    
... {
        env->ExceptionDescribe();
        env->ExceptionClear();
        printf("
查找 FileOutputStream 类构造方法失败。 ");
        
return  false ;
    }
    
    
// 创建 FileOutputStream 类的对象。
    jobject fileOutputStream = env->NewObject(fileOutputStreamClass, fileOutputStreamConstructor, pathString);
    
if  (env->ExceptionCheck() == JNI_TRUE || fileOutputStream == NULL)
    
... {
        env->ExceptionDescribe();
        env->ExceptionClear();
        printf("
创建 FileOutputStream 类的对象失败。 ");
        
return  false ;
    }
    
    
// 查找 PrintStream 类。
    jclass printStreamClass = env->FindClass("java/io/PrintStream");
    
if  (env->ExceptionCheck() == JNI_TRUE || printStreamClass == NULL)
    
... {
        env->ExceptionDescribe();
        env->ExceptionClear();
        
        printf("
查找 PrintStream 类失败。 ");
        
return  false ;
    }
    
    
// 查找 PrintStream 类构造方法。
    jmethodID printStreamConstructor = env->GetMethodID(printStreamClass, "<init>", "(Ljava/io/OutputStream;)V");
    
if  (env->ExceptionCheck() == JNI_TRUE || printStreamConstructor == NULL)
    
... {
        env->ExceptionDescribe();
        env->ExceptionClear();
        printf("
查找 PrintStream 类构造方法失败。 ");
        
return  false ;
    }
    
    
// 创建 PrintStream 类的对象。
    jobject printStream = env->NewObject(printStreamClass, printStreamConstructor, fileOutputStream);
    
if  (env->ExceptionCheck() == JNI_TRUE || printStream == NULL)
    
... {
        env->ExceptionDescribe();
        env->ExceptionClear();
        printf("
创建 PrintStream 类的对象失败。 ");
        
return  false ;
    }
    
    
// 查找 System 类。
    jclass systemClass = env->FindClass("java/lang/System");
    
if  (env->ExceptionCheck() == JNI_TRUE || systemClass == NULL)
    
... {
        env->ExceptionDescribe();
        env->ExceptionClear();
        printf( "
查找 System 类失败。 ");
        
return  false ;
    }
    
    
// 查找 System 类设置方法。
    jmethodID setStreamMethod = env->GetStaticMethodID(systemClass, pszMethod, "(Ljava/io/PrintStream;)V");
    
if  (env->ExceptionCheck() == JNI_TRUE || setStreamMethod == NULL)
    
... {
        env->ExceptionDescribe();
        env->ExceptionClear();
        printf("
查找 System 类设置方法失败。 ");
        
return  false ;
    }
    
    
// 设置 System 类的流。
    env->CallStaticVoidMethod(systemClass, setStreamMethod, printStream);
    
if  (env->ExceptionCheck() == JNI_TRUE)
    
... {
        env->ExceptionDescribe();
        env->ExceptionClear();
        printf("
设置 System 类的流失败。 ");
        
return  false ;
    }
    
    
return  true ;
}
 
第二步,将Java文件打包为exe文件,也很简单。在Dos提示符下执行copy命令:
C:/>copy test.exe+test.jar test.exe
其实,就是将Java打包文件追加到exe文件尾部。打开文件属性对话框,可看到有“压缩文件”属性页。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值