For a while now, we’ve had a problem with the Java compiler, starting with JDK1.6.0 Update 4. While I’m not the expert on this, it seems like the compiler can no longer use *.exe files on the class path, even if they are just a wrapper around a *.jar file, which is how we create our Windows *.exe file.
Strangely enough, the class loader continues to accept *.exe files, as did the compiler in the past. Whatever Sun did to the Java compiler, now the compiler and class loader have divergent behaviors, and we have therefore considered this a bug on Sun’s part and filed a bug report. The bug report, however, has not been accepted (yet), and therefore isn’t accessible anywhere. We also don’t know if it has been rejected since Sun doesn’t provide notifications for rejected bugs. So, after several months, we have grudgingly accepted that we need to deal with this problem, even though there’s a simple work-around: Just use the *.jar file.
What we plan to do now is to extract a temporary copy of JUnit from our DrJava executable, and put that file instead of the DrJava *.exe file on the class path for compilation. Of course, we only do that if the user is running Windows, the DrJava application is a *.exe file, and the compiler being used is JDK1.6.0 Update 4 or newer.
We still need to exactly figure out when to create that file and when to remove it. Of course, we want to pay the smallest performance penalty possible. There are basically two options
- Create the file before every compile, delete the file after every compile.
- Create the file at DrJava startup, delete the file during DrJava shutdown.
The first option keeps the temporary directory very clean, but it will probably also be quite time-consuming, particularly on networked drives often found at universities. The second option is much less time-consuming, but it might leave a copy of the extracted file in the temporary directory if DrJava shuts down in an unclean way.
The compromise that we’ll probably attempt is to create temporary file names with a known, unique (or at least rare) naming scheme, e.g.
drjava-junit-java6u4-problem-#.jar, where the
# stands for a sequential number.
On DrJava startup, we will create a temporary file
drjava-junit-java6u4-problem-1.jar, overwriting an already existing file with the same name if one exists. If we cannot overwrite the file because it is locked by another process, we will increase the sequential number until we have found a file that can be overwritten or does not exist.
On DrJava termination, we will attempt to delete all files in the temporary directory that match the pattern
drjava-junit-java6u4-problem-#.jar: The file the current instance of DrJava created, and all other files left behind by other instances of Drjava.
This approach combines the low overhead of option 2) with a relatively clean temporary directory, which is a feature of option 1).
We may have to consider that the user could switch from one compiler version to a different one while running DrJava, so we may need to perform the above actions not only on startup, but also when the compiler is changed.
We are planning to have this code in place for an upcoming beta release for testing, and ready to use for the next stable version to be released at the beginning of the next school year.