A Custom-Class Loader for the Thread Checker

I’ve been working on a custom class loader that does the instrumentation required for the thread checker on the fly. I’ve got most of it working now, even though I ran into a bunch of weird bugs that had me confused for several hours: I was using incorrectly formatted class names, names in the format “Lsome/package/name/MyClass$InnerClass;", as they are used in descriptors and annotations for class constant pool info items that expect class names of the format "some/package/name/MyClass$InnerClass". For some reason, this ran without any “Illegal class name” ClassNotFoundExceptions when I instrumented everything offline, but when I did the instrumentation on the fly, the exception was thrown.

The problem I’m facing now concerns auto-generated compound annotations, and also only in the on-the-fly version: I’m getting InvocationTargetExceptions when the auto-generated predicate method is trying to make a call to a member predicate method that is in a private or package-private class.

java.lang.IllegalAccessError: tried to access class
sample.threadCheck.predicate.PrintPrimitive from class
auto.sample.threadCheck.predicate.AndPrintStringsPred

Here, auto.sample.threadCheck.predicate.AndPrintStringsPred is the automatically generated class with the predicate for a @Combine-style annotation. sample.threadCheck.predicate.PrintPrimitive is a package-private class that contains the predicate method for the PrintStringAnnotation, which is a member of AndPrintStringsPred.

Right now, I see two ways around this: Either I use some reflection magic and allow access to private entities, or I change the placement and naming of auto-generated classes. Allowing access to private entities, if not done carefully, might alter the behavior of the program that is running. I have to check if I can somehow enable access just when I need it and disable it afterwards. That might be the easiest way.

The other way, of course, would be to generate the predicate classes so that they do have access to the private classes they need. However, I don’t believe that’s possible in all cases. What if an auto-generated class needs to refer to two package-private classes that reside in two different packages? I think I’ll go with the former route, even though I don’t like the prospect of enabling and disabling reflection features frequently.

In general, though, the good news is that the custom class loader is very easy to use. It’s almost the same as running something using the java command: Right now, the class to use is edu.rice.cunit.CUnitRun, which can do on-the-fly instrumentation for any kind of instrumentation strategy, but I’ll probably wrap that in a dedicated class, perhaps something like edu.rice.cunit.TCRun.

Instead of writing java MyProg, right now I have to write

java edu.rice.cs.cunit.CUnitRun
     -i edu.rice.cs.cunit.instrumentors.threadCheck.CompoundThreadCheckStrategy
     MyProg

This looks quite cumbersome, but it’s actually pretty simple. CUnitRun is basically a replacement for javac, the -i argument with the following class name specifies the instrumentation strategy to run, in this case the Thread Checker strategy, and the normal javac arguments follow after that. There are a few more flags for debugging and finer-grained control, but they don’t really matter right now. With a dedicated class to run the Thread Checker instrumentation on-the-fly, the command will boil down to this:

java edu.rice.cs.cunit.TCRun MyProg

Simple enough, I think.

Share

About Mathias

Software development engineer. Principal developer of DrJava. Recent Ph.D. graduate from the Department of Computer Science at Rice University.
This entry was posted in Concurrent Unit Testing. Bookmark the permalink.

Leave a Reply