The Minimum You Need to Know About Java on OpenVMS by Roland Hughes - HTML preview

PLEASE NOTE: This is an HTML preview only and some elements such as links or page numbers may be incorrect.
Download the book in PDF, ePub, Kindle for a complete version.

Chapter 1

Basics of Java

1.1 A Little Bit of History and Concept

Don’t worry, I’m not going to bore you to tears re-hashing the same history lesson every other Java book feels compelled to provide. Not my style. You can read about that for free on-line, or you can buy one of the oh-so-numerous books on Java which will burn an entire chapter covering the history.

First, let me ask for a show of hands, or whatever limbs you happen to possess, “How many of you consider yourself descent, good or seasoned C++ developers?” A very special form of Hell waits for you while learning Java. “How many of you consider yourself comfortable or good with pointers in either C or C++?” Ah, one or more chemical dependancies are in your future learning this language. Choose your poison now!

This may not come as a surprise to you, but I’m not the biggest fan of this language.  Having spent way too many years coding in C and C++ on viciously underpowered platforms tweaking cycles out of loops, I got really good with those languages. (Okay, I’m a lot better with C than C++, at least according to the purists.) This language offended me in many ways. While I am somewhat functional with the language, I am by no means an expert, and avoid it when possible. (I’m still trying to figure out how I got talked into writing this book. It sure wasn’t the publisher, because I’m self published!)

I think the biggest source of problems I and most other C/C++ programmers have with this language are rooted in the syntax and where the language came from. Java was not originally developed to be a Web language. That happened when marketing got involved.  Java was originally developed to be an embedded systems language. The kind of system which exists in your microwave, VCR and later model automobiles.

This concept wasn’t too bad at the time it was developed. Having done some near embedded development myself in the early days of pen computing under DOS (don’t ask!),  I can tell you that state of RTOS (Real Time Operating Systems) for embedded use was not good. Most shops had a collection of routines they kept using and tweaking with each new project, but commercial RTOS were way too expensive and not much cleaner. Almost everybody was hacking in assembler, with only the high end shops using C. (Ironically,  that’s pretty much the way it was when I last looked at the embedded market as well.)

In truth, the concept was phenomenal. Rather than bread boarding together a CPU,  some RAM, an EPROM and some IO devices; there were going to be these prepackaged chips containing all of that along with a VM which understood Java. These single chip machines were going to be built in volume and used for everything because they would be cheap enough.

That really was a nice idea. It may even happen at some point. I just don’t see it happening as long as there are enough grizzled old timers still working. Too many of them know how to hook together a 4-bit or 8-bit CPU, some RAM and some IO along with many years worth of hand tuned assembler. When they get done, it has a production cost measured in cents, not dollars. Higher end appliances, like cell phones and PDA’s are probably already using the once planned embedded Java. I just don’t see it working its way into your VCR or DVD player any time soon. Just how many brains do consumers who leave the clock flashing 12:00 really need their VCR to have?

When Java was being created, the creators wanted it to be quickly adopted. At least,  that is the reason I’ve always been given when I asked why they used the syntax of C++.  My personal opinion is that they would have gotten far more support from seasoned C/C++ developers if they had invented a completely new language syntax, or used something like FORTRAN.

The reason for this belief is mind set. When you pull up a screen of code and it looks like either FORTRAN, BASIC or COBOL you immediately go into the mind set for that language. Every seasoned developer does it. You don’t even know you do it. When you pull a Java source file up in your favorite text editor, you immediately go into C++ mind set, then are constantly frustrated by what is missing.

Had there not been a rash of GUI pick and point tools developed early on for Java, I think the language would have died on the vine. That’s my personal opinion. I will back that up with a test you can perform at your company. Ask someone that calls themselves a Java programmer at your company to develop an application without using any GUI development tools. Tell them to hand code everything in a text editor. No drag and drop components. Make it something small, like our Mega Zillionare sample application. What you will find is that most of the Java programmers are really GUI tool users who happen to know enough of the Java language to tweak things here and there.

Each and every time I need to discuss the syntax of Java with someone I have to vent my frustration so communication can occur in a productive manner. Remember when I said the C++ programmers had a very special Hell waiting for them, well here it is: You  will be completely consumed by the belief that Sun had a bunch of developers sitting  around who were physically incapable of learning C++, so they wrote a compiler which  handled as much as those developers could understand and tried to do the rest for them.

