Java/Maven

CopyOnWriteArrayList in Java

I am reading Java Concurrency in Practise. Priceless if you know a thing or two about concurrency already, but would like to brush up on the theory and also learn one or two new developments. The book is extremely well-written.

And here is a little something I would like to share. In the book Brian Goetz glides over this, but this is so amazing, that it deserves a deeper look.

// CopyOnWriteTest.java

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteTest {

	private static void f( List l ) {
		l.add( 2 );
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		List copyOnWriteList = new CopyOnWriteArrayList();
		List simpleList = new ArrayList();
		copyOnWriteList.add( 1 );
		simpleList.add( 1 );
		Iterator copyOnWriteIterator1 = copyOnWriteList.iterator();
		Iterator simpleListIterator1 = simpleList.iterator();
		f( copyOnWriteList );
		Iterator copyOnWriteIterator2 = copyOnWriteList.iterator();
		Iterator simpleListIterator2 = simpleList.iterator();
		// debug point on the output line just below
		System.out.println(copyOnWriteList);
	}

}

And when we debug into it we see this amazing picture (comments in red on the right):

CopyOnWriteArrayList debug screen

CopyOnWriteArrayList debug screen

As you see the normal non-thread safe ArrayList iterator holds reference to the collection itself. Whereas the clever little CopyOnWrite iterator creates a clone of the underlying array every time a modification is made, so whenever an iterator is called it just gets the latest clone – which doesn’t change throughout the life of the iterator. Rather new clones are created.

Now there is another way of doing this – where we don’t abstract away the reference and therefore when the collection is modified in a function we don’t see that in the caller. But this is not true here and if you let the little example run, you will see it print [1, 2], which is brilliant! 2 is added in the function f.

I should point out that Vector, which is thread safe, looks exactly like the ArrayList here.

For those searching for uniqueness guarantees there is CopyOnWriteArraySet, which uses CopyOnWriteArrayList underneath, so all of the same features hold.

Links

Standard
Java/Maven, Programming

Testing threads with JUnit

Problem
Sometimes there is a need to test a simple piece of multi-threaded code. For example, how will your code behave, when two threads read and then modify one of the variables? Well, if you know your threads you can devise and code the scenario, so that thread access is exactly right. For example, by using a mutex or semaphore. But how do you assert that your test succeeds? I mean besides sitting next to it with a debug session and checking things on every step.

JUnit is a very nice framework, but it does not handle assertions within other threads as well as one would hope it could.

Solution
I will use JUnit 4.0, but this applies to earlier versions as well.

In the sample below we have two test cases, testCaseNaive() will try to do the thing that should work out of the box. However, as far as JUnit is concerned the test succeeds with flashing lights and shooting ribbons. The second test case, testCase2Threads(), uses a somewhat hackish trick. And this trick does involve you creating the two runnables right here in the test.

The idea is quite simple, assertions in JUnit propagate up through the stack by throwing an exception, which is then caught by the test runner. If we get to execute the last statement in the thread as planned – all is well, no assertions were violated, if not – something has gone wrong. And in the case of a fail we rely on the test runner to print out the exception.

// TestMyClass.java

import java.util.ArrayList;
import java.util.Vector;
import junit.framework.Assert;
import org.junit.Test;

public class TestMyClass {

	@Test public void testCaseNaive() throws InterruptedException{
		Runnable runnable1 = new Runnable() {
			@Override public void run() {
				Assert.fail();
			}			
		};
		Thread t1 = new Thread( runnable1 );
		t1.start();
		t1.join();
	}
	
	@Test public void testCase2Threads() throws InterruptedException {
		final ArrayList< Integer > threadsCompleted = new ArrayList< Integer >();
		Runnable runnable1 = new Runnable() {
			@Override public void run() {
				Assert.fail();
				threadsCompleted.add(1);
			}
		};
		
		Runnable runnable2 = new Runnable() {
			@Override public void run() {
				Assert.assertTrue( true );
				threadsCompleted.add(2);
			}
		};
		
		Thread t1 = new Thread( runnable1 );
		Thread t2 = new Thread( runnable2 );
		
		t1.start();
		t2.start();
		t1.join();
		t2.join();
		
		System.out.println( "Threads completed: " + threadsCompleted );
		Assert.assertEquals(2, threadsCompleted.size());
	}
}
// testCaseNaive() passes, but the output still contains this
Exception in thread "Thread-0" junit.framework.AssertionFailedError: null
	at junit.framework.Assert.fail(Assert.java:47)
	at junit.framework.Assert.fail(Assert.java:53)
	at TestMyClass$1.run(TestMyClass.java:13)
	at java.lang.Thread.run(Unknown Source)
// testCase2Threads() fails and the output is:
Exception in thread "Thread-1" junit.framework.AssertionFailedError: null
	at junit.framework.Assert.fail(Assert.java:47)
	at junit.framework.Assert.fail(Assert.java:53)
	at TestMyClass$2.run(TestMyClass.java:25)
	at java.lang.Thread.run(Unknown Source)
Threads completed: [2]

Generally speaking, I have not found a nice way to assert fine detail inside a thread. The exceptions are cut off from the main thread and therefore never reach the runner. So the only way to look at these tests is to test the side effects after the test is complete or in the middle of the execution, if you can stop your threads reliably.

Standard
Java/Maven

Accessing Java Private Attributes and Methods

Java reflection is a very powerful framework.

Sometimes its power seems outside the usual Java methodology.

For example, I needed to manually change a private variable in one of the classes I was testing.

Java reflection has an API that allows this. Of course, the API does not know if one is in a test or production source code. It works anywhere!

