Black Hill Software

  • Home
  • Products
    • EasySMF
      • Release Notes and Latest Version
      • Online Manual
      • License Agreement
    • EasySMF:JE
      • EasySMF:JE Java Quickstart
      • Release Notes and Latest Version
      • Javadoc
      • EasySMF JSON Javadoc
      • License Agreement
    • 30 Day Trial
  • Purchase
    • How to Buy
    • Purchase a License
  • Support
    • EasySMF Support
    • Get the latest version of EasySMF
    • EasySMF:JE Support
    • Get the latest version of EasySMF:JE
  • News
  • Contact
    • Support
    • Sales

Systems Programmer Friendly Java

August 11, 2015 by Andrew

This article describes how to set up a simple environment for running Java batch reports or utilities, including JCL PROCs similar to the compile and go PROCs that come with other languages.

Java on z/OS is great. Fast and powerful, you can perform complex functions in very few lines of code. In the past, I have used Rexx for small utilities, but now Java is my first choice.

Java is an advanced language with many features that simplify programming problems. For example, the Collections framework provides various List, Map, Set etc. classes that allow you to quickly and efficiently create, search and compare groups of data items.

The JZOS Toolkit comes with Java on z/OS and provides interfaces for working with regular z/OS datasets.

Java should be in every systems programmer’s toolbox.

The problem is there is not much guidance on how to create a simple Java batch environment on z/OS. Most of what is out there is written for large Java applications rather than simple batch jobs and as a result is unnecessarily complex.

The Objective

To create a set of procs for batch Java Compile, Go, and Compile and Go (there is no Link step for Java).

Compiling and running a Java class should be as simple as:

//ANDREWRG JOB CLASS=A,      
//             MSGCLASS=H,   
//             NOTIFY=&SYSUID
//JAVACG   EXEC JAVACG,
// JAVACLS='''MyClass'''
//G.INPUT DD DISP=SHR,DSN=...

Optionally, you need to be able to override the locations for Java source, Java class files, class path etc. and the various Java options that can be specified.

The compile and link steps should be consistent so that you can switch between JAVAC, JAVAG and JAVACG without making other changes to the JCL.

Prerequisites

First, obviously, if Java is not already installed you need to install it. Refer to IBM 31-bit SDK for z/OS, Java Technology Edition, Version 8 and/or IBM 64-bit SDK for z/OS, Java Technology Edition, Version 8 for Java installation instructions.

JZOS Batch Launcher

You also need to install the JZOS Batch Launcher. This provides the functions that make Java useful in a z/OS batch environment.

Installation is straightforward. There is one load module to copy to a PDS/E, a JCL procedure and a sample job. The Readme suggests copying the load module to SYS1.SIEALNKE, however this is a SMP/E maintained dataset so if you are installing outside of SMP/E you should use a different location – create a new PDS/E if necessary.

JZOS documentation can be found here:

  • JZOS Knowledge Center Page
  • JZOS Installation and User’s Guide.

z/OS 2.1

These PROCs use symbol substitution in instream data which was introduced with z/OS 2.1, so z/OS 2.1 is a prerequisite. The JCL procedure delivered with JZOS works with earlier versions, but in that case the JCL required in the calling job is more complicated.

JCL Procedures

Most languages on z/OS come with a set of compile, link and go JCL procedures. These allow you to compile and run programs using standard options without dealing with the gory details every time.

We can create the same thing for Java, which greatly simplifies the process of compiling and running Java batch programs. I will be calling the PROCs JAVAC, JAVAG and JAVACG.

Design Considerations

Default Locations

Java source and class files need to be in the unix filesystem.

A standard directory structure will mean that we can set a default Java CLASSPATH etc. in the PROC, to simplify the user’s JCL.

We will use:

  • ~/java/src for the Java source
  • ~/java/target for the output class files

(~ is shorthand for the user’s home directory)

These can be overridden by the SRCPATH and TGTPATH parameters of the PROCs.

Line length

Instream data in the proc is limited to 80 bytes. If the symbol substitution extends the line beyond 80 bytes, the step gets a S001 abend. This is most likely if multiple symbols are used on one line.

