Most Read This Week
By: Jim Barnabee
Feb. 1, 1999 12:00 AM
As the popularity of Java increases, many information services departments are embracing Java as the solution to their cross-platform challenges. As this trend progresses, many developers will be faced with the challenge of migrating their Java servers from UNIX to an NT boot-time environment. Administrators tend to take the attitude that since Java is a cross-platform language, this migration should be effortless. Unfortunately, this isn't the case. The thread management of child threads in the current Java Virtual Machine from Microsoft can cause problems for those developers migrating from a UNIX environment. This article explores one workaround for the thread management and garbage collection differences between the Sun and Microsoft JVMs. Microsoft recently agreed to implement a court decision to make their JVM ISO-compliant. It remains to be seen whether this will affect the behavior of Microsoft's proprietary Service class.
Considerable trial and error is associated with the migration of Java server classes to the NT environment. In the UNIX operating system it's possible simply to fork off a Java process in a script that's run at boot time. (The particular script, and the associated operating system messages that need to be caught, depends on the flavor of UNIX involved.) Under the NT operating system no fork is available, so to start a process at boot time, an NT service must be created and registered with the service's control panel. The problem inherent in this approach is that the NT OS doesn't allow fine control over the child process once it's been started. If a Java class utilizes threads, you have to override the stop method of the extended Service class to isolate and stop your threads manually. This task is made more complex because there's no definitive way to isolate your threads from the operating system threads other than their placement on the stack. Consequently, other processes started after your server may interfere with the stopping of your service. Recent versions of the Microsoft JVM have addressed this problem, but to ensure proper garbage collection, manual thread management within services is still necessary.
To create an NT service, you have to create a Java class file that extends the coms.ms.service.Service class provided by Microsoft in its Software Developers Kit for Java. This class is located in C:\SDK\NTService\service.zip in version 1.02 and C:\SDK-Java.202\Bin\jntsvc\service.zip in version 2.02 of the SDK files installed by the Microsoft SDK-Java installer. Do not attempt to unzip this file and examine the Java files. All the documentation you should need to extend the Service class is contained in the SDK-Java documents and in this article. The SDK-Java is available on Microsoft's Web site at www.microsoft.com\java\. This executable should be downloaded and installed on the system that will run the Java service. Be sure to install the Internet Explorer Java support as part of the SDK installation because the support actually installs the Java Virtual Machine. The JVM is necessary because the NT operating system won't try to access the normal Java executable located on the path; instead, it will invoke the jview executable resident within the Microsoft SDK. Microsoft's proprietary compiler and JVM contain custom hooks into the OS that are not part of the ISO standard. It remains to be seen whether these hooks will be deprecated as part of the move toward ISO compliance by Microsoft. The services control panel now defaults to the Microsoft proprietary JVM, called jview.
The Service class of the coms.ms.service package provides methods to allow the NT OS to start, stop and pause a service. However, the JVM doesn't allow the NT services driver to access child threads of the parent class automatically. The ramifications of this are that if you create a wrapper class that extends service, you have to manually instantiate, start, pause and stop any child threads from within the wrapper class itself. Any child threads instantiated or started from within the Java class being wrappered won't be accessible from within the NT services framework. Once a child thread has been instantiated and started, the NT OS no longer knows that the child thread is grouped with its parent.
Any attempts to stop or pause a service that contains child threads without taking this into consideration will result in the OS's returning an error stating that it is unable to stop the service. To avoid this, the wrapper class in its stop method has to isolate and stop any child threads. Note that this is true for wrapper classes, while classes that directly extend the coms.ms.service.Service class will stop, usually without error, in version 2.02 and above. For previous versions, and to ensure proper functionality if wrappering classes are involved, manual thread grouping should still be utilized.
Listing 1 is an example of how you might extend the coms.ms.service.Service class to create a wrapper class that can be registered as an NT service, and will call the public static void main(String args) method of your Java class. To use this example code, replace YOURSERVICE with the class name of the application you wish to wrapper.
Once your Java file has been created, it needs to be compiled to bytecode. Once you have a Linking.class, move the Linking.class file to the C:\SDK-Java\NTService\ or C:\SDK-Java.202\Bin\jntsvc\ directory that was created when you ran the Microsoft SDK-Java executable. You now have a wrapper class that can be registered as an NT service.
To ensure that your target system is configured properly so you can register and use the Java service class you've created, follow the steps below.
3. (If you're using version 2.02 or higher of the SDK, you can skip this step as the jntsvc registration program will modify the registry for your service.) The last step is to modify the JVM's CLASSPATH variable, because the standard Java CLASSPATH environmental variable isn't recognized by the JVM. The JVM CLASSPATH variable is explicitly defined within the JVM's set of environmental variables. Therefore it's necessary to directly modify the CLASSPATH variable that the JVM places in the system registry as follows:
My Computer\HKey_Local_Machine\Software \Microsoft\JavaVM
Now open the CLASSPATH environmental variable for editing by double-clicking on the small book icon directly left of the word CLASSPATH.
Registering the Service
For version 2.02:
Testing and Evaluation
Set the Events to the Application log, and refresh the view. This allows you to examine the debug lines from the linking class so you can debug your classes or linking structures. Note: If the Event Viewer Application log says it can't find your class, make sure both CLASSPATH variables are set to include the paths to your linking class and all classes you wish to import.
Many companies are pursuing Java in an attempt to reduce their operating budgets and increase their efficiency. Java is promising cross-platform compatibility. Most of the problems associated with the migration of Java can be attributed to its youth as a language. While developers feel joy about a "write once, run anywhere" ability, it's short-lived when the virtual machines don't conform to the same specifications. While Sun has made - and continues to pursue - true cross-platform compatibility among all JVMs, not all have achieved a workable level of compliance. As a result of litigation, Microsoft is migrating its JVM into compliance with the ISO standard. It remains to be seen, however, whether this migration will affect the necessarily proprietary NT Service installation classes. These differences require developers and IT staff who wish to import their code to Windows to be aware that the "write once, run anywhere" promise of Java is not always applicable in a Windows environment. Until all Java Virtual Machines behave identically, there will continue to be issues of migration for developers and IS departments to face.
Reader Feedback: Page 1 of 1
Subscribe to the World's Most Powerful Newsletters
Today's Top Reads