Feeds:
Posts
Comments

Archive for the ‘Java tips’ Category

Let’s take a very simple code example just to understand where I am heading to:

public class Tester {

  public static void main(String[] args) {

    String[] strings = {"alpha", "beta"};
    Integer[] integers = {1, 2, 3};
    Long[] longs = {31L, 76L};
    Short[] shorts = {7, 8, 9};

    printAnArrayOfAnything(strings);
    printAnArrayOfAnything(integers);
    printAnArrayOfAnything(longs);
    printAnArrayOfAnything(shorts);

  }

  private static void printAnArrayOfAnything(Object[] objects) { 
   
    StringBuilder out = new StringBuilder("");
    for (Object obj : objects)
      out.append(obj.getClass().getSimpleName()).append("=")
         .append(obj).append(" ");
    System.out.println(out.toString());

  }
}

The output would be:

String=alpha String=beta
Integer=1 Integer=2 Integer=3
Long=31 Long=76
Short=7 Short=8 Short=9

The method printAnArrayOfAnything() can process any of the declared arrays. This is because in Java, arrays of objects are co-variant. This means that the added assignment statements are accepted by the compiler:

public class Tester {

  public static void main(String[] args) {

    String[] strings = {"alpha", "beta"};
    Integer[] integers = {1, 2, 3};
    Long[] longs = {31L, 76L};
    Short[] shorts = {7, 8, 9};

    Object[] objects = integers;
             objects = longs;
             objects = shorts;

Otherwise said Integer[] is an Object[]
Equally Long[], Short[] or an array of any Object sub-class is an Object[]

This is why, even though the method expects a parameter of type Object[], an array of any component, sub type of Object, will be accepted.

Now, the problem with co-variance is illustrated by the following example:


public class Tester {

  public static void main(String[] args) {

    Integer[] integers = {1, 2, 3};
    Object[] objects = integers;

    objects[0] = "A string";
  }
}

This code compiles just fine. Nothing prevents you from putting a String in an Object array, right?

But, in fact, objects points to an array of Integer. So putting a String in it would corrupt this array.

This kind of programming error is unfortunately caught only at run time in Java.

It will raise the following Exception:

Exception in thread "main" java.lang.ArrayStoreException: java.lang.String

In Java arrays, the type of the element is kept in an instance variable, making at least such a run time safety net available.

We will see that conversly, in generic types, the type parameters being erased at run time, forces such generic type to be non covariant (or rigid).

On the other end, what can you do if you deal with arrays of primitive types instead of sub-classes of Object?

public class Tester {

  public static void main(String[] args) {

    int[] ints = {10, 20, 30};
    long[] longArray = {67L, 23L};
    short[] shortArray = {87, 79, 9};

    printAnArrayOfAnything(ints);   // does not compile
    printAnArrayOfAnything(longs);  // does not compile
    printAnArrayOfAnything(shorts); // does not compile

  }

  private static void printAnArrayOfAnything(Object[] objects) {
    
      StringBuilder out = new StringBuilder("");
      for (Object obj : objects)
        out.append(obj.getClass().getSimpleName()).append("=")
           .append(obj).append(" ");
      System.out.println(out.toString());

  }
}

Obviously, neither int[], long[] or short[] conform to Object[], since int, long or short are just NOT Objects.

What we would need is a super-type T of int, long or short and use it as the type of the parameter of the method, like this: printAnArrayOfAnything(T[] items).

But such of super-type just does not exist. Of course we could use Object as a super type of int[], short[], long[] etc, but with an Object we cannot iterate to print the elements of the underlying array.

So, should we renounce to have a unique method to print all these different arrays of primitives? Not exactly, but we need to convert each array of primitives to an array of Object:

public class Tester {

  public static void main(String[] args) {

    String[] strings = {"alpha", "beta"};
    Integer[] integers = {1, 2, 3};
    Long[] longs = {31L, 76L};
    Short[] shorts = {7, 8, 9};

    printAnArrayOfAnything(strings);
    printAnArrayOfAnything(integers);
    printAnArrayOfAnything(longs);
    printAnArrayOfAnything(shorts);

    int[] ints = {10, 20, 30};
    long[] longArray = {67L, 23L};
    short[] shortArray = {87, 79, 9};

    printAnArrayOfAnything(ints);
    printAnArrayOfAnything(longArray);
    printAnArrayOfAnything(shortArray);

  }

  private static void printAnArrayOfAnything(Object param) {

    Object[] objects;

    if (param instanceof Object[])
      objects = (Object[]) param;
    else
      objects = toWrapperArray(param);

    StringBuilder out = new StringBuilder("");
    for (Object obj : objects)
      out.append(obj.getClass().getSimpleName()).append("=")
         .append(obj).append(" ");
        
    System.out.println(out.toString());

  }

  public static Object[] toWrapperArray(Object array) {

    if (Array.getLength(array) == 0)
      return new Object[0];

    Class wrapperClass = Array.get(array, 0).getClass();
    Object[] objArray = (Object[]) Array.newInstance(wrapperClass,
                                   Array.getLength(array));
    int i = 0;
    for (Object o : objArray) {
      objArray[i] = Array.get(array, i);
      i++;
    }
    return objArray;
  }
}

Here, we change the type of the method parameter to Object and not Object[], to be more general and encompasses array of primitives (line 24).

The method toWrapperArray() is called when dealing with arrays of primitives. Its duty is to transform the array of primitives received, to an array of the corresponding wrapper class instances.

For example int[] will be transformed to Integer[], short[] to Short[] etc.

For doing so, some static methods of the class Array are very handy to handle an array even so it has been declared as a simple Object.

The method Array.get() is a replacement to T[i] for example. Moreover, Array.get() returns the element as a wrapper instance. i. e. it will return an Integer instance if called on an int[]

This way we can get the wrapper class of the array primitive element and are able to build an array of the wrapper class instances.

The drawback of this method is that the array must not be empty, otherwise Array.get() rises an ArrayIndexOutOfBoundsException.

In this occurrence, we simply return an empty Object[] instead of an empty Integer[], or Long[], which is not perfectly correct.

Alternatively, we could do this:

public class Tester {

  public static void main(String[] args) {

    boolean[] bools = {true, false};
    char[] chars = {'a', 'b', 'c'};
    byte[] bytes = {};
    short[] shortArray = {87, 79, 9};
    int[] ints = {10, 20, 30};
    long[] longArray = {67L, 23L};
    float[] floats = {1.2f, 3.78f, 3.14f};
    double[] doubles = {3 / 4d, 1 / 3d};

    printAnArrayOfAnything(bools);
    printAnArrayOfAnything(chars);
    printAnArrayOfAnything(bytes);
    printAnArrayOfAnything(shortArray);
    printAnArrayOfAnything(ints);
    printAnArrayOfAnything(longArray);
    printAnArrayOfAnything(floats);
    printAnArrayOfAnything(doubles);

  }

  private static void printAnArrayOfAnything(Object param) {

    Object[] objects;

    if (param instanceof Object[])
      objects = (Object[]) param;
    else
      objects = toWrapperArray(param);

    StringBuilder out = new StringBuilder(
                            objects.getClass()
                                   .getComponentType()
                                   .getSimpleName()
                            + "[");

    for (Object obj : objects)
      out.append(obj).append(", ");

    if (objects.length > 0)
      out.setLength(out.length() - 2);

    out.append("]");

    System.out.println(out.toString());

  }

  public static Object[] toWrapperArray(Object array) {

    Class primitiveClass = array.getClass().getComponentType();
    Class wrapperClass = primitiveToWrapper.get(primitiveClass);
    Object[] objArray = (Object[]) Array.newInstance(wrapperClass,
                                   Array.getLength(array));
    int i = 0;
    for (Object o : objArray) {
      objArray[i] = Array.get(array, i);
      i++;
    }
    return objArray;
  }

  private static Map<Class, Class> primitiveToWrapper 
                                      = new HashMap<Class, Class>();

  static {
    primitiveToWrapper.put(Boolean.TYPE, Boolean.class);
    primitiveToWrapper.put(Character.TYPE, Character.class);
    primitiveToWrapper.put(Byte.TYPE, Byte.class);
    primitiveToWrapper.put(Short.TYPE, Short.class);
    primitiveToWrapper.put(Integer.TYPE, Integer.class);
    primitiveToWrapper.put(Long.TYPE, Long.class);
    primitiveToWrapper.put(Float.TYPE, Float.class);
    primitiveToWrapper.put(Double.TYPE, Double.class);
  }
}

This output would be:


Boolean[true, false]
Character[a, b, c]
Byte[]
Short[87, 79, 9]
Integer[10, 20, 30]
Long[67, 23]
Float[1.2, 3.78, 3.14]
Double[0.75, 0.3333333333333333]

This way, the array’s component type is correct even though the array is empty.

Unfortunately, there is no way to obtain directly the wrapper class from a primitive class (or at least I never found it!).
However, there is the field TYPE in every wrapper class that indicates the corresponding primitive class. We take advantage of this to build a correspondance map.

In a coming post, we will explore polymorphic aspects of generic types like collections and the impact of having covariant type parameters or not.

Finally we will compare Java and Scala design on these aspects.

Stay tuned !

Advertisements

Read Full Post »

After the previous post, I was still uncertain about the best and safe way to manage a cache of objects without paying too much price for the apparently unvoidable synchronization!

Then I found these articles:


Concurrent structures and collections in Java 5

Java theory and practice: Concurrent collections classes

So it suffices to replace the class HashMap by ConcurrentHashMap, like this:


private ConcurrentMap<String, HeavyObject> cache 
  = new ConcurrentHashMap<String, HeavyObject>();

public HeavyObject getHeavyObject(String key) {
    HeavyObject anObject = cache.get(key);
    if (anObject  == null) {
        anObject = getHeavyObjectFromDataBase(key);
        cache.put(key, anObject);
    }
    return anObject;
}

It is not perfect still, because there is a possibility that two threads add the same object in a very short time. But at least, when an object is already in the cache, there is apparently a very little overhead compared to traditionnal synchronization and there is no risk of corrupting the map by concurrent updates.

Notice that I am not using the method putIfAbsent because anyway I will have paid the price of retrieving the object from the database, so, I prefer refreshing the cache with the most current object.

If you use JMX to reload objects after they have been modified externaly in the database, you need simply to do this:


public void reloadObject(String key) {
    anObject = getHeavyObjectFromDataBase(key);
    cache.put(key, anObject);   
}

This is the best way I found so far. I will use it now for all projects.

Thank you Neil Coffey and Brian Goetz !

Read Full Post »

Let’s say that you need random access to some persisted objects and that retrieving them is a costly operation.

You will naturally come up with the idea of putting these objects into a cache. Each time you need a particular object, you will first look in the cache, in case it has already been read. If it has not, you will read it from the database or the related service and you will put it in the cache for later use, before delivering it to the requester. This is a classical method.

For example, assuming we want to put instances of HeavyObject in cache and that the key of these objects is a String:


private Map<String, HeavyObject> cache = new HashMap<String, HeavyObject>();

public synchronized HeavyObject getHeavyObject(String key) {
    HeavyObject anObject = cache.get(key);
    if (anObject  == null) {
        anObject = getHeavyObjectFromDataBase(key);
        cache.put(key, anObject);
    }
    return anObject;
}

If you are in a multi-threaded environment, you need to synchronize the getHeavyObject() method. Otherwise the cache map could be (and will be) corrupted by concurrent modification. In simple case, where the cached objects are not mutable it could not be a big deal, resulting only in reading more objects than necessary. But in more complex situations, it could simply be not acceptable.

With synchronization you ensure the data integrity. The problem is that you pay a price for this synchronization even when the hit ratio is growing high, meaning that most objects requested happen to be already in the cache.

You could be tempted by a technique called “double-check”, to cancel the synchronization time penalty. I will not describe this technique here, first because it has been explained numerous times and you can easily find articles on it. But I will simply say that it is proved that this technique just don’t work, due to the way the JVM optimizes its memory accesses.

So, what else can we do?

I use the following approach and never had any problem with it.

I use two caches, the primary cache and the secondary one.


private Map<String, HeavyObject> primaryCache = 
                            new HashMap<String, HeavyObject>();
private Map<String, HeavyObject> secondCache = 
                            new HashMap<String, HeavyObject>();

public HeavyObject getHeavyObject(String key) {
    HeavyObject anObject = primaryCache.get(key);
    if (anObject  == null) {
        synchronized(this) {
            anObject = secondCache.get(key);
            if (anObject  == null) {
                anObject = getHeavyObjectFromDataBase(key);
                secondCache.put(key, anObject);
                primaryCache = 
                    new HashMap<String, HeavyObject>(secondCache);
            }
        }
    }
    return anObject;
}

Initially both caches are empty. When an object is requested, we first look into the primary cache without synchronization. If it is not found then when entered a synchronized block which ensures that only one thread at a time can execute this piece of code.

If the record is not found in the second cache either, it is retrieved from the database and added to the secondary cache. Then, the secondary cache is simply cloned to make the primary cache.

After this process, both caches contain the same set of objects.

Now let’s say that thread A look for the object 1. And a few micro-seconds later, thread B looks for the very same object. Both lookups will fail because the object 1 is not in the cache. Then only one thread begins the synchronized block, let’s say thread A, while thread B is waiting for the lock to be released.

When thread A will release the lock, the object 1 will have been put into both caches. Thread B will enter the synchronized block but will not do anything since it will find the object in the secondary cache.

By this technique we can have the best of both worlds. No synchronization when there is a hit, and a synchronized update of the cache.

I have just finished to explain this pattern and, quite frankly, I am not so sure anymore that it is bulletproof!

May be I was just lucky so far!

Have I just re-invented the “double-check” on disguise?

So, if you are kings of the JVM, your input would be more than welcomed!

Read Full Post »