Thursday, 26 January 2012

"Java Sucks" revisited

Overview

An interesting document on Java's short comings (from C developer's perspective) was written some time ago (about 2000? ) but many of the arguments issues are as true (or not) today as they were ten years ago.

The original Java Sucks posting.

Review of short comings

Java doesn't have free().

The author lists this as a benefit and 99% of the time is a win. There are times when not having it is a downside, when you wish escape analysis would eliminate, recycle or free immediately an object you know isn't needed any more (IMHO the JIT / javac should be able to work it out in theory)

lexically scoped local functions

The closest Java has is anonymous methods. This is a poor cousin to Closures (coming in Java 8), but it can be made to do the same thing.

No macro system

Many of the useful tricks you can do with macros, Java can do for you dynamically. Not needing a macro system is an asset because you don't need to know when Java will give you the same optimisations. There is an application start up cost that macros don't have and you can't do the really obfuscated stuff, but this is probably a good thing.

Explicitly Inlined functions

The JIT can inline methods for you. Java can inline methods from shared libraries, even if they are updated dynamically. This does come at a run time cost, but its nicer not to need to worry about this IMHO.

I find lack of function pointers a huge pain

Function pointers makes in lining methods more difficult for the compiler. If you are using object orientated programming, I don't believe you need these. For other situations, I believe Closures in Java 8 is likely to be nicer.

The fact that static methods aren't really class methods is pretty dumb

I imagine most Java developers have come across this problem at some stage. IMHO: The nicest solution is to move the "static" functionality to its own class and not use static methods if you want polymorphism.

It's far from obvious how one hints that a method should be inlined, or otherwise go real fast

Make it small and call it lots of times. ;)

Two identical byte[] arrays aren't equal and don't hash the same

I agree that its pretty ugly design choice not to make arrays proper objects. They inherit from Object, but don't have useful implementation for toString, equals, hashCode, compareTo. clone() and getClass() are the most useful methods. You can use helper methods instead, but with many different helper classes called Array, Arrays, ArrayUtil, ArrayUtils in different packages its all a mess for a new developer to deal with.

Hashtable/HashMap does allow you to provide a hashing function

This is also a pain if you want to change the behaviour. IMHO, The best solution is to write a wrapper class which implements equals/hashCode, but this adds overhead.

iterate the characters in a String without implicitly involving half a dozen method calls per character

There is now String.toCharArray() but this creates a copy you don't need and is not eliminated by escape analysis. When it is, this is the obvious solution.

The same applies to "The other alternative is to convert the String to a byte[] first, and iterate the bytes, at the cost of creating lots of random garbage"

overhead added by Unicode support in those cases where I'm sure that there are no non-ASCII characters.

Java 6 has a solution to this which is -XX:+UseCompressedStrings. Unfortunately Java 7 has dropped support for this feature. I have no idea why as this option improves performance (as well as reducing memory usage) in test I have done.

Interfaces seem a huge, cheesy copout for avoiding multiple inheritance; they really seem like they were grafted on as an afterthought.

I prefer a contract which only lists functionality offered without adding implementation. The newer Virtual Extension Methods in Java 8 will provide default implementations without state. In some cases this will be very useful.

There's something kind of screwy going on with type promotion

The problem here is solved by co-variant return types which Java 5.0+ now supports.

You can't write a function which expects and Object and give it a short

Today you have auto-boxing. The author complains that Short and short are not the same thing. For efficiency purposes this can make surprisingly little difference in some cases with auto-boxing. In some cases it does make a big difference, and I don't foresee Java optimising this transparently in the near future. :|

it's a total pain that one can't iterate over the contents of an array without knowing intimate details about its contents

Its rare you really need to do this IMHO. You can use Array.getLength(array) and Array.get(array, n) to handle a generic array. Its ugly but you can do it. Its one of the helper class which should really be methods on the array itself IMHO.

The only way to handle overflow is to use BigInteger (and rewrite your code)

Languages like Scala support operators for BigInteger and it has been suggested that Java should too. I believe overflow detection is also being considered for Java 8/9.

I miss typedef

This allows you to use primitives and still get type safety. IMHO, the real issue is that the JIT cannot detect that a type is just a wrapper for a primitive (or two) and eliminate the need for the wrapped class. This would provide the benefits of typedef without changing the syntax and make the code more Object Orientated.

I think the available idioms for simulating enum and :keywords are fairly lame

Java 5.0+ has enum which are first class objects and are surprising powerful.

