分享
 
 
 

打造个性化Java启动器

王朝java/jsp·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

主要内容:

________________________

一、java程序的启动过程

二、Windows平台的启动器

三、配置和使用

________________________

对于普通用户来说,Java最让人不习惯的是程序的启动过程;即使对于富有经验的开发者,为了用默认的装载器启动Java程序,不得不编写大量批命令、脚本文件,不得不在命令行环境下进行大量的复制/粘贴操作,也很轻易出现误操作。

用惯了Windows方便快捷的GUI,人们早就习惯了通过双击运行程序的方式。对于Java程序,要实现这个本机启动功能就必须编写定制的启动器。用定制启动器启动Java程序不仅方便了最终用户,而且使软件作品看起来更专业。本文就以Windows平台为例,介绍如何构造Java定制启动器。

Java程序可以由任何本机运行的程序调用执行。所谓Java启动器,就是一个专门用来启动Java程序的本机执行程序。最常见的启动器是Sun在Java Runtime Environment的/bin目录中提供的启动器,就Windows平台而言,它们是java.exe和javaw.exe。前者运行时打开两个窗口:一个是接收System.out/err和启动器输出的控制台窗口,另一个是Java程序本身的窗口;javaw运行时不打开控制台窗口。在J2SE/EE平台中,虚拟机以动态库的形式实现,也放在/bin目录下。动态库的名字在Windows中是java.dll,在Unix中是java.so。所谓“装入虚拟机”,就是指装入这个动态库。

提供给VM的参数可以通过两种方式指定,或者是在启动器的命令行参数中指定,或者通过定义相应的环境变量指定。只有一个参数例外——要启动的类的名称只能在启动器的命令行参数中指定。虽然指定方式的多样姓为人们各取所需带来了方便,但不可否认地,它也正是许多混乱的根源。使用定制启动器能够完全避免这方面的问题。

当VM结束启动类的main()方法的运行,启动器调用destroy()方法释放各种资源并退出。应当注重的是,VM一旦开始运行,我们就不能再卸载它。对于Java启动器来说,能否关闭VM无关紧要,因为启动器会随着Java程序的退出而退出;然而,对于嵌入了VM的本机应用,例如浏览器,这意味着有一块内存被永久姓地占用,不能再收回。

二、Windows平台的启动器

搞清楚了Java程序的启动过程,我们就可以开始编写启动器的代码。下面这个启动器用C++写成,适合于所有Windows平台。

// Windows平台下的Java程序启动器

// 适用于1.2或更高版本的VM

#include

#include

#include

using namespace std;

void vShowError(string sErrorMessage);

void vShowLastError(string sErrorMessage);

void vDestroyVM(JNIEnv *env, JavaVM *jvm);

void vAddOption(string& sName);

JavaVMOption* vm_options;

int mctOptions = 0;

int mctOptionCapacity = 0;

boolean GetapplicationHome(char *buf, jint sz);

typedef jint (CALLBACK *CreateJavaVM)(JavaVM **pvm, JNIEnv **penv, void *args);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPRevInstance, PSTR szCmdLine, int iCmdShow){

JNIEnv *env;

JavaVM *jvm;

jint jintVMStartupReturnValue;

jclass jclassStartup;

jmethodID midStartup;

// 确定各种文件所在的路径

// -应用的主目录

char home[2000];

if (!GetApplicationHome(home, sizeof(home))) {

vShowError("不能确定应用的主目录。");

return 0;

}

string sAppHome(home);

string sOption_AppHome = "-Dapplication.home=" + sAppHome;

string sJREPath = sAppHome + "\jre";

// -VM路径

string sRuntimePath = sJREPath + "\bin\classic\";

string sJVMpath = sRuntimePath + "jvm.dll";

// -启动路径

string sBootPath = sJREPath + "\lib";

string sOption_BootPath = "-Dsun.boot.class.path=" + sBootPath;

// -CLASSPATH

string sClassPath = sAppHome + "\classes";

string sOption_ClassPath = "-Djava.class.path=" + sClassPath;

// 设置VM参数

// vAddOption(string("-verbose"));

vAddOption(sOption_ClassPath);

vAddOption(sOption_AppHome);

// VM初始化参数

JavaVMInitArgs vm_args;

vm_args.version = 0x00010002;

vm_args.options = vm_options;

vm_args.nOptions = mctOptions;

vm_args.ignoreUnrecognized = JNI_TRUE;

// 装入JVM库

HINSTANCE hJVM = LoadLibrary(sJVMpath.c_str());

if( hJVM == NULL ){

vShowLastError("不能从下面的路径装入JVM:" + sJVMpath);

return 0;

}

// 启动1.2/3/4 VM

CreateJavaVM lpfnCreateJavaVM = (CreateJavaVM) GetProcAddress(hJVM, "JNI_CreateJavaVM");

jintVMStartupReturnValue = (*lpfnCreateJavaVM) (&jvm, &env, &vm_args);

// 是否成功?

if (jintVMStartupReturnValue

FindClass(sStartupClass.c_str());

if (jclassStartup == NULL) {

string sErrorMessage ="找不到启动类[" +sStartupClass + "]";

vShowError(sErrorMessage);

vDestroyVM(env, jvm);

return 0;

}

// 要启动的方法

string sStartupMethod_Identifier = "main";

string sStartupMethod_TypeDescriptor ="([Ljava/lang/String;)V";

midStartup = env-GetStaticMethodID(jclassStartup,

sStartupMethod_Identifier.c_str(),

sStartupMethod_TypeDescriptor.c_str());

if (midStartup == NULL) {

string sErrorMessage = "找不到启动方法["+ sStartupClass + "."+ sStartupMethod_Identifier

+ "],类型描述符是[" + sStartupMethod_TypeDescriptor + "]";

vShowError(sErrorMessage);

vDestroyVM(env, jvm);

return 0;

}

// 构造启动方法的参数

jstring jstringExampleArg;

jclass jclassString;

jobjectArray jobjectArray_args;

jstringExampleArg = env-NewStringUTF("string1");

if (jstringExampleArg == NULL){

vDestroyVM(env, jvm);

return 0;

}

jclassString = env-FindClass("java/lang/String");

jobjectArray_args = env-NewObjectArray(1, jclassString, jstringExampleArg);

if (jobjectArray_args == NULL){

vDestroyVM(env, jvm);

return 0;

}

// 调用启动方法启动Java程序

env-CallStaticVoidMethod(jclassStartup, midStartup, jobjectArray_args);

// 在退出之前尝试分离主线程

if (jvm-DetachCurrentThread() != 0) {

vShowError("分离主线程失败。\n");

}

// 只要还有非守护线程,下面的调用将一直被挂起

jvm-DestroyJavaVM();

return 0;

}

void vDestroyVM(JNIEnv *env, JavaVM *jvm){

if (env-ExceptionOccurred()) {

env-ExceptionDescribe();

}

jvm-DestroyJavaVM();

}

void vShowError(string sError) {

MessageBox(NULL, sError.c_str(), "错误", MB_OK);

}

/* 在对话框中显示错误信息,括号内包含

的GetLastError错误信息 */

void vShowLastError(string sLocalError) {

LPVOID lpSystemMsgBuf;

FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER

FORMAT_MESSAGE_FROM_SYSTEM FORMAT_MESSAGE_IGNORE_INSERTS,

NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),

(LPTSTR) &

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有