- A Concurrent Affair - https://www.concurrentaffair.org -

Thread Checking DrJava

After writing a few more auxiliary strategies, like one that can turn annotated class files into an XML configuration file with the equivalent annotations, I’ve created a branch for DrJava now and am adding my thread checking annotations.

So far, I’ve just searched for the string event thread” and put a @OnlyRunBy(@ThreadDesc(eventThread=true)) annotation in front of all the method that claimed they “should only be run in the event thread”. I haven’t performed any deeper analysis on whether that’s actually necessary or not. This pretty random process has lead me to insert 77 annotations.

There were three subtyping warnings that were produced:

edu.rice.cs.drjava.model.DefaultGlobalModel$ConcreteOpenDefDoc.runMain()V
    has @OnlyRunBy event thread
    but edu.rice.cs.drjava.model.AbstractGlobalModel$ConcreteOpenDefDoc.runMain()V
    does not

edu.rice.cs.drjava.ui.MainFrame.pack()V has @OnlyRunBy event thread
    but java.awt.Window.pack()V does not

edu.rice.cs.util.docnavigation.JListSortNavigator.addDocument
    (Ledu/rice/cs/util/docnavigation/INavigatorItem;)V
    has @OnlyRunBy event thread
    but edu.rice.cs.util.docnavigation.JListNavigator.addDocument
    (Ledu/rice/cs/util/docnavigation/INavigatorItem;)V
    does not

The first one is a semi-valid concern: The supermethod should be annotated as well; since there are no other subclasses in this case, though, it did not really matter. Except for the comment that this method “is usually executed in the event thread”, I also did not find a reason for it. I added the annotation anyway.

The second warning is bogus, I think. To me it seems like calling pack is always safe. Here’s the code in question:

/** Ensures that pack() is run in the event thread. Only used in test code */
@OnlyRunBy(@ThreadDesc(eventThread=true))
public void pack() {
Utilities.invokeAndWait(new Runnable() { public void run() { packHelp(); } });
}

/** Helper method that provides access to super.pack() within the
* anonymous class new Runnable() {...} above */
private void packHelp() { super.pack(); }

I think it’s more an issue of making sure that the “packing” has already occurred when the code continues rather than making sure it happens in the event thread. I ended up removing that annotation.

The third one was just a case where I had missed to add the annotation. With these three changes made, there were no more subtyping warnings. So far, so good.

When I started an instrumented version of the drjava-15.jar file, I already got my first violation:

Thread Violation: OnlyRunBy
        Current thread 'main', id 1, group 'main' did not match
        the event thread
        at edu.rice.cs.drjava.config.KeyStrokeOption. (KeyStrokeOption.java:-1)
        at edu.rice.cs.drjava.config.OptionConstants. (OptionConstants.java:278)
        at sun.misc.Unsafe.ensureClassInitialized (Unsafe.java:-2)
        at sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor (UnsafeFieldAccessorFac
        at sun.reflect.ReflectionFactory.newFieldAccessor (ReflectionFactory.java:122)
        at java.lang.reflect.Field.acquireFieldAccessor (Field.java:917)
        at java.lang.reflect.Field.getFieldAccessor (Field.java:898)
        at java.lang.reflect.Field.get (Field.java:357)
        at edu.rice.cs.drjava.config.OptionMapLoader. (OptionMapLoader.java:57)
        at edu.rice.cs.drjava.config.SavableConfiguration.loadConfiguration (SavableConfig
        at edu.rice.cs.drjava.config.FileConfiguration.loadConfiguration (FileConfiguratio
        at edu.rice.cs.drjava.DrJava._initConfig (DrJava.java:432)
        at edu.rice.cs.drjava.DrJava. (DrJava.java:117)
        at edu.rice.cs.drjava.DrJavaRoot.main (DrJavaRoot.java:97)

The code for KeyStrokeOption states that only the event thread accesses the methods in this class:

/** Class representing all configuration options with values of type KeyStroke.
* This code should only run in the event thread, so no synchronization is necessary
* (or advisable).*/
@OnlyRunBy(@ThreadDesc(eventThread=true))
public class KeyStrokeOption extends Option {

Obviously that isn’t true, the main thread also runs it. This is probably not a big issue, but it’s an error in the documentation. Other than that, DrJava has been holding up quite admirably so far. But right now I’m only checking against a few of our own constraints, and I haven’t run the unit tests yet.

I’ve also started looking at the Java API, and that, of course, is where it gets really interesting. I’ve found this comment in javax.swing.text.DefaultCaret, for example:

/** ...
* The repaint of the new caret location will occur on the event thread in any case,
* as calls to modelToView are only safe on the event thread.

I’m sure that I should mark javax.swing.text.DefaultCaret.repaintNewCaret() as event thread-only, but doesn’t the comment really imply that javax.swing.plaf.TextUI.modelToView should only be called in the event thread? I’ve marked those methods event thread-only too now, even though they seem to be used in many places without special concern.

[1] [2]Share [3]