Below is an example of three classes.

  • IntWrapper is the class under question.
  • IntWrapperTest is the JUnit class
  • RegularMainClass is a class with a main method, almost a copy of IntWrapperTest.

It is worth noting that the testers and the testee are in separate packages. So one can change the private variable or call a private method of any class in any package!

package com.otherexample;

public class IntWrapper {

	private int i;
	
	public IntWrapper(int i) {
		this.i = i;
	}

	private void incrementI() {
		i++;
	}
	
	public int getI() {
		return i;
	}
	
}
package com.example;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.junit.Test;

import com.otherexample.IntWrapper;

import static org.junit.Assert.*;

public class IntWrapperTest {

	@Test
	public void testPrivateMembers() {
		try {
			IntWrapper iw = new IntWrapper( 15 );
			assertEquals(15, iw.getI() );
			Field f = iw.getClass().getDeclaredField("i");
		
			f.setAccessible(true);
			f.setInt(iw, 18);
			assertEquals(18, iw.getI() );
			
			Method m = iw.getClass().getDeclaredMethod("incrementI");
			m.setAccessible(true);
			m.invoke(iw);
			assertEquals(19, iw.getI() );
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}
	
}
package com.example;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.otherexample.IntWrapper;


public class RegularMainClass {

	public static void main(String[] args) {
		try {
			IntWrapper iw = new IntWrapper( 15 );
			if( 15 != iw.getI() ) System.err.println("Assertion failed");
			else System.out.println("all is well 1");
			Field f = iw.getClass().getDeclaredField("i");
		
			f.setAccessible(true);
			f.setInt(iw, 18);
			if( 18 != iw.getI() ) System.err.println("Assertion failed");
			else System.out.println("all is well 2");
			
			Method m = iw.getClass().getDeclaredMethod("incrementI");
			m.setAccessible(true);
			m.invoke(iw);
			if( 19 != iw.getI() ) System.err.println("Assertion failed");
			else System.out.println("all is well 3");

		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}

}
Standard
Java/Maven

Ignoring Java Generics Safety

Java Generics (something like List <String>) provides a very nice way to group similar operation on different types of objects.

There is a way around it though.

In C++ the template invocation actually causes a new instance of the underlying type to be created and compiled. Java only creates the one type instance and then uses the generics as a variable when performing the type checks. Generics allow the compiler to enforce more type safety checks.

More type safety is a brilliant idea and I really like generics, so I have no practical use for this work around to fool the compiler safety checks. Let me know if you find one.


import java.util.ArrayList;
import java.util.Collection;

public class Q1{

	public static void main( String[] args ) {
		
		ArrayList<Integer> is = new ArrayList<Integer>();
		// list is [  ]
		
		is.add(2);
		// list is [ 2 ]
		
		Collection<?> ac = is;
		ac.add( null );
		
		// null is the only value that can be added to the ac list.
		// list is [ 2, null ]		
		
		(( ArrayList<String> ) ac).add("andrejserafim");
		
		// the above will give you an unchecked cast warning, 
		// but will compile and work
		
		// list is [ 2, null, "andrejserafim" ]
		
	}

}

Initially the list is tagged with ArrayList<Integer>.

The cast to Collection<?> wipes off that tag.

Then ArrayList<String> cast writes a new tag onto the list now stating it’s a list of strings.

Standard
Java/Maven

JUnit Testing Under Maven2

JUnit testing provides an easy to use flexible framework to write unit tests for Java code. Maven incorporates this functionality as part of it’s software life cycle. JUnit plug-in under maven2 is called Surefire.


> mvn test

Putting the above on the command line will compile the test code and run it.This is really convenient when testing someones code or if you are willing to test everything.

Single Test

However if you are the developer and are working on one specific feature tested in one test case you can run:


> mvn -Dtest=MyTestCase test

This will compile all the tests, but will run only the specified one.

Multiple Selected Tests

Sometimes you want to run just a selected set of tests. For example 2 out of 50:


> mvn -Dtest=MyTestCase,MyOtherTestCase test

This will compile all the tests, but will run only the specified two tests.

Wild Cards

You can use ‘*’ in the anywhere in the name of the class. However be careful if you have inner classes as for example My* will match MyTestCase and MyTestCase$1, which is the inner class you have used in the code, but it is not really a test and therefore the build will fail. Link to Documentation .

Cleaning

However what happens if you have discovered a bug or for some other reason edited the functional code (the one you are testing)? You will be surprised, but maven will not pick it up and will continue the old version of the compiled code. To make it compile the entire sub-project you should first clean it.


> mvn clean -Dtest=MyTestCase test

This will clean your target/ directory and therefore get rid of the old compilations. Then it will recompile the whole project along with the testing code, but still run only MyTestCase.

Abstract Tests

Before Maven 2.0.8 test cases starting with a word Abstract were not considered to be real tests. Abstract Tests are usually used if you have some testing code, which is common for 2 test cases. Then you would write an Abstract*Test class and extend it by the 2 test cases. The inheritance allows you to have the code in one place, but Abstract tests are not really test cases, so they should not be run. This changed with the new version. Excludes property contains the patterns of names, which should be excluded from testing. With its help you can remove the Abstract tests again if your project relies on it.In your pom.xml you should add:


  <build>

    <plugins>

      <!-- Added test excludes for Abstract -->
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-surefire-plugin</artifactId>
          <configuration>
            <excludes>
              <exclude>**/Abstract*</exclude>
            </excludes>
          </configuration>
      </plugin>

      <!-- ....... other configuration ....... -->

    </plugins>
  </build>

Standard