立即注册
 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
广州大学城网业务调整

[Java/JSP] 将Java代码打包为exe文件 [复制链接] qrcode

查看: 3733 | 回复: 0

大法师的 该用户已被删除
发表于: 2013-2-20 15:54:37 | 显示全部楼层

    现在有很多的工具将Java代码打包为exe文件,执行时不需要再编写批处理文件,或者在命令行输入长长的classpath信息,为用户使用提供了很大的方便。这也是很多商业软件常常使用的方法。
作者:晏斐
2       Java代码打包为exe文件
       现在有很多的工具将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>
//#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_07jreinserverjvm.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文件尾部。打开文件属性对话框,可看到有压缩文件属性页。老牌的JBuilder.exe开发工具编译生成的exe文件即采用如下方式生成。



 Java是一门最有前景的面向对象语言,学习java是许多人获得高薪的方法!现在学习java最好就是参加java培训广州java培训机构有很多,选择一个合适的java培训机构对于我们的就业是很重要的。因此大家一定要擦亮眼睛。选择合适的java培训机构
  QQ 744437114
 
跳转到指定楼层
快速回复 返回顶部 返回列表