HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

"Creating a Custom Launcher"
Vol. 7, Issue 9, p. 48

	


Listing 1: Typical Windows launcher for a 1.2 or later VM


#include <windows.h>
#include <jni.h>
#include <string>
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;


   // Path Determination


   // --- application home
   char home[2000];
   if (!GetApplicationHome(home, sizeof(home))) {
      vShowError("Unable to determine \
        application home.");
   return 0;
   }
   string sAppHome(home);
   string sOption_AppHome = "-Dapplication.home="
      + sAppHome;


   string sJREPath = sAppHome + "\\jre";


   // --- VM Path
   string sRuntimePath  = sJREPath +
      "\\bin\\classic\\"; // must contain jvm.dll
   string sJVMpath = sRuntimePath + "jvm.dll";


   // --- boot path
   string sBootPath = sJREPath + "\\lib";
   string sOption_BootPath =
      "-Dsun.boot.class.path=" + sBootPath;


   // --- class path
   string sClassPath = sAppHome + "\\classes";
   string sOption_ClassPath =
      "-Djava.class.path=" + sClassPath;


   // setup VM options
   // vAddOption(string("-verbose"));
   vAddOption(sOption_ClassPath);
   vAddOption(sOption_AppHome);


   // initialize args
   JavaVMInitArgs vm_args;
   vm_args.version = 0x00010002;
   vm_args.options = vm_options;
   vm_args.nOptions = mctOptions;
   vm_args.ignoreUnrecognized = JNI_TRUE;


   // load jvm library
   HINSTANCE hJVM = LoadLibrary(sJVMpath.c_str());
   if( hJVM == NULL ){
      vShowLastError("Failed to load JVM from "
        + sJVMpath);
      return 0;
   }


   // try to start 1.2/3/4 VM
   // uses handle above to locate entry point
   CreateJavaVM lpfnCreateJavaVM = (CreateJavaVM)
      GetProcAddress(hJVM, "JNI_CreateJavaVM");
   jintVMStartupReturnValue = (*lpfnCreateJavaVM)
      (&jvm, &env, &vm_args);


   // test for success
   if (jintVMStartupReturnValue < 0) {
      string sErrorMessage = "Unable to create VM.";
      vShowError(sErrorMessage);
      vDestroyVM(env, jvm);
      return 0;
   }


   // find startup class
   string sStartupClass = "javabunny/JavaBunny";
   // notice dots are translated to slashes
   jclassStartup = 
      env->FindClass(sStartupClass.c_str());
   if (jclassStartup == NULL) {
      string sErrorMessage =
        "Unable to find startup class [" +
        sStartupClass + "]";
      vShowError(sErrorMessage);
      vDestroyVM(env, jvm);
      return 0;
   }


   // find startup method
   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 =
      "Unable to find startup method ["
      + sStartupClass + "."
      + sStartupMethod_Identifier
      + "] with type descriptor [" +
      sStartupMethod_TypeDescriptor + "]";
      vShowError(sErrorMessage);
      vDestroyVM(env, jvm);
      return 0;
   }


   // create array of args to startup method
   jstring jstringExampleArg;
   jclass jclassString;
   jobjectArray jobjectArray_args;
   jstringExampleArg =
     env->NewStringUTF("example string");
   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;
   }


   // call the startup method -
   // this starts the Java program
   env->CallStaticVoidMethod(jclassStartup,
     midStartup, jobjectArray_args);


   // attempt to detach main thread before exiting
   if (jvm->DetachCurrentThread() != 0) {
      vShowError("Could not detach main thread.\n");
   }


   // this call will hang as long as there are
   // non-daemon threads remaining
   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(),
     "Model App Error", MB_OK);
}


/* Shows an error message in an OK box with the
   system GetLastError appended in brackets */
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) &lpSystemMsgBuf,    0,    NULL );
      string sSystemError =
        string((LPTSTR)lpSystemMsgBuf);
    vShowError(sLocalError +
        " [" + sSystemError + "]");
}


void vAddOption(string& sValue) {
   mctOptions++;
   if (mctOptions >= mctOptionCapacity) {
      if (mctOptionCapacity == 0) {
         mctOptionCapacity = 3;
         vm_options =
(JavaVMOption*)malloc(mctOptionCapacity *
  sizeof(JavaVMOption));
    } else {
         JavaVMOption *tmp;
         mctOptionCapacity *= 2;
         tmp = 
(JavaVMOption*)malloc(mctOptionCapacity *
  sizeof(JavaVMOption));
         memcpy(tmp, vm_options, (mctOptions-1) *
  sizeof(JavaVMOption));
         free(vm_options);
         vm_options = tmp;
      }
   }
   vm_options[mctOptions-1].optionString =
        (char*)sValue.c_str();
}


/* If buffer is "c:\app\bin\java",
 * then put "c:\app" into buf. */
jboolean GetApplicationHome(char *buf, jint sz) {
   char *cp;
   GetModuleFileName(0, buf, sz);
   *strrchr(buf, '\\') = '\0';
   if ((cp = strrchr(buf, '\\')) == 0) {
      // This happens if the application is in a
    // drive root, and there is no bin directory.
      buf[0] = '\0';
      return JNI_FALSE;
   }
   return JNI_TRUE;
}

 

Additional Code For This Article (~ 49.2 KB ~zip format )
 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.