在C++代码中创建Java虚拟机。

转载 2007年10月08日 20:13:00

好多人都在问如何将java代码打包成exe文件,其实,下面这段代码稍微修改一下就可以做一个类似Java2Exe的功能。

顺便看了一下JBuilder编译生成的exe文件(星期天半天的时间花在研究这个上面了),是将jar文件追加到exe文件末尾,然后将exe文件当作jar文件来使用,因此,调试了半天也没发现它写临时文件。方法还是挺巧妙的。其实,替换掉JBuilder生成的exe文件末尾的jar文件就可以生成你自己的打包exe文件。 

下面代码是csdn blog 上fita的,原文在:http://blog.csdn.net/fita/archive/2005/03/23/327838.aspx ,不过有编译错误(估计是fita故意的),我只是调了调。

另一个问题是,如果是Java GUI程序,须在启动Java程序后,开始一个消息循环,否则Java程序窗口会一闪而过。

 

#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=./startup.jar;./DirectMail.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/qzsoft/directmail/MainFrame";
    
    
//启动方法,通常是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[i]);
        
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, 00))
    
...{
        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;
}

 

使用C++创建jvm虚拟机

如果我们愿意同样也可以在C++中调用Java方法。
  • wjc133
  • wjc133
  • 2017-06-01 15:08:44
  • 537

在C++代码中创建Java虚拟机。

好多人都在问如何将java代码打包成exe文件,其实,下面这段代码稍微修改一下就可以做一个类似Java2Exe的功能。顺便看了一下JBuilder编译生成的exe文件(星期天半天的时间花在研究这个上面...
  • mr_yanfei
  • mr_yanfei
  • 2007-08-13 00:09:00
  • 1420

JAVA虚拟机:对象的创建过程

简要说明的话,Java对象的创建过程分为下面几步: 1、执行相关检查; 2、为对象分配内存,将分配到的内存空间都初始化为零值; 3、进行构造代码块和构造函数的初始化  下面详细介绍这几个步骤: 1、执...
  • wanggg2760
  • wanggg2760
  • 2016-07-15 10:46:45
  • 755

在JNI中创建一个Java虚拟机实例

Java语言分为编译和运行两个阶段。 第一个阶段是使用javac命令完成的,第二阶段是使用java命令完成的。 下面的目标就是写一个java程序,然后手动创建一个Java虚拟机实例来执行该ja...
  • hp910315
  • hp910315
  • 2017-12-25 13:59:51
  • 185

eclipse启动创建java 虚拟机失败

刚开始玩安卓开发的时候,打开开发包就出了这么个错误,网上找了一下,将自己的eclipse.ini改成如下式样: -startup plugins/org.eclipse.equinox.launche...
  • widenstage
  • widenstage
  • 2017-04-05 09:13:32
  • 2243

eclipse不能创建java虚拟机-解决方法

转自http://blog.163.com/piaoxue_dongji/blog/static/192760882011112724929144/ 以前用的eclipse-jee因为在部署项目...
  • dujunjie2008
  • dujunjie2008
  • 2015-07-04 10:06:15
  • 1191

Java对象在虚拟机中的创建过程

虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用。并且检查代表这个符号引用的类是否已经被加载、解析和初始化过。如果没有,那么必须先执行相应的类加载。在类加载...
  • fjse51
  • fjse51
  • 2017-01-06 16:34:31
  • 522

打开Flash builder 提示无法创建java虚拟机 .

装上flash builder 之后运行,弹出错误提示 failed to create the java virtual machine 解决方法(转) 可能运行时没有设置扩大内存的参数造成内...
  • MeetLunay
  • MeetLunay
  • 2012-05-17 16:41:45
  • 1782

在java虚拟机中对象的创建过程

虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化过。如果没有,那么必须先执行相应的类加载过程。在类...
  • chao_19
  • chao_19
  • 2017-06-11 18:19:40
  • 169

Java对象与JVM(一) Java对象在Java虚拟机中的创建过程

下面我们详细了解Java程序中new一个普通对象时,HotSpot虚拟机是怎么样创建这个对象的,包括5个步骤:相应类加载检查过程、在Java堆中为对象分配内存、分配后内存初始化为零、对对象进行必要的设...
  • tjiyu
  • tjiyu
  • 2016-12-29 07:47:14
  • 4338
收藏助手
不良信息举报
您举报文章:在C++代码中创建Java虚拟机。
举报原因:
原因补充:

(最多只允许输入30个字)