Thread Jiggling

Overview

Thread jiggler is a simple testing framework for exercising code to find threading problems. It works by modifying classes bytecode at runtime to insert Thread.yield() calls between instructions – “jiggling” the threads. This greatly increases the likelihood of discovering threading issues, and does it without you needing to change your production code.

Background

I was recently researching how to test multithreaded code for threading issues, and found out about a tool from IBM called ConTest, but couldn’t find any code I could use myself. So naturally, I thought I’d spike my own.

Consider this canonical simple, but thread unsafe class:

private int count = 0 ;

    public void count() {
        count++;
    }

The count method’s byte code is:

DUP
GETFIELD asm/Foo.counter : I
ICONST_1
IADD
PUTFIELD asm/Foo.counter : I

This provides several places where there could be a context switch, which means that count my be increased, but not stored as expected. Let consider a quick unit test:

Counter counter = new BadCounter();
    int n = 1000;

    @Test
    public void singleThreadedTest() throws Exception {

        for (int i = 0; i < n; i++) {
            counter.count();
        }

        assertEquals(n, counter.getCount());
    }
    ...

This test runs in a single thread, and passes. Lets try and run this on two threads and see if it fails.

public void threadedTest() throws Exception {

        final CompletionService<Void> service = new ExecutorCompletionService<Void>(Executors.newFixedThreadPool(2));

        for (int i = 0; i < n; i++) {
            service.submit(new Callable<Void>() {
                @Override
                public Void call() {
                    counter.count();
                    return null;
                }
            });
        }

        for (int i = 0; i < n; ++i) {
            service.take().get();
        }

        assertEquals(n, counter.getCount());
     }

This also passes. On my computer I can increase n to 100,000 before it starts to fail consistently.

Expected :1000000
Actual   :999661

Just 0.04% of the tests had a problem. What have we learned? We’ve learned a simple way to run a multithreaded test, but we’ve learned that, because we can’t control when threads do their work, it’s a bit trial and error.

Thread Jiggling

So one problem exercising code to find threading defects is that you can’t control when threads will yield. However, we can re-write the bytecode to insert Thread.yield() into the bytecode between instructions. In the above example we can get the code to produce more issues by changing the bytecode:

DUP
GETFIELD asm/Foo.counter : I
INVOKESTATIC java/lang/Thread.yield ()V
ICONST_1
IADD
PUTFIELD asm/Foo.counter : I

Using ASM, we can create a rewriter to insert these invocations. The JigglingClassLoader re-writes classes on the fly, adding these calls. From this we can create a JUnit runner to run use the new class loader for the test.

@Jiggle("threadjiggler.test.*")
public class BadCounterTest {
    ...
}

Now running the test:

Expected :1000000
Actual   :836403

The number of test where we see the threading problem jump to 16%. We’ve done this with out any recompilation of the code, or impacting on other unit tests running in the same JVM.

Exercise for the Reader

SimpleDateFormat is a well know, non-thread safe class in Java. Write a test that jiggles the class. Why is it not thread-safe? How would you rewrite it so that it was thread safe? How can you do so without using a ThreadLocal, locks or synchronisation?

Source Code

The code for this can be found on Github.

Further Reading

I’ve written a post on testing threaded code for correctnes. You may also wish to read more generally:

 

Reference: Thread Jiggling from our JCG partner Alex Collins at the Alex Collins ‘s blog blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

Leave a Reply


× 6 = forty two



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close