I know that some very learned people worked on the language and that they are considered way smarter than me. That’s okay. I’m not the only C++ developer I’ve met who has the exact same feeling. I’ve even seen it expressed in far more politically correct terms throughout the years in geek magazines. Early on in its existence I even read some interviews with the author of the language where it was stated they wanted to remove bad stuff out of C++. During the evolution of Java, a lot of the bad stuff got added back in because you simply couldn’t live without it. Let’s spend part of our history and concept time discussing the bad stuff.

Remember back in the first book when talking about C++ and I told you I couldn’t remember what the default protection was in a class? That was not completely honest.  I do have lucid moments from time to time where that knowledge randomly surfaces. If you never knew it, then I suggest you don’t bother learning it. The reason I suggest that,  and the reason I don’t remember on a regular basis, is I have had to work with Java upon occasion. The default protection method is different under Java. It is best you never learn what the default protection method is, and always code; public, private or protected.

Java was created back when “goto-less” programming was all of the rage. Java even went so far as to reserve the “goto” phrase as a keyword so other VM writers couldn’t add it. There is one thing you can always say about a “goto”. Code a big enough and complex enough program with lots of iterative changes handed out by the users, and you will need it. The very quiet replacement for this bad thing was the labeled “break” and “continue”  statements. Java got rid of the “goto” keyword and replaced it with two synonyms for “goto”. (When making that last statement in a bar around programmers whose religion is Java, it is advisable to wear machine washable clothing. It is good for at least one thrown drink and usually a fist fight.)

One of the biggest sources of bugs in code written by C and C++ developers is pointer usage. Many developers learning the language simply don’t understand the concept. This leads them to use uninitialized pointers and write over random sections of memory. The other problem is that they allocate a big chunk of memory and forget to free it. If you are working on a robust operating system, this last little bit isn’t a problem for your application. Once your process is exited the operating system will clean up the allocation you forgot to free. On lesser platforms it’s a real problem. Even after your process exits,  that memory is still allocated.

Java sought to solve both of these problems. The first solution was pretty drastic.  They removed pointers completely from the language. The second solution was built in garbage collection. We discussed garbage collection some in the first book when talking about relational databases cleaning up deleted rows in its tables. This garbage collection has to do with the freeing of unused items in memory, much like C++ does when objects go out of scope. Java went a whole lot farther. It provides no “delete” operator. When working with C++ you have both “new” and “delete” to give a programmer nearly complete control over object life time. Java, only lets you control when an object is created. It has to go out of scope, then wait for garbage collection, to actually be deleted. (Some developers refer to this as “going out to the curb” since that is where garbage pick up occurs for suburban residents.)

Another bad thing that went away was multiple inheritance. Right here is pretty much where I get that foul taste in the back of my throat that just won’t go away. It is also the point which leads me to the opinion about a bunch of developers that couldn’t learn C++.

Let me describe multiple inheritance in plain speak. Multiple inheritance is a concept in C++ (and most other OOP languages) which lets you create a shiny new object by inheriting all of the inheritable properties of more than one other object. These objects don’t have to have any relation what-so-ever. They can be at different levels in their own inheritance trees. How anyone managed to write a compiler specification for that I’ll never really understand.

Don’t go letting your eyes glaze over just now. This was the most powerful tool C++ gave us. It allowed you to solve unbelievably complex problems. I don’t want to give you a contrived example, and we aren’t covering C++ in depth in this book. Being able to combine multiple unrelated objects into a single new object definition was a tool which was indispensable with C++. Java learned its lesson by leaving it out. The later definitions of the language added it back in, but they don’t call it multiple inheritance,  they call it “interfaces”.

Oh, what a horrible choice of names “interfaces” was. This is a completely different definition of “interfaces” than most C++ programmers use. With respect to Java an interface is a collection of constants and abstract methods. They are not classes. An interface doesn’t declare any usable data items. When you choose to implement an interface within a class you must provide all of the methods declared in the interface and they must be at the same protection level as declared in the interface. When you declare your class you can inherit from only one other class, but you can implement many interfaces. When C++ programmers talk about interfaces to classes they are talking about the externally available list of methods and members. In C++, every class has an interface. With Java, only a class that “implements” an interface has an interface. (The keyword is implements not implement.)

If your eyes glazed over reading that last paragraph, it’s okay. There is a reason I didn’t talk much about interfaces when we discussed C++ in the last book. I didn’t want to get you far enough into the language of C++ to make your journey through Java painful.

Java was originally intended to be pure OOP (Object Oriented Programming).  Everything, short of the most basic data types, is a class. You can’t even have a stand alone “main()” function as you can with C++. The philosophy behind C++ was you could use it as a better C until you got comfortable enough with OOP to start doing more with OOP. With Java, you have to do a running cannon ball into the pool of OOP. There simply is no other way.

