News
Abstract
An enhancement in COBOL/JNI interface.
Content
This technical note describes an enhancement to assist COBOL programs running in AMODE 31 to interact with Java programs in AMODE 64.
Note: COBOL programs that contain OO features cannot use this enhancement. Examples are programs that contain INVOKE statements, OBJECT-REFERENCE data items and class definitions. An exception is JNIEnvPtr, a COBOL special register that is used in OO programs but can be used by non-OO COBOL programs to make Java Native Interface (JNI) calls.
Applications initiated from COBOL in AMODE 31 calling Java methods in AMODE 64
For applications that start from COBOL and need to make JNI calls, it is necessary to get the JNI environment pointer through the COBOL special register JNIEnvPtr. This special register can be used to establish addressability to the JNIEnv and JNINativeInterface structures defined in copybook JNI.cpy. JNIEnvPtr can also be passed to JNI calls as the JNI environment pointer parameter.
Since the COBOL program will start the Java Virtual Machine (JVM), the user can set the environment variable COBJVMINITOPTIONS to the desired JVM initialization options. To leverage the mixed AMODE JVM support, the JVM option -XX:+Enable3164Interoperability must be specified. For example:
export COBJVMINITOPTIONS=”-XX:+Enable3164Interoperability -Djava.library.path=.”
The CLASSPATH environment variable should also be set appropriately.
Applications initiated from Java in AMODE 64 calling COBOL native methods in AMODE 31
For applications that start from Java, the JNI environment pointer is passed as a parameter to COBOL native programs, so there is no need to use the JNIEnvPtr special register. For coding convenience, the JNIEnvPtr special register is still available. The JVM option XX:+Enable3164Interoperability is required to invoke native functions (COBOL programs) in AMODE 31.
Programming considerations:
In mixed 31/64-bit environment, references to Java types must be declared as PIC 9(18) COMP-5 in COBOL (i.e. as an 8-byte data item). The OBJECT-REFERENCE type cannot be used as this data item maps to an incorrect 4-byte size in AMODE 31 COBOL programs. This applies to COBOL data items that are used to interact with JNI types such as jobject, jclass, jfieldID, jmethodID, jarray, jarray<type>, etc., when using them as parameters in JNI calls.
Note that accesses to EXTERNAL data items and EXTERNAL files are not serialized.
Building the mixed AMODE COBOL/Java interoperability application
It is recommended that you build and run COBOL JNI applications in z/OS UNIX.
Compiling
To compile the COBOL program, use the cob2 command in a z/OS UNIX shell. Specify the RENT, DLL and PGMNAME(LONGMIXED) compiler options. The THREAD option is not mandatory, provided that there is only one COBOL program active in the run-unit at any time.
If the COBOL program includes the file JNI.cpy by using a COPY statement, specify the include subdirectory of the COBOL install directory (typically /usr/lpp/cobol/include) in the search order for copybooks. You can specify the include subdirectory by using the -I option of the cob2 command or by setting the SYSLIB environment variable.
Linking
To prepare the COBOL program for execution, link the object file with the following two DLL side files to create an executable module:
-
libjvm31.x, which is provided with your 64-bit IBM Java Software Development Kit: $JAVA_HOME/lib/s390x/j9vm.
-
igzxjni2.x, which is provided in the lib subdirectory of the cobol directory in the z/OS UNIX file system (typically /usr/lpp/cobol/lib). This DLL side file is also available as the member IGZXJNI2 in the SCEELIB PDS.
Do not link with the sidedeck igzcjava.x. This is used only by OO features, which is not supported in the mixed AMODE environment. Linking both igzxjni2.x and igzcjava.x in the same program can lead to ABENDs.
Note: $JAVA_HOME is the home directory of the 64-bit IBM Java Software Development Kit.
Running The Program
To run the program under z/OS UNIX, set up as follows:
-
STEPLIB – Include the Language Environment datasets SCEERUN and SCERUN2 in the STEPLIB concatenation. For example:
export STEPLIB=CEE.SCEERUN2:CEE.SCEERUN
Or use the default Language Environment installed on your system.
-
Java environment variables – set the LIBPATH and CLASSPATH environment variables. $JAVAHOME is the home directory of the installed Java JDK. For example:
export LIBPATH=$JAVA_HOME/lib/s390x/j9vm:./
export CLASSPATH=./
-
COBJVMINITOPTIONS – Set this environment variable to Java JDK initialization options. The JVM option -XX:+Enable3164Interoperability is needed to initialize the mixed AMODE environment. For example:
export COBJVMINITOPTIONS=”-XX:+Enable3164Interoperability -Djava.library.path=.”
APARs
The following APARs are needed for this enhancement. Support is provided for Language Environment 2.3 and up.
-
APAR PH37101 (COBOL)
-
APAR PH28966 (LE)
-
IBM SDK, Java Technology EditionV8.0.6.35 (JVM)
Example
Below is an example of a COBOL program starting in AMODE 31 and calling the main method in Java in AMODE 64.
COBOL program:
Compile and link the program below with cob2. (The program text is in source file prog.cbl.)
cob2 -o prog.cbl -I/usr/lpp/cobol/include -q"dll" -q"pgmname(longmixed)" prog.cbl /usr/lpp/cobol/lib/igzxjni2.x $JAVA_HOME/lib/s390x/j9vm/libjvm31.x
IDENTIFICATION DIVISION.
PROGRAM-ID. "PROG" recursive.
*
ENVIRONMENT DIVISION.
*
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-CLASS-NAME PIC X(50) VALUE LOW-VALUES.
01 WS-METHOD-NAME PIC X(50).
01 WS-METHOD-SX PIC X(50).
01 WS-MAIN-METHOD-ID PIC S9(18) COMP-5.
01 WS-CLASS-ID PIC S9(18) COMP-5.
01 WS-NULL PIC S9(18) COMP-5 VALUE ZERO.
01 WS-JNI-ENV USAGE POINTER.
*
LINKAGE SECTION.
COPY JNI.
PROCEDURE DIVISION.
0010-MAIN.
SET ADDRESS OF JNIEnv TO JNIEnvPtr.
SET ADDRESS OF JNINativeInterface TO JNIEnv.
DISPLAY "set class name".
MOVE z"Greetings" TO WS-CLASS-NAME.
CALL "__etoa" USING WS-CLASS-NAME.
* ***********************************************
* FIND CLASS
* ***********************************************
CALL FindClass USING BY VALUE
JNIEnvPtr
ADDRESS OF WS-CLASS-NAME
RETURNING WS-CLASS-ID .
IF WS-CLASS-ID = ZERO
DISPLAY "CANT LOAD CLASS " WS-CLASS-NAME
GOBACK
END-IF.
* ***********************************************
* FIND METHOD (main)
* ***********************************************
MOVE z"main" TO WS-METHOD-NAME.
CALL "__etoa" USING WS-METHOD-NAME.
MOVE z"([Ljava/lang/String;)V" TO WS-METHOD-SX.
CALL "__etoa" USING WS-METHOD-SX.
CALL GetStaticMethodId USING BY VALUE
JNIEnvPtr
WS-CLASS-ID
ADDRESS OF WS-METHOD-NAME
ADDRESS OF WS-METHOD-SX
RETURNING
WS-MAIN-METHOD-ID.
* ***********************************************
* CALL METHOD (main)
* ***********************************************
CALL CallStaticVoidMethod USING BY VALUE
JNIEnvPTR
WS-CLASS-ID
WS-MAIN-METHOD-ID.
GOBACK.
0100-INIT.
EXIT.
Java program:
Create a Java Class helloWorld, with static main method.
public class Greetings {
public static void main(String[] args){
System.out.println("Greetings from AMODE 64");
}
}
import com.ibm.jzos.ZUtil;
public class Greetings
{
public static void main(String[] args)
{
try {
ZUtil.redirectStandardStreams("1047", true);
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
System.out.println("Greetings from AMODE 64");
}
}
//USERID2 JOB 'MY COBOL JOB',
// MSGLEVEL=(1,1),MSGCLASS=S,CLASS=C,NOTIFY=USERID
/* REGION=0M
//*******************************************************************
//* This JCL assumes the following:
//*
//* 1) JNI.cpy file exists in z/OS UNIX directory
//*
//* /usr/lpp/cobol/igyvXrY/include
//*
//* where X is the version number and Y is the release
//* number of COBOL installed on your system.
//*
//* This path is referenced in the COPYLOC option.
//*
//* Alternatively, copy JNI.cpy to dataset &SYSUID.COBOL.COBOL
//* and add &SYSUID.COBO.COBOL to your SYSLIB during the
//* compile step and and do not use COPYLOC option.
//*
//* 2) Your COBOL source files existin in a dataset called
//* &SYSUID..COBOL.COBOL
//*
//* 3) There is a dataset to receive linked executables and DLLs
//* called:
//*
//* &SYSUID.COBOL.LOAD
//*
//* 4) Set LIBPRFX and LNGPRFX below to identify the prefix of
//* your runtime (SEERUN, SCEERUN2, etc.) and compiler
//* (SIGYCOMP, SIGYPROC, SIGYMAC, etc.) datasets
//*
//* 5) The .class file for the Java Greetings class is available
//* in a z/OS UNIX directory that is listed in the CLASSPATH
//* environment variable defined in the GO step.
//*
//*******************************************************************
//*******************************************************************
//SETUP0 SET LIBPRFX='TSCTEST.CEEZ230'
// SET LNGPRFX='TSC390.COBOL.IGY.V6R3M0.GOOD'
//*******************************************************************
//PROCLIB JCLLIB ORDER=(&LNGPRFX..SIGYPROC)
//*******************************************************************
//SETUP1 SET INFILE='PROG'
//*******************************************************************
//DEL1 EXEC PGM=IEFBR14
//DD01 DD DSN=&SYSUID..&INFILE..LISTING,DISP=(MOD,DELETE,DELETE),
// SPACE=(TRK,(1,1))
//*******************************************************************
//COBOL1 EXEC IGYWC,
// LNGPRFX=&LNGPRFX,
// LIBPRFX=&LIBPRFX,
// PARM.COBOL='DLL,PGMNAME(LONGMIXED),OPTFILE'
//SYSLIB DD DSN=&SYSUID..COBOL.COBOL,DISP=SHR
//SYSIN DD DSN=&SYSUID..COBOL.COBOL(&INFILE),DISP=SHR
//SYSLIN DD DSN=&&OBJECT(&INFILE),DISP=(NEW,PASS),
// DCB=(RECFM=FB,LRECL=80,DSORG=PO),DSNTYPE=LIBRARY,
// SPACE=(CYL,(1,10)),UNIT=SYSALLDA
//SYSPRINT DD SYSOUT=*
//SYSOPTF DD DATA,DLM='/>'
COPYLOC(PATH('/usr/lpp/cobol/igyv6r3/include/JNI.cpy'))
/>
//SYSOUT DD SYSOUT=*
//*******************************************************************
// IF (COBOL1.COBOL.RUN AND (COBOL1.COBOL.RC EQ 0)) THEN
//LKED EXEC PGM=IEWL,
// PARM='RENT,LIST,LET,DYNAM(DLL),CASE(MIXED)'
//SYSLIB DD DSN=&LIBPRFX..SCEELKED,DISP=SHR
// DD DSN=&LIBPRFX..SCEELKEX,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSTERM DD SYSOUT=*
//SYSLMOD DD DSN=&SYSUID..COBOL.LOAD(&INFILE),DISP=SHR
//SYSDEFSD DD DUMMY
//OBJMOD DD DSN=&&OBJECT(&INFILE),DISP=SHR
//SIDEDK DD DSN=&LIBPRFX..SCEELIB(IGZXJNI2),DISP=SHR
//SYSLIN DD *
INCLUDE OBJMOD
INCLUDE SIDEDK
//*
// ENDIF
//*******************************************************************
// IF (LKED.RUN AND (LKED.RC EQ 0)) THEN
//GO EXEC PGM=&INFILE,
// REGION=512M
//STEPLIB DD DSN=&SYSUID..COBOL.LOAD,DISP=SHR
// DD DSN=&LIBPRFX..SCEERUN,DISP=SHR
// DD DSN=&LIBPRFX..SCEERUN2,DISP=SHR
//CEEOPTS DD *
ENVAR(
"COBJVMINITOPTIONS=-Djzos.merge.sysout=true",
"CLASSPATH=/home/userid/jtoc/jcl",
"LIBPATH=/usr/lpp/java/IBM/J8.0_64/lib/s390x/j9vm:/usr/lpp/java/IBM/J8.
0_64/lib/s390x")
//SYSOUT DD SYSOUT=*
//STDOUT DD SYSOUT=*
//STDERR DD SYSOUT=*
// ENDIF
//*******************************************************************
End Of Technical Note
Related Information
Was this topic helpful?
Document Information
Modified date:
03 December 2021
UID
ibm16451263