To get around the problem, where we need multiple substitutions on 1 line we can assign the values to shell variables, and then use the shell variables. They are substituted later by the Unix shell which doesn’t have the same restrictions.

Java Classpath

The Java classpath is potentially lengthy with multiple entries. To allow for longer classpaths multiple CLASPAT* parameters are provided on the PROC.

To make life more complicated, the classpath syntax for the JZOS Batch Launcher is different from the Java compiler classpath syntax. The Java compiler allows wildcards but JZOS does not. We want to use the same classpath parameters in the JCL for the compile and go steps, so we need to expand wildcards in the JZOS script. To make sure the compile and go steps use the same classpath, we do the same expansion for the compile step.

Why triple quotes?

The triple quotes (apostrophes) are a quirk of JCL, which seems to be required for lowercase parameters. The enclosing quotes are stripped off when the parameters are set. The result still needs to be quoted otherwise the lowercase data causes a JCL error.

JAVAC

JAVAC is the Java compile PROC. It invokes BPXBATCH to run the Java compiler.

//JAVAC   PROC JAVACLS=,
//  REGSIZE='0M',
//* Parameters for instream data need triple quotes
//* to preserve quotes in the SET statement
//  SRCPATH='''java/src''',
//  TGTPATH='''java/target''',
//  CLASPATH='''''',
//* Additional CLASPAT* entries allow CLASSPATH to
//* be extended with less JCL continuation issues.
//  CLASPAT2='''''',
//  CLASPAT3='''''',
//  CLASPAT4='''''',
//  CLASPAT5='''''',
//* Options to the java compiler
//  JAVACOPT=''''''
//*
//SYMBOLS  EXPORT SYMLIST=(JAVACOPT,
//     SRCPATH,
//     TGTPATH,
//     CLASPATH,
//     CLASPAT2,
//     CLASPAT3,
//     CLASPAT4,
//     CLASPAT5,
//     JAVACLS)
//*
//         SET JAVACLS=&JAVACLS
//         SET SRCPATH=&SRCPATH
//         SET TGTPATH=&TGTPATH
//         SET CLASPATH=&CLASPATH
//         SET CLASPAT2=&CLASPAT2
//         SET CLASPAT3=&CLASPAT3
//         SET CLASPAT4=&CLASPAT4
//         SET CLASPAT5=&CLASPAT5
//         SET JAVACOPT=&JAVACOPT
//*
//C        EXEC PGM=BPXBATCH,REGION=&REGSIZE
//* STDPARM is multiple commands chained into one with
//* semicolons as an argument to "SH"
//* IFS splits CLASSPATH based on ":"
//* Then wildcards are expanded and recombined
//STDPARM  DD *,SYMBOLS=JCLONLY
SH CLASSPATH=&TGTPATH;
 IFS=":";
 for i in &CLASPATH; do
    for j in ${i}; do
       CLASSPATH="${CLASSPATH}":"${i}";
    done;
 done;
 for i in &CLASPAT2; do
    for j in ${i}; do
       CLASSPATH="${CLASSPATH}":"${i}";
    done;
 done;
 for i in &CLASPAT3; do
    for j in ${i}; do
       CLASSPATH="${CLASSPATH}":"${i}";
    done;
 done;
 for i in &CLASPAT4; do
    for j in ${i}; do
       CLASSPATH="${CLASSPATH}":"${i}";
    done;
 done;
 for i in &CLASPAT5; do
    for j in ${i}; do
       CLASSPATH="${CLASSPATH}":"${i}";
    done;
 done;
 export CLASSPATH="${CLASSPATH}";
 SRCPATH=&SRCPATH;
 TGTPATH=&TGTPATH;
 JAVACLS=&JAVACLS;
 /usr/lpp/java/J8.0/bin/javac
 &JAVACOPT
 -sourcepath
 ${SRCPATH}
 -d
 ${TGTPATH}
 ${SRCPATH}/${JAVACLS}.java
