Unix on the Mainframe: COB2 compiler, for Java calling COBOL - java

I've been working on trying to get COBOL and Java to interact with each other on the mainframe, and have run into trouble with specifically the cob2 compiler, which is the Unix on the mainframe equivalent.
I haven't seen many user experiences with this compiler online, so I was wondering if I asked a more direct question, people would reveal their insight.
IBM has several examples of Java calling COBOL DLL's either directly or indirectly, but they ultimately boil down to compile the COBOL as a dll, use System.load, compile Java and run. These examples haven't worked for me for the following reasons.
When using cob2 with the -c option, it is purported to generate a .o object file. This has not happened for me, although it did generate an empty .lst file. I was able to get around this by simply skipping the -c step and compiling and linking using this series of commands:
` sh ${COB2HOME}/bin/cob2 -o ${DIR}/c2jcr.o
-qdll,thread,case=mixed ${DIR}/c2jcr.cbl;
${COB2HOME}/bin/cob2
-o ${DIR}/libc2jcr.so
-bdll,case=mixed ${DIR}/c2jcr.o
${JAVAHOME}/bin/j9vm/libjvm.x
${COB2HOME}/lib/igzcjava.x `
This appears to provide the .so library that is required for link with the Java program, but upon investigation of the load, and during run, the system declares that the LE CSECT CEESTART is not there.
Am I missing something in my cob2 library that has these LE modules, or somewhere in my scripting? I tried pulling in loads from the mainframe compiled with the LE modules intact and ENTRY CEESTART explicitly stated in the link step, but could not get any further than "UnsatisfiedLinkError" with "Internal Error".
Any wisdom is greatly appreciated, especially if you've gone down a completely different route to call COBOL from Java. Thank you very much.

After conferring with IBM, it turns out I had a couple things missing.
You must have a STEPLIB environment field set to the location of your COBOL compiler on the mainframe, so it can find your IGYCRCTL module.
Second, like other COBOL 5+ compiling, you must allocate a gargantuan amount of space in order to compile. 2 GB is not enough. Since I don't have permission to reallocate this in Unix, I ran a BPXBATCH job with REGION=0M.
After those two changes, -c compiles came out as normally. The "workaround" I provided in the question is completely incorrect. You must use:
sh ${COB2HOME}/bin/cob2 -c -qdll,thread,case=mixed ${DIR}/${COBPROG}.cbl
as your compile step, and the rest is just linkage.

Related

how to avoid using javac -cp

I have a Java class which uses a .jar file.
Every time that I want to compile this class, I have to do something like javac -cp ".:myJar.jar" myClass.java and every time that I want to execute it, I have to do the similar thing but with java instead of javac.
Is there a way to avoid doing this?
I know that I could put this jar file into my class path but I don't want to do that. I don't neither want to do a maven projet.
There is nothing preventing you from using an IDE, taking advantage of all its super useful features when developing the program, and then submit just the source code and associated jars to the professor.
Advantages of using IDE that your professor don't need:
Syntax color-coded editors with auto-complete.
Built-in display of javadoc, so you know what all the built-in Java methods do, and how they work.
Instant high-lighting of syntax errors.
Never having to compile the code, since IDE always keeps the code compiled.
Easy single-button execution of the program when you want to run it.
Debugger. Very important feature when your code is not working as you intended.
... more ...

What are the limits to JShell?

