IBM Support

An enhancement in COBOL/JNI interface

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"); 
        } 
} 
Compiling the COBOL program from JCL
For users who would like to build the COBOL portion of the program using JCL and to run the entire application from batch, the following JCL is an example of how that may be done.  Note the assumptions listed at the top of the JCL and make modifications as necessary.  It is assumed that the Java class (Greetings) has already been compiled and the .class file is available in a z/OS UNIX directory.  Adjust the CLASSPATH environment variable in the GO step as needed so that the .class file can be located.  The Java program itself has been modified from the one used in the pure z/OS UNIX scenario to facilitate the capturing of Java output.
Modified Java program:
 
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"); 
  } 
} 
JCL:
//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 

[{"Business Unit":{"code":"BU058","label":"IBM Infrastructure w\/TPS"},"Product":{"code":"SS6SG3","label":"Enterprise COBOL for z\/OS"},"Component":"Runtime","Platform":[{"code":"PF035","label":"z\/OS"}],"Version":"6.3","Edition":"Enterprise","Line of Business":{"code":"LOB35","label":"Mainframe SW"}}]

Document Information

Modified date:
03 December 2021

UID

ibm16451263