//STDENV   DD DDNAME=ENV
//         DD DDNAME=ADDENV
//ADDENV   DD DISP=SHR,DSN=NULLFILE
//ENV      DD *
HJV_JZOS_JVM_SMF_LOGGING=true
HJV_JZOS_JVM_SMF_LOGGING_INTERVAL=10
HJV_JZOS_JVM_SMF_THREADS=true
//STDOUT   DD SYSOUT=*
//STDERR   DD SYSOUT=*
//*
// PEND

JAVAC Examples

//ANDREWRG JOB CLASS=A,
//             MSGCLASS=H,
//             NOTIFY=&SYSUID
//JAVACG   EXEC PROC=JAVAC,
// JAVACLS='''helloworld'''
//ANDREWRC JOB CLASS=A,
//             MSGCLASS=H,
//             NOTIFY=&SYSUID
//*
//JAVAC    EXEC JAVAC,
// JAVACLS='''com/blackhillsoftware/samples/RecordCount''',
// SRCPATH='''java/easysmf-je-1-5-2/samples/source''',
// JAVACOPT='''-Xlint -verbose''',
// CLASPATH='''java/easysmf-je-1-5-2/jar/*'''
STDENV, ENV and ADDENV DD Statements

The STDENV DD statement allows you to specify enviroment variables for the BPXBATCH step.

STDENV concatenates 2 other DD statements:

  • ENV has default environment variables you want to set for all users of the proc.
  • ADDENV is a null file which can be overridden by the calling job to add or modify the default environment
//C.ADDENV DD * 
MYVARIABLE=ABCD
CLASSPATH

CLASSPATH can be set using wildcards or explicit entries. You can have multiple entries on one line separated by “:”, e.g.

// CLASPATH='''java/easysmf-je-1-5-2/jar/*''',
// CLASPAT2='''java/lib/javax.mail.jar:java/lib/jsoup-1.10.2.jar'''

The shell script sets the field separator (IFS) to “:” so it can split multiple entries in the class path and expand any wildcards, before recombining all the entries.

JAVAG

JAVAG is based on the JVMPRC80 and JVMJCL80 samples delivered with the JZOS Batch Launcher.

The embedded script has been modified to set the classpath using the same syntax as the JAVAC proc.

//JAVAG  PROC JAVACLS=,                              
//  ARGS=,                                           
//  LIBRARY='PDSE.CONTAINING.JVMLDM80',                       
//  LOGLVL='',                                       
//  REGSIZE='0M',                                    
//  LEPARM='',                                       
//* Parameters for instream data need triple quotes  
//* to preserve quotes in the SET statement          
//  SRCPATH='''java/src''',                          
//  TGTPATH='''java/target''',                       
//  CLASPATH='''''',                                 
//* Additional CLASPAT* entries allow CLASSPATH to   
//* be extended with less JCL continuation issues.   
//  CLASPAT2='''''',                                 
//  CLASPAT3='''''',                                 
//  CLASPAT4='''''',                                 
//  CLASPAT5=''''''                                  
//*                                                  
//SYMBOLS  EXPORT SYMLIST=(JAVACOPT,                 
//     SRCPATH,                                      
//     TGTPATH,                                      
//     CLASPATH,                                     
//     CLASPAT2,                                     
//     CLASPAT3,                                     
//     CLASPAT4,                                     
//     CLASPAT5,                                     
//     JAVACLS)                                      
//*                                                  
//         SET JAVACLS=&JAVACLS                      
//         SET SRCPATH=&SRCPATH                      
//         SET TGTPATH=&TGTPATH                      
//         SET CLASPATH=&CLASPATH                    
//         SET CLASPAT2=&CLASPAT2                    
//         SET CLASPAT3=&CLASPAT3                    
//         SET CLASPAT4=&CLASPAT4                    
//         SET CLASPAT5=&CLASPAT5                    
//*                                                  
//G        EXEC PGM=JVMLDM80,REGION=&REGSIZE,        
//   PARM='&LEPARM/&LOGLVL &JAVACLS &ARGS'           
//*                                                  
//STEPLIB  DD DSN=&LIBRARY,DISP=SHR                 
//SYSPRINT DD SYSOUT=*                              
//SYSOUT   DD SYSOUT=*                              
//STDOUT   DD SYSOUT=*                              
//STDERR   DD SYSOUT=*                              
//CEEDUMP  DD SYSOUT=*                              
//ABNLIGNR DD DUMMY                                 
//STDENV   DD DDNAME=ENV                            
//         DD DDNAME=ADDENV                         
//ADDENV   DD DISP=SHR,DSN=NULLFILE                 
//ENV      DD *,SYMBOLS=JCLONLY                     
. /etc/profile                                      
export JAVA_HOME=/usr/lpp/java/J8.0                 
export PATH=/bin:"${JAVA_HOME}"/bin                 

LIBPATH=/lib:/usr/lib:"${JAVA_HOME}"/bin            
LIBPATH="$LIBPATH":"${JAVA_HOME}"/lib/s390          
LIBPATH="$LIBPATH":"${JAVA_HOME}"/lib/s390/j9vm     
LIBPATH="$LIBPATH":"${JAVA_HOME}"/bin/classic       
export LIBPATH="$LIBPATH":                          

APP_HOME=&TGTPATH                                   
CLASSPATH="${APP_HOME}"                             
IFS=':'                                             
for i in &CLASPATH; do                              
    for j in ${i}; do                               
        CLASSPATH="${CLASSPATH}":"${j}"             
        done                                        
    done                                            
for i in &CLASPAT2; do                              
    for j in ${i}; do                               
        CLASSPATH="${CLASSPATH}":"${j}"             
        done                                        
    done                                            
for i in &CLASPAT3; do                              
    for j in ${i}; do                               
        CLASSPATH="${CLASSPATH}":"${j}"             
        done                                        
    done                                            
for i in &CLASPAT4; do                              
    for j in ${i}; do                               
        CLASSPATH="${CLASSPATH}":"${j}"             
        done                                        
    done                                            
for i in &CLASPAT5; do                            
    for j in ${i}; do                             
        CLASSPATH="${CLASSPATH}":"${j}"           
        done                                      
    done                                          
export CLASSPATH="${CLASSPATH}"                   

IJO="-Xms16m -Xmx128m"                            
export IBM_JAVA_OPTIONS="$IJO "                   

export HJV_JZOS_JVM_SMF_LOGGING=true              
export HJV_JZOS_JVM_SMF_LOGGING_INTERVAL=10       
export HJV_JZOS_JVM_SMF_THREADS=true              
// PEND                                           

JAVAG Examples

//JAVAG    EXEC PROC=JAVAG,
// JAVACLS='''helloworld'''
//*JAVACLS='''com/blackhillsoftware/ivp'''
//*JAVACLS='''-jar /u/ajr/java/helloworld.jar'''
//G.INPUT    DD DISP=SHR,DSN=ANDREWR.SMF.SAMPLE
//G.ADDENV DD * 
IJO="$IJO -verbose:class"
export IBM_JAVA_OPTIONS="$IJO "

This sample JCL shows 3 different types of Java class that can be invoked:

  1. A class which is not part of a package.
  2. A class (ivp) which is a member of package com.blackhillsoftware.
  3. A runnable jar.

//G.INPUT is an example of a DDNAME used by a particular Java program, not a DD required by the PROC.

STDENV, ENV and ADDENV DD Statements

The STDENV DD statement provides a script that is run before the Java program is invoked. It is used to set environment variables.

Unfortunately, the syntax is different to STDENV for BPXBATCH in the compile step. BPXBATCH STDENV sets the environment variables directly, while JZOS requires a script. The JZOS approach adds some flexibility, but means you need to explicitly “export” the variables.

As with the compile step, STDENV concatenates 2 other DD statements:

  • ENV has the standard script inline in the PROC.
  • ADDENV is a null file which can be overridden by the calling job to add or modify the default environment.
//G.ADDENV DD * 
IJO="$IJO -verbose:class"
export IBM_JAVA_OPTIONS="$IJO "
CLASSPATH

CLASSPATH is set using the same syntax as the compile PROC.

JAVACG

JAVACG combines the C and G PROCs, with a condition code check after the BPXBATCH compile step.

//JAVACG  PROC JAVACLS=,                              
//  ARGS=,                                            
//  LIBRARY='PDSE.CONTAINING.JVMLDM80',                        
//  LOGLVL='',                                        
//  REGSIZE='0M',                                     
//  LEPARM='',                                        
//* Parameters for instream data need triple quotes   
//* to preserve quotes in the SET statement           
//  SRCPATH='''java/src''',                           
//  TGTPATH='''java/target''',                        
//  CLASPATH='''''',                                  
//* Additional CLASPAT* entries allow CLASSPATH to    
//* be extended with less JCL continuation issues.    
//  CLASPAT2='''''',                                  
//  CLASPAT3='''''',                                  
//  CLASPAT4='''''',                                  
//  CLASPAT5='''''',                                  
//* Options to the java compiler                      
//  JAVACOPT=''''''                                   
//*                                                   
//SYMBOLS  EXPORT SYMLIST=(JAVACOPT,                  
//     SRCPATH,                                       
//     TGTPATH,                                       
//     CLASPATH,                                      
//     CLASPAT2,                                      
//     CLASPAT3,                                      
//     CLASPAT4,                                      
//     CLASPAT5,                                      
//     JAVACLS)                                       
//*                                                   
//         SET JAVACLS=&JAVACLS                       
//         SET SRCPATH=&SRCPATH                       
//         SET TGTPATH=&TGTPATH                       
//         SET CLASPATH=&CLASPATH                     
//         SET CLASPAT2=&CLASPAT2                     
//         SET CLASPAT3=&CLASPAT3                     
//         SET CLASPAT4=&CLASPAT4                     
//         SET CLASPAT5=&CLASPAT5                     
//         SET JAVACOPT=&JAVACOPT                     
//*                                                   
//C        EXEC PGM=BPXBATCH,REGION=&REGSIZE          
//* STDPARM is multiple commands chained into one with
//* semicolons as an argument to "SH"                 
//* IFS splits CLASSPATH based on ":"                 
//* Then wildcards are expanded and recombined        
//STDPARM  DD *,SYMBOLS=JCLONLY             
SH CLASSPATH=&TGTPATH;                      
 IFS=":";                                   
 for i in &CLASPATH; do                     
    for j in ${i}; do                       
       CLASSPATH="${CLASSPATH}":"${i}";     
    done;                                   
 done;                                      
 for i in &CLASPAT2; do                     
    for j in ${i}; do                       
       CLASSPATH="${CLASSPATH}":"${i}";     
    done;                                   
 done;                                      
 for i in &CLASPAT3; do                     
    for j in ${i}; do                       
       CLASSPATH="${CLASSPATH}":"${i}";     
    done;                                   
 done;                                      
 for i in &CLASPAT4; do                     
    for j in ${i}; do                       
       CLASSPATH="${CLASSPATH}":"${i}";     
    done;                                   
 done;                                      
 for i in &CLASPAT5; do                     
    for j in ${i}; do                       
       CLASSPATH="${CLASSPATH}":"${i}";     
    done;                                   
 done;                                      
 export CLASSPATH="${CLASSPATH}";           
 SRCPATH=&SRCPATH;                          
 TGTPATH=&TGTPATH;                          
 JAVACLS=&JAVACLS;                          
 /usr/lpp/java/J8.0/bin/javac               
 &JAVACOPT                                  
 -sourcepath                                
 ${SRCPATH}                                 
 -d                                         
 ${TGTPATH}                                 
 ${SRCPATH}/${JAVACLS}.java                 
//STDENV   DD DDNAME=ENV                    
//         DD DDNAME=ADDENV                 
//ADDENV   DD DISP=SHR,DSN=NULLFILE         
//ENV      DD *                             
HJV_JZOS_JVM_SMF_LOGGING=true               
HJV_JZOS_JVM_SMF_LOGGING_INTERVAL=10        
HJV_JZOS_JVM_SMF_THREADS=true                    
//STDOUT   DD SYSOUT=*                           
//STDERR   DD SYSOUT=*                           
//*                                              
//G        EXEC PGM=JVMLDM80,REGION=&REGSIZE,    
//   PARM='&LEPARM/&LOGLVL &JAVACLS &ARGS',      
//   COND=(0,NE,C)                               
//*                                              
//STEPLIB  DD DSN=&LIBRARY,DISP=SHR              
//SYSPRINT DD SYSOUT=*                           
//SYSOUT   DD SYSOUT=*                           
//STDOUT   DD SYSOUT=*                           
//STDERR   DD SYSOUT=*                           
//CEEDUMP  DD SYSOUT=*                           
//ABNLIGNR DD DUMMY                              
//STDENV   DD DDNAME=ENV                         
//         DD DDNAME=ADDENV                      
//ADDENV   DD DISP=SHR,DSN=NULLFILE              
//ENV      DD *,SYMBOLS=JCLONLY                  
. /etc/profile                                   
export JAVA_HOME=/usr/lpp/java/J8.0              
export PATH=/bin:"${JAVA_HOME}"/bin              

LIBPATH=/lib:/usr/lib:"${JAVA_HOME}"/bin         
LIBPATH="$LIBPATH":"${JAVA_HOME}"/lib/s390       
LIBPATH="$LIBPATH":"${JAVA_HOME}"/lib/s390/j9vm  
LIBPATH="$LIBPATH":"${JAVA_HOME}"/bin/classic    
export LIBPATH="$LIBPATH":                       

APP_HOME=&TGTPATH                                
CLASSPATH="${APP_HOME}"                          
IFS=':'                                          
for i in &CLASPATH; do                           
    for j in ${i}; do                            
        CLASSPATH="${CLASSPATH}":"${j}"          
        done                                     
    done                                         
for i in &CLASPAT2; do                           
    for j in ${i}; do                            
        CLASSPATH="${CLASSPATH}":"${j}"          
        done                                     
    done                                         
for i in &CLASPAT3; do                           
    for j in ${i}; do                            
        CLASSPATH="${CLASSPATH}":"${j}"          
        done                                
    done                                    
for i in &CLASPAT4; do                      
    for j in ${i}; do                       
        CLASSPATH="${CLASSPATH}":"${j}"     
        done                                
    done                                    
for i in &CLASPAT5; do                      
    for j in ${i}; do                       
        CLASSPATH="${CLASSPATH}":"${j}"     
        done                                
    done                                    
export CLASSPATH="${CLASSPATH}"             

IJO="-Xms16m -Xmx128m"                      
export IBM_JAVA_OPTIONS="$IJO "             

export HJV_JZOS_JVM_SMF_LOGGING=true        
export HJV_JZOS_JVM_SMF_LOGGING_INTERVAL=10 
export HJV_JZOS_JVM_SMF_THREADS=true        
// PEND                                     

JCL to invoke it looks like:

//JAVAC    EXEC PROC=JAVA8UCG, 
// JAVACLS='smf/joblist'
//*
//* DD statement for the Java program 
//G.INPUT    DD DISP=SHR,DSN=SMF.DATA
//* Optional DD statements to demonstrate
//* modifing compile/go environments
//G.ADDENV DD   *
IJO="$IJO -verbose:class" 
export IBM_JAVA_OPTIONS="$IJO " 

Writing your Java program

Most examples suggest using an IDE like Eclipse to write and compile your program, transferring the class files to z/OS to run.

Eclipse is a very productive environment for writing Java and if you are used to using Eclipse, writing Java without it is painful. However, writing Java is no different to writing in any other language on z/OS and the simplicity of working with a single platform and familiar tools has a lot to recommend it.

I suggest getting a simple batch environment working on z/OS, and only then expanding the environment to use Eclipse, build and deploy scripts etc. if required. It is much easier to setup and debug more complex functions if you start with a simple, working batch environment.

Java programs must live in Unix directories due to the way Java uses the directory structure. ISPF option 3.17 provides a nice environment for editing z/OS unix files.

Tip: ISPF highlighting doesn’t have a Java option, but setting the language to C works pretty well for matching braces, showing comments etc.

Those pesky class not found errors

First efforts to run Java on z/OS often result in mystifying class not found errors. You look at the CLASSPATH, you can see the Java class file there, why can’t Java find it?