Nearly every book on Java you buy will show you how to write applets in Java. In order to run the applet you will need to write some HTML and use a browser. This book will not bother with applets or browsers. The concept in this book is how to convert your existing core business applications to use Java, yet still preserve your investment in the most stable platform on earth. You will also want to preserver your investment in character cell terminal emulators and character cell terminal emulators cannot run a browser.

1.2 Data Types

Java supports a limited set of core data types. The distinction between a core data type and other data types is the lack of class. Core data types are understood directly by the compiler without using any library functions. All other data types are class definitions and require the run time libraries. There are only 3 groups of core data types: numeric,  boolean, and character. Do not leap to the conclusion that character is how you deal with string values in Java. While that is true for many 3GL’s, it is not true for Java. To deal with string data types, you have to use the String class.

During the course of the first book I mentioned several times the problems of porting data from one hardware platform to another. Some machines are Big Endian and others are Little Endian. Additionally, many machines developed their own proprietary numeric data types for handling floating point values. Java solved that problem with the VM.  Every data type has the exact same byte order no matter what machine the VM was implemented on. This means that if you create a flat data file using raw numeric values on one machine, it can be read by Java on another machine. All bets are off with indexed files that are native to a specific platform. The Java language itself doesn’t provide any indexed file support.

One of the biggest selling points for most GUI development environments is that they give you some form of indexed file library along with database access. The catch was any machine you wanted to use this data on had to have the database engine, or at least the GUI development environment installed. As I said, Java is some of the most expensive “freeware” you can get. If you surf around on the Web you can usually find some B-tree indexed file systems written completely in Java. Good luck finding free versions of them though, since most developers have bad habits like eating and living indoors.

There are six core numeric data types supported by Java.

img3.png

Remember that there are eight bits to a byte on most machines these days, then look at the following C code.

img4.png

When working with C a long is 32-bits. The long data type in Java corresponds to the quadword data type I spent so much time harping about during the first book. Get this difference down.

Since the core numeric types can be restrictive to some developers, some additional numeric classes were added to the language. These classes are BigDecimal and BigInteger. They can be used to create numbers of arbitrary width and precision. We won’t be messing with them in this book. Just remember they are there in case you need to create some 128-bit floating point values.

With respect to floating point data types, Java stole some pages from the FORTRAN specifications. It has specific values for NAN (Not a Number), Negative Infinity and Positive Infinity. You get NAN results when performing illegal operations, such as dividing by zero or multiplying by infinity. Since division by zero happens a lot in the business world, this is a good thing.

Boolean is a data type most of us think we should know, but we don’t. Under most languages boolean values are simply integers that use either positive/negative or 1/0 to indicate true/false. Under Java there is a specific boolean data type which can have only true or false as its value. If you forget to initialize your boolean it is initialized to false.

Keep in mind that Java provides a default initialization for all class data members,  but not locally scoped variables. We will discuss more on this later, or you can open the previous book and skim through the scope discussion for the C/C++ chapter.

The character data type is the one which trips up most developers coming from other languages. When we covered BASIC, FORTRAN, COBOL and C/C++ in the previous book a character was always 8-bits wide and held an ASCII value. With the exception of the currency symbol, the representation of these characters was standard across platforms for the first 127 values. The last 128 characters were a free-for-all dependant upon the active code set on the machine and what a developer chose to load for them. (We did not cover loading different values in the last 128 characters. That is something usually only done by PC developers to draw graphics.)

The creators of Java decided they wanted it to be an international language, not follow existing trends. As a result the character values used by Java are 16-bits wide and are Unicode characters. For the most part, Unicode kept the first 127 the same as ASCII,  simply because of the installed base. I won’t go into the ins and outs of Unicode. Those of you wanting to know more about Unicode can visit http://www.unicode.org.

1.3 Everything is a Class (almost)

Since the creator(s) of Java wanted it to be a pure OOP language, almost everything is a class. The previous section covering the core data types is just about the only thing which isn’t a class, but can only be used from within a class. Your application has to have one primary class with a “main()” method declared in it in order to run.

The first class you need to get familiar with is String. Technically the full name of the class is “java.lang.String”, but since it is the core API you can declare instances of it just using String. When you place a quoted string in your source listing the compiler doesn’t just create an array of characters, it creates a String object (instance of a String class) to contain those characters. Those characters will magically be flagged for deletion whenever they go out of scope.

Let me go into this just a little further.

String mantra = “I am a real programmer”;

