More Information about the Sync Points

I created the strategy and thread monitor that supply and use the additional debugging information I mentioned before — a class index and a method index. Now I know exactly in which method a synchronization point originates.

The CompactSynchronizedBlockDebugStrategy creates a method database in a text file with the following format:

00003192 00000001: OneSyncBlockTest.main([Ljava/lang/String;)V
00003193 00000000: FewSyncBlockTest.<init>()V
00003193 00000001: FewSyncBlockTest.main([Ljava/lang/String;)V

Each line begins with two 8-digit hexadecimal numbers, the class and the method index. The human-readable name consisting of the class name, the method name, and the descriptor follow after the colon. Whenever synchronization points are encountered in the bytecode, these indices are stored in the buffer as well.

When the thread monitor is run in a mode that uses this debug information, it can load the method database and decypher the indices. The annotated log then looks like this:

// Note: Attempting to process sync points - main exited
// Total number of compact sync points so far: 2803
2 0 00003157 00000018 java.lang.StringBuffer.append(C)Ljava/lang/StringBuffer;
1 0 00003157 00000018 java.lang.StringBuffer.append(C)Ljava/lang/StringBuffer;
...
1 0 00003157 00000004 java.lang.StringBuffer.length()I
2 0 00003157 00000004 java.lang.StringBuffer.length()I
...
1 0 00003157 00000035 java.lang.StringBuffer.toString()Ljava/lang/String;
2 0 00003157 00000035 java.lang.StringBuffer.toString()Ljava/lang/String;
1 0 000030dd 00000002 java.io.ExpiringCache.get(Ljava/lang/String;)Ljava/lang/String;
2 0 000030dd 00000002 java.io.ExpiringCache.get(Ljava/lang/String;)Ljava/lang/String;
1 0 00003090 00000001 java.security.Permissions.add(Ljava/security/Permission;)V
...
1 0 00003087 00000001 java.io.FilePermissionCollection.add(Ljava/security/Permission;)V
2 0 00003087 00000001 java.io.FilePermissionCollection.add(Ljava/security/Permission;)V
...
1 0 00003084 00000001 java.security.BasicPermissionCollection.add(Ljava/security/Permission;)V
2 0 00003084 00000001 java.security.BasicPermissionCollection.add(Ljava/security/Permission;)V
2 0 00003090 00000001 java.security.Permissions.add(Ljava/security/Permission;)V
1 0 000030c0 00000015 java.net.URL.hashCode()I
2 0 000030c0 00000015 java.net.URL.hashCode()I
2 0 000030c9 00000005 java.security.SecureClassLoader.getProtectionDomain(Ljava/security/CodeSource;)
    Ljava/security/ProtectionDomain;
1 0 0000316c 0000000b java.util.Hashtable.get(Ljava/lang/Object;)Ljava/lang/Object;
2 0 0000316c 0000000b java.util.Hashtable.get(Ljava/lang/Object;)Ljava/lang/Object;
1 0 0000316c 0000000d java.util.Hashtable.put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
2 0 0000316c 0000000d java.util.Hashtable.put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
...
1 0 000030b6 00000002 sun.misc.Launcher$AppClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;
2 0 000030b6 00000002 sun.misc.Launcher$AppClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;
2 0 000030b6 00000002 sun.misc.Launcher$AppClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;
1 0 000030b6 00000002 sun.misc.Launcher$AppClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;
2 0 000030b6 00000002 sun.misc.Launcher$AppClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;
1 0 00003193 00000001 FewSyncBlockTest.main([Ljava/lang/String;)V
2 0 00003193 00000001 FewSyncBlockTest.main([Ljava/lang/String;)V
1 0 00003193 00000001 FewSyncBlockTest.main([Ljava/lang/String;)V
1 0 00003193 00000001 FewSyncBlockTest.main([Ljava/lang/String;)V
2 0 00003193 00000001 FewSyncBlockTest.main([Ljava/lang/String;)V
2 0 00003193 00000001 FewSyncBlockTest.main([Ljava/lang/String;)V
1 0 00003193 00000001 FewSyncBlockTest.main([Ljava/lang/String;)V
2 0 00003193 00000001 FewSyncBlockTest.main([Ljava/lang/String;)V
// Note: getting updated thread list from VM
//    13: put ($$$threadID$$$ = 6, name = Signal Dispatcher)
//     3: put ($$$threadID$$$ = 2, name = Finalizer)
//     4: put ($$$threadID$$$ = 1, name = Reference Handler)
//     1: put ($$$threadID$$$ = 0, name = main)
// Note: Finished processing sync points - main exited
// -- The application exited --
// Total number of compact sync points: 2803

The above is actually an abridged trace of what happens after the main method is entered. The comment says “main exited” because that’s when the buffer got pushed.

A lot of the synchronization points happen in java.lang.StringBuffer, mostly in void append(char). A few synchronization points also happen in classes dealing with permissions and a class loader. The bottom eight synchronization points are points that actually happen in the program’s main method.

I’m gonna mull this over now for a little bit and go to sleep. I don’t exactly know what it means, but it’s definitely interesting.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

DestroyJavaVM

The that produces the synchronization points after the main method has been exited during replay, thread 9, is called “DestroyJavaVM”. It appears for the first time immediately after the main method is left.

I also realized why these sync points don’t show up during recording: Recording happens in blocks, and a block only gets sent to the master VM when the buffer is full, when the main method is entered or exited. These eight sync points in the “DestroyJavaVM” thread can’t be pushed to the master VM anymore since main has already been left, the buffer doesn’t get full anymore, and when the application terminates (VMDeathEvent event) the data is not accessible anymore — the client VM is already dead.

This is not a catastrophe, though. It simply means that we cannot guarantee that sync points are recorded properly after the main method has been left. That may require some code to be rewritten, but a simple join() to wait until other threads have died will do the trick. There are other ways to fix this: For example, after the main method has been exited, the buffer size could be set to 1, forcing the client VM to push the buffer at every sync point. I’m not sure if this is necessary, but it’s worthwhile to keep it in mind.

There is another implication that’s more important, though: The replay program has to let the client VM run without monitoring if the schedule ends prematurely. In the current case, the last eight sync points by “DestroyJavaVM” are not present in the schedule, but we have to let the client VM execute them nonetheless. Also, not a biggie.

One secret (thread 9) has been investigated. Now I’m off to a more serious debugging to find the source of the sync points at the beginning…

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Trying to Find the Source

I’m still trying to find the source of the synchronization points that only appear at the beginning during recording. I have created a few more, very simple test files to gain an understanding of what sync points belong to what portion of the code.

The program

public static void main(String[] args) {
synchronized(OneSyncBlockTest.class) {
}
}

produces a whole bunch of sync points, but during the recording phase, the last sync points are “1 0; 2 0”, as expected. During replay, the only sync points generated by thread 0 are “1 0; 2 0; 1 0; 2 0”, followed by “1 9; 2 9; 1 9; 1 9; 2 9; 1 9; 2 9; 2 9”. I don’t yet know what thread 9 does or why there’s a “1 0; 2 0” preceding the expected sync points.

A more complicated program with nested synchronized blocks,

public static void main(String[] args) {
synchronized(FewSyncBlockTest.class) {
}
synchronized(FewSyncBlockTest.class) {
synchronized(args) {
}
}
synchronized(args) {
}
}

produces sync points during recording that end with “1 0; 2 0; 1 0; 1 0; 2 0; 2 0; 1 0; 2 0”, as expected. During replay, we get the same sync points, again preceded by a “1 0; 2 0” and followed by sync points by thread 9.

Interestingly, the most trivial program,

public static void main(String[] args) {
}

with an empty main method doesn’t produce any valid sync points: The main method is never entered!

Unfortunately, so far I haven’t been able to figure out where the extraneous sync points are coming from. I will now add more debug information to the compact representation. In addition to code and thread ID, I will add a long that represents the index of the class in a list of instrumented classes (0 will be the first class, 1 the next, etc.), and another long to point me to the method within the class. All of this can be inserted directly into the bytecode as constants, without having to change the constant pool. Hopefully that will provide some more information.

Update

I just noticed I was wrong; the long constants for the class and method indices have to be added to the constant pool. That shouldn’t be a problem though.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

XML Configuration Files

Oh, one more thing, it’s minor but sort of interesting: My configuration files were getting confusing now because they now have to be shared between the record and the replay application, so I took a few hours to write a small XML configuration class.

The configuration data isn’t accessed by manually traversing a tree. Instead, you specify the path to the node or attribute. I got this idea from the Perforce-style patterns and a project about DOM path blocking in Firefox that Justin Crites and I did a year ago.

Assume there is an XML file with the following contents:


abc
def

Nodes are specified using a slash (/) as separator: Then the path “foo/bar” retrieves the string “abc”, and the path “foo/fum” retrieves “def”. There may be only #text or #comment nodes in the node specified by the path. All #text nodes will be concatenated and then stripped of whitespace at the beginning and the end.

Attributes are accessed by specifying the containing node and the attribute name, separated by a dot (.): The path “foo/fum.fee” refers to the value “xyz”, and the path “foo.a” refers to the value “uvw”.

Only strings can be stored and retrieved this way. If I wanted to store more complex data with internal structure, I would either have to convert it to a string and then parse it again, or write more complex functions to handle XML. For now, though, this is sufficient and very convenient.

Later, these XML functions may be thrown away again. DrJava uses a Scheme-like syntax for configuration files, if I remember correctly. But regardless, I like my configuration class and it didn’t take long to write.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Time for Another Update

I haven’t written in my blog for a while, but again, that doesn’t mean I didn’t do anything. I did a lot, actually.

Corky — my advisor — and I decided we’re going to change the course slightly. Instead of using Lamport clocks for replay, we’ll try to record just raw synchronization points. That means I don’t have to introduce a unique ID into each object (something with which I had major problems), only a unique thread ID into the Thread class (something I already knew how to do).

This allowed me to write an instrumentation strategy that uses a compact buffer of longs. Right now, I use pairs of longs comprised of the event code (1 = monitorenter, 2 = monitorexit) and the thread ID. Later I can either merge the two into a single long, or ideally dispose of the code entirely. In the interest of safety, right now I keep track of what code it is, just as a sanity check. And that was a good thing, as I’ll explain in a second.

I then started to write the replay strategy. There’s a GUI launcher now that runs the program in the client VM and loads the synchronization points into the buffer whenever the client VM runs out. The log of synchronization points right now simply is a text file with the number pairs and some slash-slash comments. The synchronization points that were recorded before the main method was entered are included but commented out:

// -- VM Started --
// Note: getting updated thread list from VM
//     3: put
//     4: put
//     1: put
// Note: Attempting to process sync points - VM start
// Total number of compact sync points so far: 5
// 2 0
// 1 3
// 2 3
// 1 3
// 2 3
// Note: Finished processing sync points - VM start
// Note: Updating sync points. edu.rice.cs.cunit.SyncPointBuffer.transfer or compactTransfer entered by thread id 1
// Note: Attempting to process sync points - push
// Total number of compact sync points so far: 261
...
// Note: Finished processing sync points - main entered
// Note: Attempting to process sync points - main exited
// Total number of compact sync points so far: 2363
2 0
1 0
2 0
1 0
...
2 0
2 0
2 0
// Note: Finished processing sync points - main exited
// -- The application exited --
// Total number of compact sync points: 2363

Before I began to implement the actual replay algorithm, which I’ll describe in another post in more detail, I wanted to write a sanity check, so I compared the synchronization points in the buffer to the ones the program actually executed, expecting them to be the same.

For some strange reason, the synchronization points that were recorded begin with 231 synchronization points that are not found in the synchronization points that are found during replay. After those 231 synchronization points, the two lists match up. Then, at the end, there are 8 synchronization points (all by thread ID 9 — don’t yet know which thread that is) that are only found during replay. Just as a visualization, a diff of the two lists looks like this:

231 sync points (thread ID 0) only found during record
...
matching sync points
...
8 sync points (thread ID 9) only found during replay

For a while I thought that because I used the String class to send the error messages to the master VM during replay, the String class had to be initialized and that changed the order of synchronization points. Unfortunately, this just turned out to be false.

I have to admit right now I’m clueless why this is happening. On the other hand, it’s encouraging that the two lists match up except for those two blocks at the beginning and the end.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Perforce-Inspired Patterns

Last night I started writing a class name matcher that uses Perforce-inspired patterns. Internally, those are converted to Java regexes. Using this matcher, it is a lot easier now to specify which classes in what packages should be excluded.

By now, I’ve found out that not the entire sun.* package has to be excluded, but actually just sun.reflect.* . I’m still working on java.* . Right now it seems like sun.util.* and sun.lang.* have to be excluded. I haven’t exactly considered the ramifications of that yet.

But more about those patterns. First of all, the entire string has to match, so ^ and $ for beginning and end are always implied. A ? matches a single character, a * matches zero or more characters but not a period (.), and \*\*\* truly matches zero or more characters. That way, * means just one package, \*\*\* means any number of packages. If a pattern is prefixed with !, then that match is negated. The matcher will indicate a match if there was at least one positive pattern that matched and no pattern that matched negatively.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Error Theory

I have a theory now for why the error below occurs:

java.lang.VerifyError: (class: Test7, method: main signature:
([Ljava/lang/String;)V) Incompatible object argument for function call
Exception in thread "main"

I am calling invokevirtual edu/rice/cs/cunit/ProperObject.wait$$$Decorator$$$()V on a Thread object, but I haven’t made ProperObject a superclass of Thread yet.

I guess I have to do that now… that’s a big, big instrumentation of many, many classes and likely to cause more errors. Makes me sick to my stomach, but there’s no way around.

Update

As expected, instrumenting the entire rt.jar with the ProperObjectSuperClassStrategy didn’t work, the VM doesn’t even initialize. I think it may have to do with the placement of ProperObject. I’ll try putting it in the java.lang package.

I also just noticed that the ProperObjectSuperClassStrategy strategy was affecting ProperObject itself, so ProperObject was its own superclass. I’m working on changing that and rerunning the tests.

Update

Now I’m getting a “java.exe – Application Error. The instruction at ‘0x6d749f0f’ referenced memory at ‘0x00000064’. The memory could not be ‘read’. Click OK to terminate the program. Click CANCEL to debug the program.” error. Lovely!

And I have no idea why!

Update

I’m excluding certain classes from the rt.jar now, and sometimes it works, sometimes it doesn’t. Right now, I’m excluding the com.* , java.* , javax.* , sun.* , and sunw.* packages, but instrumenting java.lang.Number and the test programs, and it works. It seems like there will be a few classes again where this method doesn’t work, and I’ll have to come up with workarounds for the exceptions. Sigh.

Update

Now I’ve limited it to just the java.* and sun.* packages.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

James’ Suggestions

I talked to James, my office mate, today. He has been working on NexGen, a Java compiler that does generics without resorting to erasure, so types are (almost) first class. NexGen also uses a class loader, and it should eventually also be integrated into DrJava, just like my concurrent unit testing stuff. So one thing we’ll have to do is make sure that our class loaders play along well with each other and with the class loader that DrJava has.

James suggested I could use an optional class cache. Classes that have already been instrumented could just be stored somewhere. Of course, I have to make sure the cached class file is still up-to-date. That means I have to have access to the Java source file that corresponds to it (not a big problem, there’s a SourceFile attribute) and check that the Java file hasn’t been changed since the class file was instrumented. James suggested I should also do a hash over the source file.

Thanks for the suggestion! James has an account here on the blog now, so maybe he’ll read and comment every once in a while.

I should also mention that I registered the domain concutest.org for this project, by the way. I realized my hosting package included a few free domains. I’ve also excluded <clinit> from being cloned for decorators, by the way. That works now. Guess what? I have another problem now:

java.lang.VerifyError: (class: Test7, method: main signature:
([Ljava/lang/String;)V) Incompatible object argument for function call
Exception in thread "main"

I haven’t figured out what that means yet.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Exceptions Prove the Rule

I worked some more on the ProperObjectSuperClassStrategy and decided that it probably shouldn’t do the renaming itself. I have a ChangeCallTargetInstrumentationStrategy for that. So now I’m adding static methods and <init> to the list of calls that need to be changed.

Now I’m running into a problem with the static initializer, <init>:

java.lang.IllegalAccessError: tried to access method
        java.lang.Object.<clinit>()V from class edu.rice.cs.cunit.ProperObject
        at edu.rice.cs.cunit.ProperObject.<clinit>(Unknown Source)
Exception in thread "main"

Now I have to figure out what exception I need to make exactly… when does <init> exactly get called?

Update

As it turns out, it’s never called explicitly:

A class or interface has at most one class or interface initialization method and is initialized (§2.17.4) by invoking that method. The initialization method of a class or interface is static and takes no arguments. It has the special name <init>. This name is supplied by a compiler. Because the name <init> is not a valid identifier, it cannot be used directly in a program written in the Java programming language. Class and interface initialization methods are invoked implicitly by the Java virtual machine; they are never invoked directly from any Java virtual machine instruction, but are invoked only indirectly as part of the class initialization process.

That means I just have to exclude <init> from being put in the decorator.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Just Changing Superclass Not Enough

One of the last things I’d written and begun to test before the accident was an instrumentor called ProperObjectSuperClassStrategy. It changes all classes that extend Object to extend my own ProperObject. However, this is currently only done on a class level. When I briefly tested it, of course it didn’t work.

The methods in Java are handled individually. So what this strategy also has to do is change all method calls that have Object as target to calls to ProperObject.

Update

That isn’t true. Virtual calls happen without knowing the exact target class, of course. But static and constructor calls, i.e. calls made by invokespecial and invokestatic, it seems, do require the actual class.

Update

I’m looking at the definition of invokespecial right now:

Next, the resolved method is selected for invocation unless all of the following conditions are true:

  • The ACC_SUPER flag is set for the current class.
  • The class of the resolved method is a superclass of the current class.
  • The resolved method is not an instance initialization method.

If the above conditions are true, the actual method to be invoked is selected by the following lookup procedure. Let C be the direct superclass of the current class:

  • If C contains a declaration for an instance method with the same name and descriptor as the resolved method, then this method will be invoked. The lookup procedure terminates.
  • Otherwise, if C has a superclass, this same lookup procedure is performed recursively using the direct superclass of C. The method to be invoked is the result of the recursive invocation of this lookup procedure.
  • Otherwise, an AbstractMethodError is raised.

If I read this right, it means that instance initialization methods (<init>) will always be called directly, without any further lookup, as will methods outside the current classes hierarchy. If a method in the current hierarchy is called that is not an instance initializer, then the class hierarchy is traversed up until a method has been found.

For the latter case, nothing has to be done. Object is still the end of the chain, but ProperObject‘s methods will be found first. For instance initializers and calls to outside this hieararchy, I will have to perform the changes, i.e. if a call to Object.<init> is being made, it has to be changed to ProperObject.<init>. For Object, the case of “calls to outside the hierarchy” doesn’t really apply, because everything is a subclass of Object, but it is worth keeping in mind that if I ever do this for other classes, I will have to perform the same change for these calls too.

The invokestatic instruction does not use any kind of special lookup. Any invokestatic calls to Object methods will have to be rewritten.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Long Time No See

Ok, so I’ve definitely been having a bad conscience for not writing. It’s not like I haven’t done any work, but I have to admit that I haven’t worked on the concurrent unit testing project since my accident. The week before that I was just gearing up to work on it again, after the hurricane. After the accident, for about three weeks, pretty much all through October, my back was hurting when I was sitting. It still stings a little bit now every once in a while. I just found it hard to work on a project like this that required working in long stretches.

So instead, I added an interesting part to the Rice Marine Biology Simulation. The simulation was already able to protect against fish that use System.exit, call thread or system functions, and cause a heap or stack overflow. The only thing I couldn’t really do anything against was a fish that diverged without using up any resources.

Initially I had thought about putting each fish into its own thread, and then killing the thread after a certain amount of time had passed. The problem with this is the way thread killing is implemented in Java: If I tell a thread to die, it is forced to throw a ThreadDeath exception at the next opportunity. However, ThreadDeath implements Throwable and can thus be caught. Therefore, it is possible to write a fish that diverges, catches the code>ThreadDeath that is supposed to kill it, and continues to diverge. At that point, I gave up.

After having worked on my bytecode scanning and rewriting framework for the concurrent unit testing project so much, I realized there’s another perspective: I can scan the fish classes being loaded for catch statements that are so general they might catch a Throwable, Error, or ThreadDeath, and if the user attempts to load such a class, prevent it. That means the fish that does get loaded has no way to prevent ThreadDeath from unwinding the stack and eventually killing the fish.

This is what I implemented. The actualy scanner was really easy to write. Writing and integrating the class loader was a lot more difficult. In Java, if the same class files is loaded by two different class loaders, the classes in memory are treated as different. Unfortunately, Java doesn’t provide a way to find out if a class has already been loaded by another class loader. I would have liked to know if a class has already been loaded by the system class loader so it doesn’t have to be checked anymore, but that wasn’t possible. Now I scan every class except for a select class of trusted classes. The new system is pretty cool, I think.

I was told in C#, it’s possible to deactivate the ability to catch its equivalent of the ThreadDeath exception, so such a class loader and scanner wouldn’t be necessary in a C# implementation.

I’ve also written a few thousand words for our OOP book. There’s still lots of work to do, though. We’re working with my temperature conversion examples, but we realized the step from the third iteration (built-in functions with quadratic growth) to the fourth iteration (lambdas, linear growth) is too steep. So we’ll throw in a shape example to familiarize the reader with abstract classes and inheritance first. I’ve been working on that, but haven’t had the time. I would like to write more, but I need to focus on other things.

One last piece of good news: The OOP/OOD workshop that Dr. Nguyen, Dr. Wong, Eric Cheng, and I have submitted to SIGCSE 2006, this time to be held here in beautiful Houston, has been accepted. So eventually we’ll have to work on that, but we’ll try to create as much overlap with the book as possible.

I finished lots of grading yesterday and today. And now I really have to dive into CUnit again…

Share
Posted in OOP Book, Research, Uncategorized | Leave a comment

Print This Post Print This Post  

First Day at the Office Again

Ok, so I made it back to the office. That’s good — I think just being here gives me a boost. However, I feel majorly woozy. I blame the muscle relaxers for that, because the pain medication I’m on now doesn’t quite seem strong enough. When I sit, my back still hurts. We’ll see how the day goes.

I’m loading IDEA now (which for some reason takes really long on the machine in the office), and then I’ll try to get back into what I was doing a week ago. Jeez…

Share
Posted in Uncategorized | Leave a comment

Print This Post Print This Post  

Accident

The crazy times just don’t seem to end. When I biked home from school last Wednesday, I got hit by a car. I guess I was lucky nonetheless: No fractures. I went to the hospital twice, had x-rays done twice, got two different pain killers and two different muscle relaxers. I had contusions on my hip and shoulder; they’re ok now. Now I still have pain in my lower back — pain that unfortunately is quite distracting when I’m sitting — and the medication I have now doesn’t seem to be able to mask it. I hope I don’t have a problem with my disks (the ones in my spine, nerd). Needless to say, I spent most of the last days horizontally and away from my computer.

My bike is still getting fixed. That may take two weeks, so I probably won’t go to campus as often as I would like. I’m still determined to be there tomorrow. I miss my students.

Share
Posted in Uncategorized | Leave a comment

Print This Post Print This Post  

Change Call Target & Create Decorator Strategies

I’m testing a strategy, ChangeCallTargetInstrumentationStrategy, that automatically changes call targets as specified in a list of “original call target”-“new call target” pairs now. I’ve modified the CreateDecoratorStrategy to automatically generate this list.

What I don’t know right now is how this is going to affect super() calls. I think these are just regular calls, so if something performs a super() call that takes it to a method in a decorated class (the decoree, right now java.lang.Object), then it will call the decorator instead, which will then call the decoree. This should all work, except for some complications with the different invoke flavors of Java bytecode. I think invokespecial may be used to make calls to methods in super classes, but the decorator might not be a superclass. Unless I insert the decorator into the entire hierarchy, i.e. make all classes that previously had the decoree as immediate superclass have the decorator as superclass.

That might be the easier way, actually. I could put the object ID and whatever fields I need into the decorator then. But it also messes with the object hierarchy in a major way, which may turn out to be harder to hide from reflection.

Update

I don’t really know why I didn’t consider this possibility before. It really seems easier now. I think when I started with the business of adding fields to classes, I didn’t anticipate the need to globally replace call targets. I didn’t think about final methods at that time. Now that I need to do that anyway, inserting ProperObject into the hierarchy seems easier. Right now, I touch all direct descendants of Object already anyway because I insert the fields. Placing the additional fields into ProperObject and changing all direct descendants of Object to have ProperObject as superclass is easier.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Back to Normal?

This was a crazy week. Even though hurricane Rita ended up missing Houston almost completely, it still managed to completely derail the plans for the last few days. The university was closed on Thursday and Friday, classes are still cancelled today. The university still isn’t fully operational today. I made a pointless trip to campus. On Wednesday, I decided to leave the Affiliates’ Meeting before the poster presentation. I regret not being able to present my poster, but I know it was the right thing to do: Had I waited only a few more hours, I wouldn’t have been able to get all the items I needed.

Hopefully, things will be back to normal tomorrow.

Share
Posted in Uncategorized | Leave a comment

Print This Post Print This Post  

Poster: Unit Testing for Concurrent Programs

Unit Testing for Concurrent Programs

Where: Rice University Computer Science Department, Corporate Affiliates Meeting 2005
When: September 20, 2005 and December 5, 2005

Share
Posted in Concurrent Unit Testing, Publications | Leave a comment

Print This Post Print This Post  

Status Update

Here’s an email that I just sent to my advisor:

Hi Corky:

I wanted to give you an update on where we are with the concurrent unit testing project so it will be easier for you to ask the right questions in the next few days.

I have written a two-VM system using JPDA. The master VM is a GUI program that consists of a launcher and a monitor. The launcher allows the user to define, save, and reload settings and specify which program should be debugged. When the user presses the “Run” button, the monitor is started. The monitor sets up the best possible JPDA connection (memory transfer on Windows, sockets on others) and starts the program to be debugged in the slave VM.

To generate synchronization events, the Java API (rt.jar) and the user program need to be modified in a procedure that I have called instrumentation. This inserts the necessary Java bytecode to emit the synchronization events before and after synchronized blocks, synchronized methods, thread starts, etc. The Java API needs to be instrumented off-line. It only makes sense to provide a separate tool for doing this, though, since the classes in the Java API do not change; therefore, the rt.jar should only be instrumented once. User code can either be instrumented off-line as well or be instrumented as it is loaded using a custom class loader.

The slave VM contains a buffer to store the synchronization events as they come up. Whenever the buffer is full, it notifies the master VM that the buffer needs to be read and emptied. In effect, the slave “pushes” the data over. The master VM can also perform a “pull”, either timed or user-initiated. This way, the master VM can obtain up-to-date data even if the debugged program doesn’t generate a lot of events and thet buffer does not fill up. A “pull” may temporarily fail if the slave VM is in the process of adding to the buffer, but the master VM is written in a way to automatically try to do the “pull” again once the slave VM is done working with the buffer.

By buffering the synchronization events, we reduce the number of times the slave VM has to be suspended, data be transferred, and the slave VM be resumed. All these operations carry significant overhead, so the execution time is reduced by an order of magnitude. A 1024-element buffer allows the program to run about 40 times faster than it would with a naive implementation that uses JPDA to suspend, process, and resume the slave VM at every synchronization point.

Right now, the synchronization events stored in the buffer are still heavy-weight Java classes. This incurs both large memory requirements and longer transfer times. Using these events, we have implemented a deadlock detection system and the beginnings of a schedule recorder. The format of the schedule recorder is not very concise and easy to manage yet, though; right now, it is just a human-readable text file that names the thread, type of event, and objects involved in the synchronization events.

We are in the process of converting the synchronization events to a light-weight binary format that just uses primitive data. Such an array would a lot smaller, faster to transfer, and much friendlier to the garbage collector, even though we would not lose any information we need. In effect, we need a unique thread ID, the encoding of the type of the event, and perhaps a unique ID for the object involved in the event. The unique ID is necessary for deadlock detection, but not neccessary for schedule recording.

The problem I’m facing right now is that it is not as easy as it seems to introduce the necessary fields in all the Java classes. A unique ID for all objects should conceptually be added to the java.lang.Object class, but this class cannot be freely modified. I’m trying to provide a substitute class that essentially acts as a decorator to java.lang.Object and that can be used in place of the original class. The same may have to be done for java.lang.String, which is another class that cannot be modified. The substitution can be done automatically; for all other classes, I have already done this.

I also still need to exclude synchronization events before the beginning and after the end of the main method in the debugged program, as well as those generated if the custom class loader is used. So far I have focused more on the off-line approach because it allows me to focus on the separate things that give me trouble (rewriting, buffering and processing events) in isolation.

Once I have solved the problem of introducing additional fields to all classes, I can change the format of the event buffer to the more concise, binary format. This should make the program run a lot faster. Right now, there is still a very significant impact. I have been able to run GUI programs, but they behave very sluggishly.

These additional fields need to be introduced to implement “Lamport clocks”. During each synchronization event, the clocks of all involved objects are set to max\(clock\_1, clock\_2, …, clock\_n)+1. This way, if two threads involve the same object in a synchronization, the Lamport clocks can be used to establish a relative ordering of the events: The event with the smaller clock value happened first. These computations should be reasonably cheap since they will be inserted during instrumentation and may even be JIT-compiled.

It’s a little bit frustrating how rarely the obvious solution, like adding a field to java.lang.Object, works with the JVM: In this particular example, I first tried that, then tried to write the decorator class that can be substituted for Object, but this class needs to override final methods in Object. To allow for that, I tried to remove the final flag in java.lang.Object, but then the JVM died with a native code exception. I’ll have to use a technique that I’ve used in other places before now. which involves changing all the calls to thehse final methods to first call a method with a different name, which then delegates to the original, final method.

I feel like the JPDA implementation is a lot more stable than the one-VM implementation we were still working with in the Spring.

If you have questions or comments, I’d love to hear them.

–Mathias

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Making Methods Not final Doesn’t Work

As expected, removing the final flag from methods doesn’t work, at least not in java.lang.Object. When I do that, the Visual Studio debugger comes up, so it’s probably something the JVM really doesn’t like. I haven’t tested it with other classes. I suspect this might work with classes that aren’t so intricately involved with JVM initialization, so I might be able to use this (easier) way sometimes.

It really seems like I have to do a global instrumentation and change calls to Object methods everywhere.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Problems With Decorating

I finally found some time to test the decoration. The problem I have right now is that some methods might be final and thus should not be overridden. I have two choices here:

  1. Change the decoree’s method so that it’s not final.
  2. Give the method a different name in the decorator and reroute all calls to that new method. The new method still delegates to the old, final method

If the first way works, that might actually be the easiest. Theoretically, the possibility exists that someone might try to override the now not-final method, but since all of these programs will first be compiled with the regular compiler, those things should be caught. I’m just worried that this way might not work.

The second way would most definitely work, but it makes these changes global, i.e. all files have to be changed. That’s a lot more work. Also, it introduces new names, which may have to be hidden later when I try to fix reflection.

Talking of reflection: The change to ProperObject might be a lot harder to pull off than I originally thought, at least if reflection is used. Right now it seems like I have to modify class Class and class Constructor so that whenever a request for a new java.lang.Object instance is made, a new ProperObject is created. Furthermode, ProperObject.getClass() should really return java.lang.Object.class, but that’s not really possible: Object.getClass() is native and final. Ugh. getName(), isInstance, isAssignable in class Class will probably have to be hacked, too. The idea is to always work with Object.class but always create ProperClass.class. I just don’t quite know how to do that yet.

I think I might ignore that for now and push on. Reflection on java.lang.Object and java.lang.String is probably pretty rare.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Haven’t Written in a Long Time

Wow. I haven’t written in my blog in a long time. I guess it has to do with the fact that the school year has really started again; in fact, I already graded my first assignment. I also updated the website a couple of times, made changes to solution code, and held office hours. I love holding office hours: I really get the feeling again that I’m helping people.

Not writing anything doesn’t mean I didn’t do anything, though:

I’ve been working on a poster for the annual Corporate Affiliates’ Meeting. Once it’s done I’ll make it available online again. Fortunately and unfortunately, not too much has changed from last year, so I used a lot of last year’s poster. I added the two-VM approach, though, and compared the buffered version with the unbuffered one. Unfortunately, the graph for the comparison is very small, and I can’t figure out how to get more space to make it bigger. I may end up taking it out again.

I also wrote an instrumentor that creates a decorator for a class: It generates a class file for a “class B extends A” that has the same methods as class A, but B’s methods just forward to the corresponding methods in A. This should allow me to easily generate decorators for Object and String so I can add fields. I haven’t had time to test this, though.

In other news, my Palm Tungsten E finally died. This entire year I’ve had problems with power draining really fast. Now the battery seems so damaged that the Palm sometimes just hangs and the display begins to fade. Of course, it might also be something else, but I’m pretty sure that the device is dead. I considered buying a replacement battery for $50, but that requires soldering (which I can do, of course) and might not fix the problem. So I bought a new PDA, a Palm Tungsten E2, for $195, and I’m hoping to eventually get a $50 mail-in rebate.

The Tungsten E2 is the direct successor to the PDA I had before, so naturally it is very similar. There are a few improvements, though: First of all, the PDA feels a little bit lighter, and all the buttons are a bit recessed. That’s good, the PDA shouldn’t accidentally turn on as often anymore. The E2 is also Bluetooth-enabled, but I haven’t had a chance to test that yet. It also has a brighter display, supposedly longer battery life, and if the latter turns out to be false, it has non-volatile memory, so the data doesn’t get lost even if the battery goes out. That’s a dream come true. Everything looks very nice so far, but I can’t get the included “Media” application to work. It transfers pictures to the Palm, but they don’t show up in the application. That’s really sad. Now I can’t brag with pictures of my beautiful ex-girlfriends anymore.

Time for food.

Update

I deleted a few incompatible “Photos” application files and performed a hard reset. Now the “Media” application works like a charm.

Share
Posted in Concurrent Unit Testing, Uncategorized | Leave a comment

Print This Post Print This Post