The answer lies in how Java classes are organized into packages. Packages avoid naming conflicts between classes, but Java requires that the classes are located in subdirectories that reflect the package name.

z/OS (and Windows/Unix for that matter), searches the exact locations specified (LINKLIST, STEPLIB, path etc) for executable programs. Java searches for classes in locations relative to the CLASSPATH directory, based on the class package name.

If we have a simple Java program:

public class helloworld {
    public static void main(String[] args) {
       System.out.println("Hello World!");
    }
}

This program doesn’t specify a package, so the source and class files must be in the directories specified in the SOURCEPATH and CLASSPATH.

However, if we decide to create a “helloworld” package and a “testhello” package (perhaps to share the function with other programs):

package testhello;
// This class doesn't do anything
// until called from another class
public class hello {
   public static void sayHello() {
      System.out.println("Hello World!");
   }
}

helloworld becomes:

 package helloworld;
 import testhello.hello;
 // This class has a main(...) method
 // which java calls to invoke the program
 public class helloworld {
    public static void main(String[] args) {
       hello.sayHello();
    }
 }

The helloworld class is in the helloworld package, so the PROCs specify:

// JAVACLS='helloworld/helloworld'

If the runtime CLASSPATH is set to
/u/andrew/java Java will expect to find /u/andrew/java/helloworld/helloworld.class
and /u/andrew/java/testhello/hello.class.

If your CLASSPATH is set to /u/andrew/java and the hello.class and helloworld.class files are located in that directory, Java will say they cannot be found… which can be puzzling to say the least. The answer is that the location relative to the CLASSPATH must match the package name.

Java source files are also required to use the same hierarchy. A class in package mypackage MUST be in the mypackage/ subdirectory or you will get a compilation error.

Actually, that’s not completely true… if you point the compiler at a Java file that specifies a package, that class will compile OK. It will also find other classes in the same package if they are in the same directory. However, it will locate other classes by going up the directory tree to what it considers the package root, and then looking for subdirectories according to package names.
The class files produced will be placed in subdirectories of the output directory.

This means that Java source code on z/OS must be in HFS directories – unfortunately, you can’t use regular z/OS datasets for your source code.

Jar files follow the same principle, except that the directory hierarchy is embedded in the jar file itself. You can see this if you extract a jar file with a zip program.

Naming packages

To avoid name clashes there is a naming convention for Java packages. According to convention, the package name begins with your internet domain name reversed, i.e. Black Hill Software uses com.blackhillsoftware. Subsequent components are based on your own naming conventions.

You might choose not to use the package naming conventions for your own programs, however if usage becomes more formalized e.g. you develop a library of commonly used functions it is a good idea to use names that adhere to the standard.

Either way, packages provide a good way to organize your programs inside the ~/java/src etc. directory structure. You can separate programs into packages, which allows you to organize the programs into subdirectories based on package name.

Conclusion

A set of JCL procedures for compiling and running Java programs makes Java much more useful on z/OS.

Once you can easily compile and run Java on z/OS it becomes an excellent language for writing small batch utilities and productivity tools.

What Next?

Why not try using Java for SMF reporting : EasySMF:JE Java Quickstart

Filed Under: Java

30 Day Trial

EasySMF and EasySMF:JE are available for a free 30 day trial. Download now and start using them immediately.
30 Day Trial

Information

EasySMF:JE Java API for SMF Quickstart

EasySMF:JE Sample 1 : SMF Records by type and subtype

Systems Programmer Friendly Java

Sending Email from z/OS using Java

Sign up for EasySMF News

Stay up to date. Enter your email address to receive updates about EasySMF.
unsubscribe from list

Black Hill Software

Suite 10b, 28 University Drive, Mt Helen, VIC 3350, Australia
PO Box 2214, Bakery Hill, VIC 3354, Australia
+61 3 5331 8201
+1 (310) 634 9882
info@blackhillsoftware.com

News

  • Finding UID 0 work on z/OS using SMF Data
  • Apache Log4j CVE-2021-44228 Information
  • Java vs C++ : Drag Racing on z/OS

Twitter

My Tweets

Copyright © 2023 · Enterprise Pro Theme on Genesis Framework · WordPress · Log in