I found this question, and this other, so intriguing that it begs several questions, at least for me:
Rather open-ended question, but where is jshell confined to? Obviously, GUI apps aren't in the domain for jshell solutions, or IDE replacement:
Out of scope are graphical interfaces and debugger support. The JShell
API is intended to allow JShell functionality in IDEs and other tools,
but the jshell tool is not intended to be an IDE.
Bonus points for Venn diagrams or other visuals.
Certainly, snippets should be limited in size. I'm more asking what sort of problems cannot be solved with snippets.
see also:
https://openjdk.java.net/jeps/222
https://openjdk.java.net/jeps/330
Answering the updated question
All problems can be solved with snippets (and with a sufficiently complicated shell script, too). But JShell is best used to debug and learn java - a full-fledged program is much more flexible for all other use-cases.
JShell, .jsh and java MyClass.java
JShell is an interactive shell for trying out java code. Essentially, it is a REPL for Java.
Since JShell is all about you typing in code snippets, which it then evaluates, and it often makes sense to put those snippets in a file instead of writing them several times, JShell supports .jsh scripts, which contain collections of snippets to be interpreted by JShell. In this sense, this is similar to bash accepting .sh files or command.com accepting .bat files -- typing them line by line is equivalent to importing them.
Single-source java-file execution is a very different beast. It is sugar that replaces, from JDK 11 onwards,
java MyClass.java arg1 arg2 arg3
by your local scripting equivalent of writing
TMPDIR=$(mktemp -d)
javac -d $TMPDIR MyClass.java
java -cp $TMPDIR MyClass arg1 arg2 arg3
rm -rf $TMPDIR
This allows single-source files to be quickly executed from the command line with a single command, and without leaving their compiled classes all over the place (no actual temporary directory needs to be created, as java can store those classes in memory). Since they already had 3 other execution modes in java (for classes, jar-files and modules), it is no great stretch to add this as a fourth one.
Since OP wanted a picture:
Java as a scripting language
Now that the distinction is clear (.jsh is for use with JShell, single-source java executables are only for, you guessed it, single-source java executables), what about using Java as a scripting language?
You have always had the option to write a launcher; for example,
#!/bin/bash
java -jar MyApp.jar
has worked for ages. It was technically possible to name a class directly, but not too useful, as jar files are far more handy when distributing binaries -- for one thing, they avoid mirroring the package structure as a bunch of folders. Having a launcher script as separate from the actual java code was, however, still somewhat unfriendly: you now need to keep both together, or at least have the launcher be able to locate the actual .jar to launch.
Now, they have also introduced the following shortcut: regardless of file name or extension, you can distribute your java source with a "shebang prefix" as follows:
#!/path/to/java --source 11
<source of MyClass.java>
mark it as executable, and launch it from the command-line just as you can launch any other executable. For example, copy and paste this into a helloworld file (and fix the jdk location before attempting to run it):
#!/opt/jdk-11.0.1/bin/java --source 11
public class Test {
public static void main(String ... args) {
System.out.println("Hello " + (args.length == 0 ? "world!" : args[0]));
}
}
After marking it as executable, you can launch it directly with
$ ./helloworld
Hello world!
and it even takes its arguments right:
$ ./helloworld Bob!
Hello bob!
For small programs, and provided you do not need to go outside of the JDK to pull in additional libraries, it will now be vastly easier to distribute java code for command-line use.
Java will still not be a "scripting language" (it will never compete with, say, python), but
it has a very nice REPL loop
you can execute short programs a lot easier
Well, of course, its confined to a bring a normal REPL utility in terms of scoping what an IDE and graphical user interfaces could provide. I would talk of more about its capabilities as compared to single source code programs. The features that keeps it apart still from single source code programs:
a history with editing
tab-completion
automatic addition of needed terminal semicolons and
configurable predefined imports and definitions
As mentioned in the alternatives to Single-File Source-Code Programs JEP as well:
We could delegate the task of "one-off runs" to the jshell tool. While
this may at first seem obvious, this was an explicit non-goal in the
design of jshell.
The jshell tool was designed to be an interactive
shell, and many design decisions were made in favor of providing a
better interactive experience.
Burdening it with the additional
constraints of being the batch runner would detract from the
interactive experience.
!!! Limitations and behavior!!!
On the other hands, few limitations(assumed functionalities) that one would mostly find while performing a hands-on using JShell rather than simply reading the docs would be :
use of final variables final variables are not functioning well in jshell
of course Debugging with JShell
integration of jshell with IDEs Java 11 JShell inside Intellij IDEA
disabling history Disable JShell history
redeclared variables should be reset In jshell-11, why does a redeclared reference variable that resets to null still have a type?
create module using jshell Create Module in JShell in Java 9
importing private package classes Importing Package-Private Classes to JShell
scope of objects Access to "parent scope" in JShell
clear jshell console How to clear Java 9 JShell Console?
!!! Features and more !!!
More details over the links that gives it an upper hand over Single File Source Code Programs :
why and how Why and how do you use JShell?
import classpath for a project In JShell, how to import classpath from a Maven project
run an application via JShell How to run a java application with jshell?
set custom feedback modes Create custom feedback mode in jshell
load scripts on startup Different ways to load script on jshell startup
list active methods List all active methods in jshell
run a jshell file How to run a JShell File?
execute javascript with jshell How to execute a java script with jshell?
how to use method references in jshell Is there a way to use method references for top-level functions in jshell?

