Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Merging Java and Win32: A new way to develop Windows applications

Learn how to write Win32 applications in Java instead of C++ -- and save yourself some time and effort!

  • Print
  • Feedback

Page 3 of 6

Once the JVM is no longer required, it is destroyed by a call to DestroyJavaVM (), as in the following listing.

jvm->DestroyJavaVM ()


So, how does the Invocation API allow us to create Win32 applications using Java? The following example provides an answer.

An example

I decided to create a Win32 console application similar to PKZIP, but my application would be a little simpler. It would only provide the ability to list all files in a zip archive and extract files. My application would be launched from the command line using the following syntax:

c:\>zip [-x file] zip


whereby -x is the extraction flag, file is the name of the file to extract, and zip is the name of the archive with or without a zip extension.

The following listing shows the C++ source code zip.cpp. This code implements the ZIP executable driver. This driver loads the JVM, parses the command line arguments, locates the ZIP class file, locates the main method within the ZIP class file, launches the main method (passing the arguments list to this method), and unloads the JVM.

// ===================================================
// zip.cpp
//
// ZIP Executable Driver
//
// Supports Java Virtual Machine (JVM) 1.1.2 or higher
// ===================================================
#include <jni.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#define BUFSIZE     80
// ================================================
// Handler
//
// Console Control Handler
//
// Ignore all attempts to shutdown the application.
//
// Arguments:
//
// dwCtrlType - control event type
//
// Return:
//
// TRUE (ignore event)
// ================================================
BOOL Handler (DWORD dwCtrlType)
{
   return TRUE;
}
// =======================================
// main
//
// Zip Executable Driver Entry Point
//
// Arguments:
//
// argc - number of command line arguments
// argv - array of command line arguments
//
// Return:
//
// 0 (success) or 1 (failure)
// =======================================
int main (int argc, char *argv [])
{
   int i;
   jint ret;
   JNIEnv *env;
   JavaVM *jvm;
   jclass clazz;
   jmethodID mid;
   JDK1_1InitArgs vm_args;
   char szBuffer [BUFSIZE], szClassPath [BUFSIZE * 2 + 15];
   // Prevent application from shutting down due to Ctrl-Break or Ctrl-C keypresses,
   // window close button clicks, user logoff, or system shutdown.
   SetConsoleCtrlHandler ((PHANDLER_ROUTINE) Handler, TRUE);
   // Get default initialization arguments for JVM version 1.1.2 or higher.
   vm_args.version = 0x00010001;
   JNI_GetDefaultJavaVMInitArgs (&vm_args);
   // Tell the JVM where to find the application class files and classes.zip.
   GetPrivateProfileString ("CONFIG", "PATH", ".", szBuffer, 80, "zip.ini");
   wsprintf  (szClassPath, "%s;%s\\classes.zip;", szBuffer, szBuffer);
   vm_args.classpath = szClassPath;
   // Attempt to create a JVM instance.
   if ((ret = JNI_CreateJavaVM (&jvm, &env, &vm_args)) < 0)
   {
    fprintf (stderr, "Can't create JVM.  Error: %ld\n", ret);
    return 1;
   }
   // Process command-line arguments.
   jstring jstr = env->NewStringUTF ("");
   jobjectArray str_array = env->NewObjectArray (argc - 1, 
                                                 env->FindClass ("java/lang/String"), 
                                                                 jstr);
   for (i = 1; i < argc; i++)
   {
        if ((jstr = env->NewStringUTF (argv [i])) == 0)
        {
         fprintf (stderr, "Out of memory\n");
         return 1;
        }
        env->SetObjectArrayElement (str_array, i - 1, jstr);
   }
   // Attempt to locate zip class.
   if ((clazz = env->FindClass ("zip")) == 0)
   {
       fprintf (stderr, "Can't locate the zip class.  Exiting...\n");
       return 1;
   }
   // Attempt to locate the zip class main method.
   if ((mid = env->GetStaticMethodID (clazz, "main", "([Ljava/lang/String;)V")) == 0)
   {
       fprintf (stderr, "Can't locate the main method.  Exiting...\n");
       return 1;
   }
   // Launch main method.
   env->CallStaticVoidMethod (clazz, mid, str_array);
   // Destroy the JVM instance.
   jvm->DestroyJavaVM ();
   return 0;
}


Note the call to the Win32 GetPrivateProfileString () function. This function looks for a file called zip.ini (which would be located in the Windows directory -- usually c:\windows under Windows 95 or c:\winnt under Windows NT). The purpose of this file is to hold the path where the ZIP application is installed. The JVM will look in this location for classes.zip and application class files (no matter where the ZIP application is called from).

  • Print
  • Feedback

Resources
  • The zip archive contains all of the necessary C++/Java source and deployment files used by this article http://www.javaworld.com/jw-07-1998/java-win32/zip.zip
  • I've found the following resources beneficial when I'm writing applications that use the Java native Interface (JNI).
  • Essential JNI Java Native Interface, by Rob Gordon. PublisherPrentice Hall, Copyright1998. This book dives into JNI, and covers many techniques for calling C++ code with Java and calling Java with C++ code. One chapter focuses on the Invocation API and how to construct a C++ application which embeds the Java Virtual Machine -- in other words, how to create your own AppletViewer.exe program.
  • The JavaWorld article Use native methods to expand the Java environment provides an introductory look at the Java Native Interface http://www.javaworld.com/javaworld/jw-07-1997/jw-07-javadev.html