Coming off Java for a little while after six years of immersion offered me an opportunity to look at Java from a different perspective. In particular, I got to look at some of Java's deficiencies from a non-defensive perspective.
Take this post: Static: friend or foe?, for example. Cedric pointed out that the java task in Ant, if not "fork"ed, leaves the invoked classes loaded and any of their one time (static) initializations done. Thus if two non-forked java tasks are run in the same Ant invocation, the first can affect the second in surprising ways.
His advice, avoid static variables as a rule of thumb, though good in intention, and sound in principle, does not address the root of the problem:
Ant is not a shell. It a build tool with its own wrinkles.
Now take a look at a proposed remedy for the problem. It essentially want Ant to use a different classloader for each non-forked java task. This will fix the symptom in Cedric's example, but it doesn't go far enough. For example, classes loaded by other tasks (including custom tasks) would still be loaded and initialized.
The problem with ClassLoaders is this:
ClassLoaders are not processes. It a (square) reinvention of the process wheel.
For all the ClassLoader fans out there, here's a question for you: How do you do ICC (inter-classloader communication)?