Issue running java program from batch file, runs fine in IDE

I'm doing some basic java homework for a class on my new laptop - issue is, I can't seem to get the program to compile and run from my batch file using the directions the instructor gave me.
I've set the Path variable to my JDK inside the Environment Variables settings.
My program is a simple shipping program to keep track of shipment information - I have the program working flawlessly in NetBeans (which our instructor advised us to use for developing the code), but he's going to be testing them using batch files, so we're also advised to test them on our systems with one we create prior to turning them in - pretty straightforward.
Issue is, I cannot seem to get this to work. I've never done it before, but I've used .bat files to compile and run C++ programs, as well as using makefiles on a unix system, so I feel like I'm absolutely stupid for not figuring this out on my own, but none of my searches have returned any fruitful solutions that help at all.
My program consists of 3 .java files:
Shipment.java - an interface that contains abstracted methods that are implemented in the ShipmentHW1 class
ShipmentHW1.java - a class that implements the abstracted methods from Shipment and has constructors, etc to create a usable object
TestShipment.java - the main class of this program, which utilizes and creates ShipmentHW1 objects based on preset parameters. This is super duper basic stuff here, and again, it runs perfectly fine inside the NetBeans IDE.
The instructions given to us state to have the batch file inside the package directory (which in this case I've set aside a seperate folder on my desktop titled "shipping", which is the package name - shouldn't be any issues there), where the 3 .java files are located as well.
They say if you don't need to explicitly list the path to the JDK, then you can simply have
javac TestShipment.java
java TestShipment.java
pause
Afterwards I get errors talking about how it "cannot find symbol Shipment s = new ShipmentHW1();"
I've tried adding imports, but since they're in the same package it shouldn't even be an issue.
Directory path is
C:\Users\X\Desktop\shipping
All 7 files are contained within:
TestShipment.java
TestShipment.class
Shipment.java
Shipment.class
ShipmentHW1.java
ShipmentHW1.class
doHW1.bat
Does anyone have any idea? I can provide more information if I've been too vague
Also, I'm on Windows 8 if that makes any difference
Solved
Batch file now reads
javac TestShipment.java Shipment.java ShipmentHW1.java
cd ..
java shipment.TestShipment
pause
and it works like a charm. Anyone have any ideas why I had to call the package.class instead of just compiling it regularly?
Try doing
javac TestShipment.java
java TestShipment
pause
Without seeing the contents of TestShipment.java, I'll assume you have some dependency on the Shipment and ShipmentHW1 classes. As such, when you execute a program that uses the TestShipment class, you need to have the .class files for each of the three (and any other dependencies).
So you will have to compile Shipment.java and ShipmentHW1.java as well before running your java command. If they are in the same package, you're good, if not, you will have to specify an appropriate value for the -cp option.
When running java with a class name, you need to specify the fully qualified class name.
If your .java files are declared to be in the 'shipping' package, then you probably need to be running java from the parent directory of 'shipping', e.g.
cd <path>/shipping
javac TestShipment.java
cd ..
java shipping/TestShipment