there's no efficient way to implement `assert'

assert is now built in. To implement it yourself is made efficient by the JIT. (Probably not tens years ago)

By having `new' be the only possible interface to allocation, ... there are a whole class of ancient, well-known optimizations that one just cannot perform.

This should be performed by the JIT IMHO. Unfortunately, it rarely does, but this is improving.

The finalization system is lame.

Most people agree its best avoided. Perhaps it could be more powerful and reliable. ARM (Automatic Resource Management) may be the answer.

Relatedly, there are no ``weak pointers.''

Java has always had weak, soft and phantom references, but I suspect this is not what is meant here. ??

You can't close over anything but final variables in an inner class!

There is true of anonymous inner classes, but not nested inner classes referring to fields. Closures might not have this restriction but its likely to be just as confusing. Being used to the requirement for final variables, I don't find this problem esp. as my IDE will correct the code as required for me.

The access model with respect to the mutability (or read-only-ness) of objects blows

The main complaint appears to be that there are ways of treating final fields as mutable. This is required for de-serialization and dependency injectors. As long as you realise that you have two possible behaviours, one lower level than the other, it is far more useful than it is a problem.

The language also should impose the contract that literal constants are immutable.

Literal constants are immutable. It appears the author would like to expand what is considered a literal constant.

It would be useful IMHO, to support const in the way C++ does. const is a keyword in Java and the ability to define immutable versions of classes without creating multiple implementations or read only wrappers would be more productive.

The locking model is broken.

The memory overhead of locking concern is really an implementation detail. Its up to the JVM to decide how large the header is and whether it can be locked. The other concern is that there is no control over who can obtain a lock. The common work around for this is to encapsulate your lock, which is what you would have to do in any case.

In theory the lock can be optimised away. Currently this only happens when the whole object is optimised way.

There is no way to signal without throwing

For this, I use a listener pattern with an onError method. There is no support in the language for this, but I don't see the need to.

Doing foo.x should be defined to be equivalent to foo.x(),

Perhaps foo.x => foo.getX() would be a better choice, rather like C# does.

Compilers should be trivially able to inline zero-argument accessor methods to be inline object+offset loads.
The JIT does this, rather than the compiler. This allows the calling code to be changed after the callee has been compiled.

The notion of methods "belonging" to classes is lame.

This is a "cool" feature which some languages support. In a more dynamic environment, this can look nicer. The down side is that you can piece of code for a class all over the place and you would have to have some way of managing duplicates in different libraries. e.g. library A defines a new printString() method and library B also defines a printString method for the same class. You would need to make each library see its own copy and have some way of determining which version library C would want when it calls this method.

Libraries

It comes with hash tables, but not qsort

It comes with an "optimised merge sort" which is designed to be faster.

String has length+24 bytes of overhead over byte[]

That is without considering that each of the two objects are aligned to an 8 byte boundary (making it higher). If that sounds bad, consider that malloc can be 16-byte aligned with a minimum size of 32 bytes. If you use a shared_ptr to a byte[] (to give you similar resource management) it can be much larger in C++ than Java.
The only reason for this overhead is so that String.substring() can return strings which share the same value array.
This is not correct. The problem is that Java doesn't support variable sized objects (apart from arrays). This means that String object is a fixed size and to have variable sized field, you have to have another object. Its not great either way. ;)

String.substring can be a source of "memory leak"

You have to know to take an explicit copy of you are going to retain a substring of a larger string. This is ugly, however the benefits usually out weight the down side. What would be a better solution is to be able to optimise the code so that a defensive copy was taken by default, except when the defensive copy is not needed (it is optimised away)

The file manipulation primitives are inadequate

The file system information has been improved in Java 7. I don't think these options are available, but can be easily inferred if you need to know this.

here is no robust way to ask ``am I running on Windows'' or ``am I running on Unix.'

There are System properties os.name, os.arch, os.version which have always been there.

There is no way to access link() on Unix, which is the only reliable way to implement file locking.

This was added in Java 7 Creating a Hard Link

There is no way to do ftruncate(), except by copying and renaming the whole file.

You can use RandomAccessFile.truncate(). Adding in Java 1.4.

Is "%10s %03d" really too much to ask?

It was added in Java 5.0

A RandomAccessFile cannot be used as a FileInputStream or FileOutputStream

RandomAccessFile supports DataInput and DataOutput, FileInputStream and FileOutputStream can be wrapped in DataInputStream and DataOutputStream. They can be made to support the same interfaces. I have never come across a situation where I would want to use both classes in a single method.

markSupported is stupid

True. There are a number of stupid methods which are only there for historical purposes. Another being Object.wait(millis, nanos) on every object (even arrays) and yet the nanos is never really used.

What in the world is the difference between System and Runtime?

I agree it appears arbitrary and in some cases doubled up. System.gc() actually calls Runtime.getRuntime().gc() and yet is called System GC even in internal code. In hind site they should really be one class with monitoring functionality moved to JMX.

What in the world is application-level crap like checkPrintJobAccess() doing in the base language class library

So your SecurityManager can control whether you can perform printing. (Without having to have an Application level Security Manager as well) Not sure is this really prevents the need to have Application level security. ;)

Monday, 23 January 2012

Demonstrating when volatile is required

Overview

In many cases volatile is required when you need a guarantee about visibility of changes between threads. i.e. All threads see a consistent view of the same field. Demonstrating a consistent failure when you don't use volatile is tricky, and likely to be platform specific.

An example

The following example show that each thread starts by flipping the value and then stops as each thread has a different view of the field value This works on Java 7 update 2 on Centos 5.7 (x64).

Even incidental change to the code, change the behaviour showing how brittle the example is. I would be interested if others can reproduce this behaviour

The code

public class RequiresVolatileMain {
    static boolean value;

    public static void main(String... args) {
        new Thread(new MyRunnable(true), "Sets true").start();
        new Thread(new MyRunnable(false), "Sets false").start();
    }

    private static class MyRunnable implements Runnable {
        private final boolean target;

        private MyRunnable(boolean target) {
            this.target = target;
        }

        @Override
        public void run() {
            int count = 0;
            boolean logged = false;
            while (true) {
                if (value != target) {
                    value = target;
                    count = 0;
                    if (!logged)
                        System.out.println(Thread.currentThread().getName() + ": reset value=" + value);
                } else if (++count % 1000000000 == 0) {
                    System.out.println(Thread.currentThread().getName() + ": value=" + value + " target=" + target);
                    logged = true;
                }
            }
        }
    }
}

As you can see, each thread tries to flip the value whenever it doesn't match the target. When you attempt to run this fails, perhaps not in the way you might expect. If you run this with -XX:+PrintCompilation

Sets true: reset value=true
Sets false: reset value=false
....
Sets true: reset value=true
Sets false: reset value=false
     44    1 %           com.google.code.java.core.threads.RequiresVolatileMain$MyRunnable::run @ 4 (129 bytes)
Sets true: reset value=true
Sets false: reset value=false
....
Sets true: reset value=true
Sets false: reset value=false
Sets true: value=false target=true
Sets false: value=true target=false
...
Sets true: value=false target=true
Sets false: value=true target=false
Not long after the code is compiled, the code starts acting as if it doesn't detect a change even though the value printed is clearly not the target. Exactly why it fails this way is not clear. esp. as the value in the same thread appears to be inconsistent.

The only explanation I can come up with is that if (value != target) has been incorrectly optimised away. Possibly because the only branch which sets this value is not run most of the time.

Just caching the value stops it failing for me, but this is not a proper fix and might fail on a different platform

                // caching the value stops the failure.
                boolean value = RequiresVolatileMain.value;
                if (value != target) {
                    RequiresVolatileMain.value = target;

The solution

The solution is to use a volatile variable, in which case it keeps printing that the value is reset as expected.

Why does this fail

The values are boolean. This is like a game of ping-pong. The ball is only on one side, either true or false (if you use volatile) It doesn't matter which values it is, only one thread will change the value.

Without volatile, this breaks down in a number of possible ways. One way is that the two threads each think they have changed the value and are waiting for the other i.e. each has its own cached copy of the value.

The way it breaks down in the example above is that the compiler detect that the value is not changed if it is the target value already and the thread is not going to set it to any other value. It then assumes the check isn't required and even though both thread print the value as needing changing (the opposite of the previous case) it stops changing the value.

Sunday, 22 January 2012

Another Shifty Challenge

Overview

Shifting has lots of edge cases. Some particular to Java.

Over shifting

In C the expression n << 64 and n >> 64 would always be 0, but in Java it will always be n This is because the shifted value is mod'ed by the number of bits.

A puzzle

If the following program
for (int i = -200; i < 200; i++)
    if (i >>> i == 1)
        System.out.print(i+" ");
prints
-193 -161 -129 -97 -65 -33 -1 37 70 102 135 167 199 
What do you get if you change the type to long?

See if you can work it out without running the code.

Thursday, 19 January 2012

Shifting Challenge

Overview

Using shift in Java and some surprising edge cases.

Getting the sign

For the following program, what is the values for n so that I can change the type of x without having to change the code.
// sign is 1 if negative and 0 if non-negative
long sign = x >>> n;
There is a value you can replace n such that you don't need to know the type of x

Similarly, I want to shift the lowest bit to be the highest without knowing what type I am shifting

// sign is MIN_VALUE if odd otherwise 0
long sign = x << n;

For bonus points, write formula for all the possible solutions of n (there is more than one)

Is a power of two

How do you determine an integer is a power of 2.

This is a fairly common interview question. Its pretty hard to figure out in an interview I imagine. To save you googling, you can write this in C with

x&&!(x&(x-1))
In Java, you can write this using just 0 ~ - & == != . Complete this expression using those operators
long x = 
boolean isPow2 = x != 0 .....

Wednesday, 18 January 2012

Unsigned Challenge

Overview

Its easy to assume that because Java doesn't support unsigned primitives that you need a complex wrapper to using unsigned numbers.

The challenge

Modify the following class which has been written to use signed int as unsigned value. The starting code works for signed values. You need to change the methods so it treats them as unsigned 32-bit int values. The aim is to add/change a minimum of lines. (You can't change the tests or turn them off)

public enum Unsigned {;
    public static int add(int i, int j) {
        return i + j;
    }

    public static int subtract(int i, int j) {
        return i - j;
    }

    public static int multiply(int i, int j) {
        return i * j;
    }

    public static int shiftLeft(int i, int n) {
        return i << n;
    }

    public static int shiftRight(int i, int n) {
        return i >> n;
    }

    public static int parseUnsignedInt(String text) {
        return Integer.parseInt(text);
    }

    public static String toString(int n) {
        return Integer.toString(n);
    }

    public static void main(String... args) {
        assert "2500000000".equals(toString(subtract(add(2000 * 1000 * 1000, 1750 * 1000 * 1000), 1250 * 1000 * 1000)));
        assert "4000000000".equals(toString(multiply(1000 * 1000, 4000)));
        assert "3200000000".equals(toString(shiftLeft(100 * 1000 * 1000, 5)));
        assert "1000000000".equals(toString(shiftRight(parseUnsignedInt("4000000000"), 2)));

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baos);
        writeUnsignedInt(dos, multiply(1000 * 1000, 4000));
        writeUnsignedInt(dos, parseUnsignedInt("3210000000"));
        dos.close();
        DataInputStream dis = new DataInputStream(new ByteArrayInputStream(baos.toByteArray()));
        assert "4000000000".equals(toString(readUnsignedInt(dis)));
        assert "3210000000".equals(toString(readUnsignedInt(dis)));
        dis.close();
    }
}

Hint: The solutions are surprisingly simple (which is the point of this article) If you are adding many lines of code, you are heading down the wrong path.

Monday, 16 January 2012

Java Thread Affinity support for ExecutorService

Overview

The Java Thread Affinity version 1.4.1 library has support for the concurrency library through an AffinityThreadFactory.

This follows my previous article on HyperThreading support in the library which give mroe detail on what it does and how it works.

Example

In the AffinityThreadFactoryMain example,
private static final ExecutorService ES = Executors.newFixedThreadPool(4,
        new AffinityThreadFactory("bg", SAME_CORE, DIFFERENT_SOCKET, ANY));

public static void main(String... args) throws InterruptedException {
    for (int i = 0; i < 12; i++)
        ES.submit(new Callable() {
            @Override
            public Void call() throws InterruptedException {
                Thread.sleep(100);
                return null;
            }
        });
    Thread.sleep(200);
    System.out.println("\nThe assignment of CPUs is\n" + AffinityLock.dumpLocks());
    ES.shutdown();
    ES.awaitTermination(1, TimeUnit.SECONDS);
}

by changing the ThreadFactory, you can decide how threads in the factory should be laid out. The default behaviour is to allocate from highest CPU id to lowest, however by changing the AffinityStrategy you can make it try to minimise the number of cores it uses.
Assigning cpu 7 to Thread[bg,5,main]
Assigning cpu 6 to Thread[bg-2,5,main]
Assigning cpu 3 to Thread[bg-3,5,main]
Assigning cpu 2 to Thread[bg-4,5,main]

The assignment of CPUs is
0: General use CPU
1: General use CPU
2: Thread[bg-4,5,main] alive=true
3: Thread[bg-3,5,main] alive=true
4: General use CPU
5: General use CPU
6: Thread[bg-2,5,main] alive=true
7: Thread[bg,5,main] alive=true

Releasing cpu 7 from Thread[bg,5,main]
Releasing cpu 6 from Thread[bg-2,5,main]
Releasing cpu 3 from Thread[bg-3,5,main]
Releasing cpu 2 from Thread[bg-4,5,main]
In this case, the second thread is allocated to the SAME_CORE as the first, the third cannot get one on the same core so it tries to get on on a DIFFERENT_SOCKET, but there is only one so it takes ANY available core which can be reserved.

Related topics

Java Thread Affinity support for hyper threading.
Java Thread Affinity supports groups of threads.
Thread Affinity library for Java supports JNA
Thread Affinity library for Java.

Java Thread Affinity support for hyper threading.

Overview

A benefit of hyper-threading is the ability to support more threads without incurring the overhead of context switches. If your threads spend a high proportion of their time waiting for resources e.g. busy waiting on a data source, accessing main memory or waiting for short periods of time for IO, hyper threading can improve performance at little cost.

However, hyper threading can impact performance when the two threads on the same core start competing for resources, such as the FPU, Level 1 cache, or CPU pipeline. For these reasons, hyper-threading is often turned off in high performance systems.

A solution to get the best of both worlds

The Java Thread Affinity version 1.4 library attempts to get the best of both worlds, by allowing you to reserve a logical thread for critical threads, and reserve a whole core for the most performance sensitive threads. Less critical threads will still run with the benefits of hyper threading.

Example

Say you have a system e.g. an Intel i7 with four core and two logical threads per core.
You want to reserve two cores to dedicate to critical threads. On Linux you can do this but using isolcpus= in grup.conf
Say you have two critical thread which are busy waiting for resources and can share a core called "reader" and "writer" and you have an "engine" thread you want to dedicate a whole core to (so it doesn't have to compete for resources) You can assign the threads as follows.
The "engine" only uses "CPU 3" and "CPU 7" is reserved as idle.

How does this look in code

Sample code to allocate these thread/cores is as follows
AffinityLock al = AffinityLock.acquireLock();
try {
    // find a cpu on a different socket, otherwise a different core.
    AffinityLock readerLock = al.acquireLock(DIFFERENT_SOCKET, DIFFERENT_CORE);
    new Thread(new SleepRunnable(readerLock, false), "reader").start();

    // find a cpu on the same core, or the same socket, or any free cpu.
    AffinityLock writerLock = readerLock.acquireLock(SAME_CORE, SAME_SOCKET, ANY);
    new Thread(new SleepRunnable(writerLock, false), "writer").start();

    Thread.sleep(200);
} finally {
    al.release();
}

// allocate a whole core to the engine so it doesn't have to compete for resources.
al = AffinityLock.acquireCore(false);
new Thread(new SleepRunnable(al, true), "engine").start();

Thread.sleep(200);
System.out.println("\nThe assignment of CPUs is\n" + AffinityLock.dumpLocks());
This code declares that the "main" thread uses a cpu (it gets 7). The "reader" thread should use a different socket or a different core. It get a different core as there is no second socket. The "writer" thread tries to get a thread on the same core, or the same socket, or any thread. The AffinityStrategy is an interface which allows you to create your own thread allocation strategies.

The "engine" thread tries to allocate a whole core to the thread. (It finds a core where it can allocate all the threads for that core)

When run on an i7 with isolcpus=2,3,6,7 you get the following output

Assigning cpu 7 to Thread[main,5,main]
Assigning cpu 6 to Thread[reader,5,main]
Assigning cpu 2 to Thread[writer,5,main]
Releasing cpu 7 from Thread[main,5,main]
Assigning core 3: cpus 3, 7 to Thread[engine,5,main]

The assignment of CPUs is
0: General use CPU
1: General use CPU
2: Thread[writer,5,main] alive=true
3: Thread[engine,5,main] alive=true
4: General use CPU
5: General use CPU
6: Thread[reader,5,main] alive=true
7: Thread[engine,5,main] alive=true

Related topics

Java Thread Affinity support for ExecutorService
Java Thread Affinity supports groups of threads.
Thread Affinity library for Java supports JNA
Thread Affinity library for Java.