Most read:
Popular archives:
JavaWorld's new look is here!
We've upgraded the site with a fresh look-and-feel, improved topical navigation, better search, new features, and expanded
community platform. Learn more about the changes to JavaWorld.
| Oracle Compatibility Developer's Guide |
| The Explosion in DBMS Choice |
The C/C++ world defines an entity known as a pointer. A pointer is nothing more than a variable that holds the machine address of another variable.
Functions defined in C or C++ can take pointers to variables as arguments. For example, the C/C++ program listed below contains an add function that takes two integer arguments, sums them, and returns their total via an integer pointer:
#include <stdio.h>
void add (int, int, int *);
void main (void)
{
int total;
add (3, 5, &total);
printf ("total = %d\n", total);
}
void add (int a, int b, int *sum)
{
*sum = a + b;
}
Java does not allow you to use pointers because they are not part of the language. However, it is possible to simulate a pointer to a sequence of characters with some help from the Java Native Interface (JNI).
If we can simulate a pointer, then we can communicate with an object reference. One way to simulate a pointer is to call one
of the object's methods. For example, suppose that a reference to a StringBuffer object was passed as an argument. If the StringBuffer's append method was called then it would be possible to append characters to the StringBuffer. This is shown here:
// ---------------
// useSysInfo.java
//
// SysInfo Driver
// ---------------
public class useSysInfo
{
public static void main (String [] args)
{
System.out.println ("----------\nuseSysInfo\n----------\n");
// ----------------------------------------------------
// Get and print the PATH environment variable setting.
// ----------------------------------------------------
System.out.println ("1. Get PATH environment variable setting.");
System.out.println (" Setting returned as a String object.\n");
System.out.println ("PATH = " + SysInfo.getenv ("PATH") + "\n");
// ------------------------------------------------------
// Get the PATH environment variable setting by returning
// setting in StringBuffer object referenced by evValue.
// ------------------------------------------------------
StringBuffer evValue = new StringBuffer ("");
SysInfo.getenv ("PATH", evValue);
// --------------------------------------------
// Print the PATH environment variable setting.
// --------------------------------------------
System.out.println ("2. Get PATH environment variable setting.");
System.out.println (" Setting returned in StringBuffer ref-");
System.out.println (" erence object.\n");
System.out.println ("PATH = " + evValue + "\n");
// -------------------------------------------
// Get and print the native OS version number.
// -------------------------------------------
Version v = SysInfo.getVersion ();
System.out.println ("3. Display native OS version info.");
System.out.println (" Info returned in Version object.\n");
System.out.println ("Version Major = " + v.major);
System.out.println ("Version Minor = " + v.minor);
}
}
The following statements, taken from the code above, create a new StringBuffer object, evValue, initialize it to the empty string, and pass an evValue reference to the getenv method:
StringBuffer evValue = new StringBuffer ("");
SysInfo.getenv ("PATH", evValue);
Where do you think that getenv will place the value associated with the PATH environment variable? Give up? This value will appear in evValue.
The next listing contains the Java code that loads the SysInfo native DLL and defines two overloaded getenv native methods for obtaining an environment variable's value along with a getVersion method for obtaining the host operating system's version number.
public class SysInfo
{
static
{
try
{
System.loadLibrary ("SysInfo");
}
catch (java.lang.UnsatisfiedLinkError e)
{
System.out.println (e);
}
}
public static native String getenv (String evName);
public static native void getenv (String evName, StringBuffer evValue);
public static native Version getVersion ();
}
The next chunk of code contains C++ code that defines the bodies for these native methods:
// ==========================
// SysInfo.cpp
//
// Obtain system information.
// ==========================
#include <windows.H>
#include "SysInfo.H"
// ========================================================================
// Java_SysInfo_getenv__Ljava_lang_String_2
//
// Obtain the value of an environment variable.
//
// Arguments:
//
// env - pointer to pointer to JNI function table
// clazz - handle of class that contains this method
// EVName - handle of Java String object that contains environment variable
// name
//
// Return:
//
// Java String object containing environment variable value
// ========================================================================
JNIEXPORT jstring JNICALL
Java_SysInfo_getenv__Ljava_lang_String_2
(JNIEnv *env, jclass clazz, jstring EVName)
{
// Check Java String object argument (environment variable name) to see
// if null reference passed.
if (EVName == 0)
return 0;
// Get ASCII representation of environment variable name.
const char *_EVName = env->GetStringUTFChars (EVName, 0);
// Get environment variable value.
const char *EVValue = getenv (_EVName);
// Release memory used to hold ASCII representation.
env->ReleaseStringUTFChars (EVName, _EVName);
// Return a null reference if there is no environment variable value
// otherwise return this value.
return (EVValue == 0) ? 0 : env->NewStringUTF (EVValue);
}
// =========================================================================
// Java_SysInfo_getenv__Ljava_lang_String_2Ljava_lang_StringBuffer_2
//
// Obtain the value of an environment variable.
//
// Arguments:
//
// env - pointer to pointer to JNI function table
// clazz - handle of class that contains this method
// EVName - handle of Java String object that contains environment variable
// name
// EVValue - handle of Java StringBuffer object that will hold environment
// variable value
//
// Return:
//
// none
// =========================================================================
JNIEXPORT void JNICALL
Java_SysInfo_getenv__Ljava_lang_String_2Ljava_lang_StringBuffer_2
(JNIEnv *env, jclass clazz, jstring EVName, jobject EVValue)
{
// Check Java String object argument (environment variable name) to see
// if null reference passed.
if (EVName == 0)
return;
// Check Java StringBuffer object argument (environment variable value)
// to see if null reference passed.
if (EVValue == 0)
return;
// Get ASCII representation of environment variable name.
const char *_EVName = env->GetStringUTFChars (EVName, 0);
// Get environment variable value.
const char *_EVValue = getenv (_EVName);
// Release memory used to hold ASCII representation.
env->ReleaseStringUTFChars (EVName, _EVName);
// Return if there is no environment variable value.
if (_EVValue == 0)
return;
// Obtain the Java StringBuffer class handle that corresponds to the
// Java StringBuffer object handle.
clazz = env->GetObjectClass (EVValue);
// Obtain the method ID for the StringBuffer append method which takes
// a StringBuffer object reference argument and returns a String object
// reference.
jmethodID mid =
env->GetMethodID (clazz,
"append",
"(Ljava/lang/String;)Ljava/lang/StringBuffer;");
// If this method does not exist then return.
if (mid == 0)
return;
// Create a new Java String object and populate it with the environment
// variable value. Obtain a handle to this object.
jstring _jstring = env->NewStringUTF ((const char *) _EVValue);
// Call the StringBuffer object's append method passing the handle to
// the new Java String object.
env->CallObjectMethod (EVValue, mid, _jstring);
}
// ====================================================
// Java_SysInfo_getVersion
//
// Get the native operating system's version.
//
// Arguments:
//
// env - pointer to pointer to JNI function table
// clazz - handle of class that contains this method
//
// Return:
//
// Version object containing native version information
// ====================================================
JNIEXPORT jobject JNICALL Java_SysInfo_getVersion (JNIEnv *env, jclass clazz)
{
OSVERSIONINFO osVersionInfo;
// Get operating system version information.
osVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
GetVersionEx (&osVersionInfo);
// Attempt to find the Version class.
clazz = env->FindClass ("Version");
// If this class does not exist then return null.
if (clazz == 0)
return 0;
// Allocate memory for a new Version class object. Do not bother calling
// the constructor (the default constructor does nothing).
jobject obj = env->AllocObject (clazz);
// Attempt to find the major field.
jfieldID fid = env->GetFieldID (clazz, "major", "I");
// If this field does not exist then return null.
if (fid == 0)
return 0;
// Set the major field to the operating system's major version.
env->SetIntField (obj, fid, osVersionInfo.dwMajorVersion);
// Attempt to find the minor field.
fid = env->GetFieldID (clazz, "minor", "I");
// If this field does not exist then return null.
if (fid == 0)
return 0;
// Set the minor field to the operating system's minor version.
env->SetIntField (obj, fid, osVersionInfo.dwMinorVersion);
return obj;
}
The following Java signature: