Welcome to the 37th edition of "The Java(tm) Specialists' Newsletter", sent
to 2103 Java experts in 62 countries. This week, my friend
Sydney Redelinghuys has stepped in and
provided the ideas for this newsletter, as well as most of the writing. Sydney
was the brain behind the SoftHashMap newsletter that also made it onto
DevX
. I consider Sydney to be the 2nd best Java programmer that I know (position
#1 is already given to
Paul), [SR: So what position is given to HK] [HK: Position # 0 of course!
;-] but I marvel at the designs Sydney comes up with, I don't know anyone with
such a knack for cool designs. Sydney found a copy of the Design Patterns
book in the home economics section of his university (I will refrain from making
comments regarding his university based on that last comment )).

Enough of my jabbering, let's see what Sydney, the one-legged Java Guru has
to say ...

Checking Your Classpath Validity

The classpath - like most programmers, I really struggled with it in the
beginning. I first cut my teeth on Java in middle of 1996 when I was a student
doing some vacation work, as part of an experiment of using JDK 1.0 to solve the
world's problems. As you might imagine, I caused more problems than I solved. I
must've been the most underpaid Java programmer of all time - in today's South
African currency terms, I only got US$ 272 for 2 months work (and that was with
a 100% bonus)! Enough reminiscing, back to class paths. It is not that class
paths are difficult to understand, it is just that it is too easy to get them
wrong and not easy enough to locate errors, especially if you are used to
case-insensitive NT paths. The classpath problem is so part of the Java culture
that even The
Onion reports on it! [HK: A must-read magazine for TJSN subscribers]

Even after I got more experienced it still seemed to eek its way into builds.
In those days (before Ant and what not) we used to write huge batch files to
check that all the required jars were available, I believe the company in
question still does it [HK: Actually, we had a chap who had an MCSE in WinNT
3.51 who was a real whizz at batch files. This, perhaps, was to our
disadvantage.]

These days I am involved with Websphere, a product aimed at the Java
professional who thinks he knows how Java works. This product will make even the
seasoned Java expert quiver at his knees when he gets a MarshallException
at run-time due to linkage errors often caused by an incorrect classpath. Note:
in Websphere the classpath can be specified on at least three levels
(container, server and node levels).

My first attempt at solving the marshall exception was to add another dynamic
layer like any true geek developer. [HK: Sydney is truly the master of adding
dynamic layers. That first Java program that he wrote for US$ 272 over 2 months
took US$ 13500 of real professional Java programmers' time to debug.]
Java does tend to make it too easy to do this with reflection, dynamic class
loaders, dynamic proxies, soft references and all other kinds of weird &
wonderful constructs this newsletter likes to comment on.

So, my first solution was to load the class files dynamically (via
Class.forName(...)) and then to simply try catching the
ClassNotFoundException:

Of course this worked, so now I could see the exception other application
servers probably would have provided me with originally.

This really bugged me. I had to write compilers at varsity and I always
thought I was doing the world a favour by doing compile time type checking etc.
It surely is better to find a bug at compile time than at run-time, especially
if your build-deploy cycle spirals into an affair that can take hours. [HK: With
the batch files that we had originally the build cycle took so long that we
could only do a weekly build!] [SR: I think the most time consuming part of that
process was actually Source Safe]

Ant (or other similar build-tools) could solve some of these problems,
unfortunately some of our components have to be deployed manually due to our IDE
keeping information hidden. [HK: Isn't your IDE written in Java - perhaps you
could use reflection to find the information dynamically and ... ] [SR: No such
luck it is actually written in SmallTalk.]

So I asked myself: "Why does Sun keep the classpath hidden at runtime?"
I decided to start digging in the jdk api's.

To load classes, the default class loader needs access to the classpath. The
default class loader is very easy to get hold of, via the
java.lang.ClassLoader.getSystemClassLoader static method. Unfortunately,
the interface of java.lang.ClassLoader does not contain any methods
that appear to be useful to us.

Just before I decided to start digging in the Sun source code, I noticed that
java.security.SecureClassLoader extended
java.lang.ClassLoader and java.net.URLClassLoader extended
java.security.SecureClassLoader. By doing a quick experiment, I
discovered that the System class loader (in the SUN VM) is indeed an instance of
java.net.URLClassLoader. [HK: *evil grin*]

At this point I got all excited. Why? Because URLClassLoader contains a
method getURLs() which returns the current classpath. So by writing the
following small class, I can validate the classpath (i.e. make sure all the jars
exist).

Now it is possible to add batch or script files to replace java and javac. I
was planning to leave this as an exercise for the reader but Heinz would have
none of that [HK: Incidentally, someone sent me the "exercise to the reader"
parts of the
CircularArrayList, if any of you are interested]. It turned out to be more
difficult than it initially seemed, as it is tricky to make sure that
ClassPathInfo is in the classpath.

Firstly if you are a Unix user I shall leave this as an exercise for the
reader. [HK: awww, come-on Syd] If you are using Windows you need to copy the
following three batch files with ClassPathInfo.class to somewhere
on your PATH. You also need to change the STRICTHOME enviroment variable in
checkcp.bat to the directory these files were copied into.

checkcp.bat

@echo off rem Set STRICTHOME to the directory you're deploying this file to.set STRICTHOME=C:strictjava
if ""=="%3" (
set STRICTCP="%CLASSPATH%;%STRICTHOME%"
) else (
if -classpath==%1 (
set STRICTCP="%2;%STRICTHOME%"
)else (
echo If more than three parameters are specified,
echo the first has to be -classpath.
set ERRORLEVEL=1
goto end
)
)
java -classpath %STRICTCP% ClassPathInfo
set STRICTHOME=
set STRICTCP=
:end

strictjava.bat

Please note that if you supply the classpath to these batch files, you will
have to put it in quotes (i.e. strictjava -classpath
"c:subjar1.jar;c:sub2jar2.jar" MyClass).

Regards

Sydney Redelinghuys (aka hopalong)

Copyright 2000-2004 Maximum Solutions, South Africa

Reprint Rights. Copyright subsists in all the material included
in this email, but you may freely share the entire email with anyone you feel
may be interested, and you may reprint excerpts both online and offline provided
that you acknowledge the source as follows: This material from The Java(tm)
Specialists' Newsletter by Maximum Solutions (South Africa). Please contact
Maximum Solutions for more
information.

Java and Sun are trademarks or registered trademarks of Sun Microsystems,
Inc. in the United States and other countries. Maximum Solutions is independent
of Sun Microsystems, Inc. Printer Friendly PageSend to a Friend