Obtaining the JNI environment pointer
If you need to call any JNI functions, use the /COPY file JNI from QSYSINC/QRPGLESRC. Most of the JNI functions are called through a procedure pointer. The procedure pointers are part of a data structure that it itself based on a pointer called the "JNI environment pointer". This pointer is called JNIEnv_P in the JNI /COPY file. To obtain this pointer, call the JNI wrapper procedure getJniEnv.
EVAL JNIEnv_P = getJniEnv();
Figure 1 contains sample source code for getJniEnv.
RPG program
H THREAD(*SERIALIZE)
H BNDDIR('JAVAUTIL')
// (JAVAUTIL is assumed to the binding directory that lists
// the service program containing the procedures described
// below)
/copy JAVAUTIL
// (JAVAUTIL is assumed to be the source member containing the
// prototypes for the procedures described below)
D TestClass C 'TestClass'
D StringClass C 'java.lang.String'
D newTest PR O EXTPROC(*JAVA : TestClass
D : *CONSTRUCTOR)
D name 25A VARYING CONST
D getName PR O CLASS(*JAVA : StringClass)
D extproc(*JAVA : TestClass
D : 'getName')
D setName PR extproc(*JAVA : TestClass
D : 'setName')
D newName 25A VARYING CONST
D newString PR O EXTPROC(*JAVA : StringClass
D : *CONSTRUCTOR)
D value 65535A VARYING CONST
D nameValue PR 25A VARYING
D extproc(*JAVA : StringClass
D : 'getBytes')
D myTestObj S LIKE(newTest)
D myString S LIKE(newString)
D env S LIKE(getJniEnv)
/free
// Get the JNI environment pointer so that JNI functions
// can be called.
env = getJniEnv();
// Set the beginning marker for an "object group"
// so that any objects created between now and the
// "end object group" can be freed all at once.
beginObjGroup (env);
// Create a Test object to work with
// We do not want this object to be freed with the
// other objects in the object group, so we make it
// a permanent object
myTestObj = newTest ('RPG Dept');
myTestObj = getNewGlobalRef (env : myTestObj);
// Get the current "name" from the Test object
// This creates a local reference to the Name object
myString = getName (myTestObj);
dsply (nameValue(myString));
// Change the name
setName (myTestObj : 'RPG Department');
// Get the current "name" again. This will cause
// access to the previous local reference to the old name
// to be lost, making it impossible for this RPG
// program to explicitly free the object. If the object
// is never freed by this RPG program, Java could never
// do garbage-collection on it, even though the old String
// object is not needed any more. However, endObjGroup
// will free the old reference, allowing garbage collection
myString = getName (myTestObj);
dsply (nameValue(myString));
// End the object group. This will free all local
// references created since the previous beginObjGroup call.
// This includes the two references created by the calls
// to getName.
endObjGroup (env);
// Since the original Test object was made global, it can
// still be used.
setName (myTestObj : 'RPG Compiler Dept');
// The original Test object must be freed explicitly
// Note: An alternative way to handle this situation
// would be to use nested object groups, removing
// the need to create a global reference
// beginObjGroup ------------.
// create myTestObj |
// beginObjGroup ---------. |
// ... | |
// endObjGroup ---------' |
// use myTestObj again |
// endObjGroup ------------'
freeGlobalRef (env : myTestObj);
return;
/end-free