mantra = mantra + “, I studied logic without a language.”;

After these statements execute there are actually three string instances and one StringBuffer instance in memory. At some point in time Java will get around to garbage collecting the temporary StringBuffer object that was used to concatenate the two quoted strings together. In order to understand why that is, you need to know one thing about String objects; they can’t be changed. Oh, we add, subtract, change and otherwise mutilate strings in our code, or so it appears. Behind the scenes Java keeps making new ones. A StringBuffer class is the dynamic class of string which allows for string manipulation. Once it has been manipulated the result is given to a String object and will stay as it is until the garbage collector tosses it back on the heap.

I know that the above example was a lot to swallow this early on, but we shall endeavor to persevere. The next section will help sweep it up for you.

1.4 Reference not Pointer

When we covered C++ we talked about passing objects by reference. Where a reference was a very special kind of pointer which made the object appear as if it were local to the receiving method (function). Java takes references to a new level. Everything which isn’t a core data type is a reference. In the previous example, where the syntax made it look like we declared a String object named mantra, we actually declare a String object of unknown name and mantra was a reference to that String object. This is a difficult concept for many developers.

To understand how we end up in this situation you have to remember Java runs under a VM (Virtual Machine). When we talk about compiling Java we talk about generating a P-compiled file which the Virtual Machine understands. When we talk about compiling our previously covered languages we talk about generating binary OP codes understood directly by the CPU. As programmers we tend to think our program is doing what we coded. When speaking in terms of Java, this is not true. The VM is doing what we ask.  The P-compiled translation generated something along the following lines:

Hello VM. Go create me a String object having the value of “I am a real programmer”.  When I refer to that object in the future I am going to call it mantra. Feel free to delete it when you don’t think I need it any more.

The key phrase in this conversation is “when I refer to that object”. There in lies the fundamental principle of Java. Your “program” doesn’t own anything, it never has, and it never will. It is a slave begging for favors and services from its master, the VM. When the VM decides you no longer need something, it takes it away without telling you.

1.5 The Sandbox

This master-slave relationship lead to a concept you will hear talked about quite a bit by Java developers, the sandbox. With version 1.0 of Java the sandbox was introduced.  Code which was downloaded rather than written locally would run in a sandbox. What that code could and could not do was controlled by the SecurityManager object. The abilities allowed by the sandbox change based upon settings you or your system manager tweak in the VM and by new releases of Java.

I’m bringing up the sandbox here, because as application developers, it is useful for you to envision all code as running in a sandbox. That’s really the concept behind the VM.  One sandbox may have more toys than another sandbox, but it is really just a sandbox.  Those of you reading this who own cats feel free to conjure up a humorous image of the Java sandbox and what is going on there.   Basics of Java

1.6 Garbage Collection

I need to discuss just a little bit about garbage collection before moving on to more interesting topics. At various places already I have mentioned garbage collection. This is automated memory reclamation. For lack of a better description, each little sandbox keeps a list of objects it no longer needs. When the garbage collector makes its rounds it looks at each sandbox and starts deleting items off that list, returning memory to the VM pool.

Since Java was originally designed for embedded systems which are traditionally underpowered, performance was of paramount concern. Besides wanting to eliminate pointers, the creators wanted to remove the burden of freeing memory allocations from the application developer. They placed that burden on the systems developer coding up the VM. A lot of heated arguments happened about where and when to do garbage collection.  Ultimately, it was decided to have the VM launch a task at priority zero so it only got time when the system was idle.

Developers from days gone by on OpenVMS remember fondly the NULL process. You used to be able to see it when you typed in the command:

$MONITOR PROCESS/TOPCPU

Alas, the NULL process is now hidden away from casual observers. This used to be a good guide in determining why your system seemed sluggish. If the NULL process was getting a lot of time you knew the problem was disk IO. Either you had a “hot spindle” or you had a pair of big jobs beating each other up trying to lock the same records. (A “hot spindle” is a term used to describe a disk performing massive amounts of IO.)

When your OpenVMS box is running at 80% capacity or less, this method of clean up works well. The 80% is a number I learned back on the VAX hardware. I don’t know what the number is for Alpha hardware or Itanium hardware. I assume it is now closer to 90%.  Regardless of where that magic percentage threshold is, or what platform you are on,  when you exceed it, all of those clean up tasks hooked into the idle process won’t get any time.

What this means in terms of Java is that garbage collection will not occur.  Applications will continue running on the machine, although they will seem sluggish, but memory resources will no longer free up. That means that even when your application finishes, the sandbox it ran in won’t go away because the garbage collector never got any time to come around and take out the trash. If one or more of the processes binding up the CPU doesn’t complete, you will eventually exhaust all virtual memory and things will start crashing.