Speed up application start by adding own application classes to classes.jsa

To speed up the startup time of the JVM, the Sun developers decided it is a good idea to precompile the standard runtime classes for a platform during installation of the JVM. These precompiled classes can be found e.g. at:
$JAVA_HOME\jre\bin\client\classes.jsa
My company currently develops a Java standalone application which brings its own JRE, so it would be a fantastic option to speed up our application start time by adding our own application classes to this jsa file, too.
I don't believe the JSA file was created by magic, so: How is it created? And how can I trick the JVM into incorporating my own classes?
EDIT: I already found out the following:
The classes.jsa is created by the command
java -Xshare:dump
The list of classes to incorporate in the dump can be found in $JAVA_HOME/jre/lib/classlist.
I even managed to add my own classes here (and to add them into the rt.jar for java to find them), and to generate my own checksum below the classlist file.
The final problem is: Only classes in the packages java, com.sun, and org.w3c seem to be recognized, if I leave the same classes in their original packages, they won't be loaded. I searched the whole OpenJDK source for pointer about this, but it seems to have something to do with protection domains. If someone is interested enough in this topic and knowledgeable enough, please add some pointers for me to investigaete further.
As of Java 8u40 (and Embedded Java 8u51), Java now supports Application Class Data Sharing (AppCDS) (ie your own classes in the shared archive). On our embedded java, we've found a startup improvement of >40%! Pretty awesome for almost no work on our part...
https://blogs.oracle.com/thejavatutorials/entry/jdk_8u40_released
You were almost there, you only need a couple steps to make it work. To add your own classes to the clients.js you need the following steps:
The qualified name your classes (you have it)
The classpath of these classes (you have it)
Know how to recalculate the checksum (you have it)
Dump the new file, providing the classpath of the classes you are now precompiling with the Java classes.
Run the program, providing the same classpath that you used to dump the new classes.jsa
To provide the classpath where are the classes you are adding to the classlist, use the -Xbootclasspath/a command. It will append the directories/JARs when JVM is searching the places where the boot classes are. The default space for the classes.jsa is quite small, if you need to improve it you can use the -XX:SharedReadWriteSize and -XX:SharedReadOnlySize commands. Your dump command you look similar to this:
java -Xshare:dump -Xbootclasspath/a:C:/myfiles/directoryA/;C:/myfiles/directoryB/;C:/myJars/myJar.jar;
The last step is just run the java application normally, rememebering of turn on the share mode. You also need to add the Xbootclasspath excatly as you added on the dump. It will look similar to this:
java myapp.java -Xshare:on -Xbootclasspath/a:C:/myfiles/directoryA/;C:/myfiles/directoryB/;C:/myJars/myJar.jar;
Now every class that you put on the classlist is being shared with other instances running in the same JVM.
Interesting idea. As I read it though, it's used for sharing data across VMs and for speeding up classloading, not compiling. I'm not sure how much of a boost you would get, but it might be worth a try if you have a big lag at startup already (though the VM already tries to mitigate that).
As for trying it yourself, it appears this file is normally created when the Sun VM is installed, but you can also control it. Some details are in this older Sun Java 5 Class Data Sharing document (which you may have already seen?). Some Sun Java 6 docs also mention it a few times, but don't add much to the documentation. It seems it was originally an IBM VM feature. And, to continue the link dump, it's explained a bit in this article.
I don't personally know much about it, so I don't know how you might control it. You can regenerate it, but I don't think it's intended for you to put custom stuff into. Also, even if you can "trick" it, that would probably violate a Sun/Oracle license of some sort (you can't mess with rt.jar and redistribute, for instance). And, all that said, I doubt you would see a serious improvement in startup time unless you have thousands or tens of thousands of classes in your app?
(And this isn't really an answer, I know, but it was too big to fit in a comment, and I found the question interesting so I investigated a bit and put links here in case anyone finds the same info useful.)
It took a little figuring out but I have 4 Java8 VMs (version 1.8.0_162) running using shared classes. The following script was used to set up and test sharing and with a little modification could be used elsewhere:
#!/bin/bash
# Libraries to load
LIBS1="./lib/protobuf-java-2.6.1.jar:\
./lib/jetty-server-9.2.18.v20160721.jar:./lib/jetty-util-9.2.18.v20160721.jar:./lib/servlet-api-3.1.jar:./lib/jetty-http-9.2.18.v20160721.jar:./lib/jetty-io-9.2.18.v20160721.jar:\
./lib/derby.jar:\
./lib/json-simple-1.1.1.jar:"
LIBS2=":./lib/GTFS.jar"
# Uncomment these lines for the first phase where you are determining the classes to archive. During this phase aim to get as many classes loaded as possible
# which means loading a schedule and retrieving the stop list and next vehicle information
#
#APPCDS="-Xshare:off -XX:+UnlockCommercialFeatures -XX:+UseAppCDS -XX:DumpLoadedClassList=../GtfsAppCds.lst"
#java -Xmx512m $APPCDS -Dderby.system.home=database -classpath $LIBS1$LIBS2 com.transitrtd.GtfsOperatorManager
# Uncomment these lines when the class list is created and run to create the shared archive. Classes marked as unverifiable will need to be removed from the
# archived class list in GtfsAppCds.lst and the lines below run again. LIBS2 above contains jars which are left out of the archive. These are jars which change
# frequently and would therefore cause the archive to be frequently rebuilt.
#
#APPCDS="-Xshare:dump -XX:+UnlockCommercialFeatures -XX:+UseAppCDS -XX:SharedClassListFile=../GtfsAppCds.lst -XX:SharedArchiveFile=../GtfsAppCds.jsa"
#java -Xmx512m $APPCDS -classpath $LIBS1
# Uncomment these lines when wishing to verify the application is using the shared archive.
#
#APPCDS="-Xshare:on -XX:+UnlockCommercialFeatures -XX:+UseAppCDS -XX:SharedArchiveFile=../GtfsAppCds.jsa -verbose:class"
#java -Xmx512m $APPCDS -Dderby.system.home=database -classpath $LIBS1$LIBS2 com.transitrtd.GtfsOperatorManager
Note that the shared archive file (i.e.the jsa file) is architecture dependent and will need to be built on each target platform type.
Also if a jar uses sealed packages a security exception is thrown, see
https://docs.oracle.com/javase/tutorial/deployment/jar/sealman.html
for information on sealed packages. This was the case above with derby.jar but the problem could be solved by unpacking the jar file, replacing Sealed:true with Sealed:false in the manifest and repacking it.
jars built with older versions of java cannot be used in a shared archive, in the case above the derby version needed to be upgraded from 10.10 to 10.14 to benefit.

Java compiled with gcj using javax.comm api. Possible?

I have a java program that I'm required to compile into a Linux native program using gcj-4.3. This program requires serial port access. The javax.comm api provides serial port access but I'm not sure how to get my compiled java program to use it.
The target box has Java installed, but of course my compiled program isn't running in the JRE...so I'm not exactly sure how I can link in the comm.jar file or how that file can find the .properties file it requires.
I wonder if I can just compile the comm.jar allong with my .jar file and link the two object files together. Can my code then reference the classes in comm.jar?
Thanks in advance for your help!
I'm not an GCJ expert but I have some suggestions (I'm not providing the syntax, this will require some exploration that I didn't perform):
first, I think that you'll have to compile comm.jar into a (shared) library,
then, you'll have to link your code against the library,
finally, use the GCJ_PROPERTIES environment variable to pass properties to the program at invocation time.
The following pointers might be helpful to implement this:
GCJ---The GNU Compiler for Java (great resources IMO, covers all the steps mentioned above)
GCJ – Getting Started (more an intro but still nice)
Compile ActiveMQ with GCJ (more use cases but I don't think they apply here)
And of course, the official documentation :)

Categories