网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > Java
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
本月文章推荐
.JDK1.4新特性:断言.
.Enumerator 对象.
.在Struts 2中实现文件上传.
.small 方法.
.Java Swing入门基础.
.Java SE 6 -&nbs.
.给大家推荐几个方便java编辑的软.
.Java编程交互管理工具:SecureJS.
.使toString() 的创建自动化.
.JDBC基础教程之语句.
.封装JNDI操作LDAP服务器的工具类.
.高级技术分析:绿色和本地线程简单.
.Leopard新问题 不能用最新版Java.
.编程基础入门:Java修饰词的总结.
.Spring中的Template和Callback模.
.Eclipse基础:Java环境变量设置(图.
.在Java中轻松实现界面跳转.
.Jive源代码研究.
.JAVA调试技术.
.Java 数据对象(JDO)介绍(三).

打造个性化Java启动器

发表日期:2008-1-5



  主要内容:
  
  ________________________
  
   一、Java程序的启动过程
  
   二、Windows平台的启动器
  
   三、配置和使用
  
  ________________________
  
  对于普通用户来说,Java最让人不习惯的是程序的启动过程;即使对于富有经验的开发者,为了用默认的装载器启动Java程序,不得不编写大量批命令、脚本文件,不得不在命令行环境下进行大量的复制/粘贴操作,也很轻易出现误操作。
  
  用惯了Windows方便快捷的GUI,人们早就习惯了通过双击运行程序的方式。对于Java程序,要实现这个本机启动功能就必须编写定制的启动器。用定制启动器启动Java程序不仅方便了最终用户,而且使软件作品看起来更专业。本文就以Windows平台为例,介绍如何构造Java定制启动器。
  打造个性化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) &
上一篇:动态Proxy与Java ACL用户访问控制机制实现 人气:634
下一篇:Java:并发使一切变得简单 人气:698
浏览全部Java的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