Those of you coming from Windows and Unix type environments will envision this as a complete system crash. Nothing could be further from the truth on OpenVMS.  Remember back in the first book where I made you look at UAF (User Authorization File) entries? Every process runs under a user ID. Each user ID process has an amount available to them determined by the entries in the UAF for that user. If you are starting and stopping a lot of Java programs under a standard user account when the garbage collector is barred from doing its job, you will most likely be the process which crashes.  Look on the bright side though. When your process goes away, it will free up some CPU cycles so the garbage collector can finally clean up after you.

1.7 No Include Files or Preprocessor

One of the most abused concepts in the C language was the preprocessor. Developers did nasty things with macros that would collide with other macros creating a complete debacle for the hapless coder trying to make two commercial libraries work together. C++ tried to help alleviate the problem by adding namespaces to its language definition.

The creators of Java decided, when it came to header files, that dog won’t hunt. They don’t exist in the language. But it didn’t take long for that idea to create its own little train wreck. Without some method of inclusion from external sources, you couldn’t use libraries together without cutting and pasting large amounts of code into your source file.

Enter the “import” statement. This isn’t like the #include directive you find in C, even if it does look a lot like it. The import statement allows you to bring in either specific class definitions from packages, or entire packages.

What’s a package you ask? A package is a group of classes that get compiled into a package. (Nice Webster, eh?) At the top of each class source file you want to be part of a package you stick in the statement “package some.package.name;” Once you have compiled all of the classes for the package, and built the package, you can then reference it in your application source file by coding “import some.package.name.SepcificClass;” to get only one class or “import some.package.name.*;” to get the entire package.

While it may seem easier to just import the entire package, don’t. These aren’t header files and Java isn’t polite like C. When working with C you could include every header file you though you might need and as long as they didn’t declare any global data, they had no impact on your executable size. With Java, your P-compiled little class suddenly becomes an 8000-lb. Gorilla when it loads.

Notice the format of the package name with all of the dots in it. This is one part of Java that seems to be tied completely to the Web. The convention for naming packages is to invert your domain name and add some stuff. If you happen to be a company or person with a registered domain name, this works out well. For those of us working internally, we have to cobble up a domain name on our internal network. The cobbled up domain name I put on my internal network is logikal.com. Packages I declare in this book will be com.logikal.something.

1.8 Constructors and Finalizers

Since we have a prerequisite that you have already read the previous book, you are already familiar with the concept of constructors and destructors from the section on C++.  The constructor is tasked with allocating storage for the object and its core data items. It does not allocate storage for data items which themselves are classes. The constructors for those objects are tasked with that. If you don’t bother to code a constructor for your class the compiler will generate a default constructor for you. Unless your classes are simple, you may not like what it does.

If you code any constructor in your class definition, the compiler will not generate a default constructor for you. This means that if you code a constructor which accepts parameters to populate data items with, you will also have to code a version which accepts no parameters if you want that functionality.

Your constructor has the same name as the class with no return value. You can overload your constructors just like you can overload methods.

Remember when we discussed C++ in the last book we talked about a destructor being the same name as the class but having a “~” in front of it? Java decided to go its own way here. Destructors in Java are called finalizers. They are actually a method named finalize() which accepts no parameters, but can flag exceptions it might throw. (We will talk about exceptions much later.)

Always declare your finalize method as a protected void method. This stops someone from being either malicious or stupid. If it isn’t protected it could be called from anywhere. A finalizer method is something people don’t code much. The reason is they don’t do much. The compiler generates the code to flag all of the items for garbage collection. The only things you wish to do in a finalizer is close files and release external resources. A case in point would be the two classes we declare for accessing RMS indexed files in the previous book. The only thing they did was call the close() method.

1.9 Arithmetic Operators

It will come as no surprise to you that Java supports most of the arithmetic operators from C. Here is a quick and dirty table for you. Precedence is in descending order with one being the highest.

img5.png

Some of you may remember the little saying I imparted to you in the last book.

Please Praise     Powers Parenthesis

My Dear     Multiplication Division

Aunt Sally     Addition Subtraction

It still works here. I’ve yet to find a place where it didn’t work. Since modulus is really a division it occurs at the same level. Java does not give us the “**” operator that BASIC did for raising a number to a power. You have to use the power() function of the math package.

1.10 Relational Operators

We get the same set of relational operators with Java that we had in C/C++.