Monday, 3 December 2012

Java Cafe 3 : WeakReferences and the caveats of WeakHashMap

WeakReference

First of all, lets see what a WeakReference is. A normal reference to an object is a strong reference, e.g.:

List list = new LinkedList();
list.add(1)

list is a strong reference to a LinkedList object. It prevents the garbage-collector from removing the LinkedList from memory, as long as list is in the current scope of executing Java program. Now, you can also wrap it around a WeakReference:

WeakReference<List<Integer>> list = new WeakReference<List<Integer>>(new LinkedList<Integer>());

List myList = list.get();
myList.add(1);

You now have a WeakReference (list) to a LinkedList, and you can obtain the LinkedList using the WeakReference.get() method. The purpose of a WeakReference is to allow the garbage-collector to gc the referred object if necessary. Consider the code below:

WeakReference<List<Integer>> list = new WeakReference<List<Integer>>(new LinkedList());
list.get().add(1);

int i = 0;
while (i < 10) {
    System.gc();
    i++;
    if (list.get() == null) {
        System.out.println("GC-ed at iteration " + i);
        break;
    }
}

On my JVM, it prints out:

GC-ed at iteration 1

That is, the LinkedList has been garbage-collected after the first System.gc() call (note that this does not necessarily have to happen)! While this behaviour is not guaranteed, we have certainly shown that WeakReferences allows the referred object to be garbage-collected.

WeakHashMap

The java.util.WeakHashMap class is one of the least frequently used in the Collections package, and it uses WeakReferences internally. It is meant to serve as a caching map where the entries can be garbage-collected if the JVM is running low on memory. It accomplishes this by weak referencing the keys in the map, also called weak keys. For instance, if you have a WeakHashMap which maps Strings to Integers:

String key = new String("one");
Integer value = new Integer(1);

WeakHashMap<String,Integer> weakMap = new WeakHashMap<String,Integer>();
weakMap.put(key, value);

key = null;
value = null;

If there are no other references to key, then map entry (key, value) can (but non-necessarily) be garbage-collected the next time GC happens. If that happens, the size of the WeakHashMap will reduce from 1 to 0, and the object key will be garbage-collected:

String key = new String("one");
Integer value = new Integer(1);

WeakHashMap<String,Integer> weakMap = new WeakHashMap<String,Integer>();
weakMap.put(key, value);

key = null;

int i = 0;
while (i < 100) {
    System.gc();
    i++;
    if (weakMap.size() == 0) {
        System.out.println("GC-ed at iteration " + i);
        break;
    }
}

In my JVM, weakMap becomes empty at iteration 6. If there are no other references to the object value, it will be garbage-collected too.

One important fact to know about the WeakHashMap is that the value objects are held using strong references. Therefore, if you had mistakenly wrote:

WeakHashMap<String,String> weakMap = new WeakHashMap<String,String>();
weakMap.put(key, key);

The entry for key will never be garbage-collected, because key is also held as the value object using a strong reference. If you need to use the same object as the value, it is recommended that you wrap it around a WeakReference, like:

weakMap.put(key, new WeakReference(key));

This way, there will be no strong references to key, allowing it to be garbage-collected.

Sunday, 25 November 2012

Java Cafe 2 : try-with-resources statement in Java 7

Prior to Java 7, if you open a resource like a file or network connection in a method, you will typically write code like below, provided that you want to handle all exceptions inside the method. This method prints the first character in a text file, and prints the stack trace of any exceptions thrown:


public void printFirstChar() {
    FileReader reader = null;
    try {
        reader = new FileReader("ex.txt");
        System.out.println((char)reader.read());
    } catch (IOException ioe) {
        ioe.printStackTrace();
    } finally {
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 

It is necessary close the resource in a finally block to guarantee the file is closed even if there were exceptions thrown, and the finally block must catch the IOException thrown by the reader.close() method. Because of closing in finally, and also you want to catch the FileNotFoundException (as an IOException) from FileReader constructor, you need to declare reader outisde the try and initialize it to null. This is obviously very clumsy.

The try-with-resources statement introduced in Java 7 solves all this. A resource is any object that must be closed after the program is done with it. This try-with-resources statement automatically closes the resource (in our case the reader) at the end of the statement. Any object that implements java.lang.AutoCloseable (new in Java 7, and simply has a close() method) can be used as a resource in the try-with-resources statement. The interface java.io.Closeable extends AutoCloseable, so any Closeable object can be used as a resource. This includes all commonly used classes in the java.io package. Using try-with-resources, our example above can be succinctly written as:

public void printFirstChar() {
    try (FileReader reader = new FileReader("ex.txt")) {
        System.out.println((char)reader.read());
    } catch (IOException ioe) {
        ioe.printStackTrace();
    }
}

17 lines of code shortened to 7! The reader object will be closed at the end of the try-with-resources statement regardless of any exception thrown. Note that if the file ex.txt does not exist, then the FileNotFoundException will be caught by the catch clause, and the stack trace of FileNotFoundException will be printed. If you do not have the catch clause, then your printFirstChar() method must throw IOException, like:

public void printFirstChar() throws IOException {
    try (FileReader reader = new FileReader("ex.txt")) {
        System.out.println((char)reader.read());
    }
}

What if an exception is thrown when reader.read() is called, and then when try-with-resources closes reader, an exception is thrown as well? The exception from reader.read() will be thrown by the printFirstChar() method, while the exception from the close will be suppressed. These suppressed exceptions can be retrieved by the calling method using the Throwable.getSuppressed() method like below:

try {
    printFirstChar();
} catch (IOException ioe) {
    for (Throwable t : ioe.getSuppressed()) {
        // do something with the suppressed exception
    }
}

Saturday, 24 November 2012

Java Cafe 1 : Never write NaN == NaN (they're not equal)

I see this Java bug time and time again:

NaN == NaN

So what's wrong with this?

The Float and Double classes in java.lang defines a constant holding a Not-a-Number (NaN) value of type float and double respectively. NaN can be used to represent a mathematically undefined number, such as that obtained by dividing zero by zero, or an unrepresentable value, such as the square root of a negative number, which is imaginary so cannot be represented as a real floating-point number. For instance:

System.out.println(0.0f / 0.0f);
System.out.println(Math.sqrt(-1.0f));

prints out:

NaN
NaN

Sometimes programmers initialize a class field to NaN to indicate that it has not been assigned a value. Later on in the program, they check if that field has been assigned a value by checking if it is equal to NaN, using the == operator, e.g.:

public class NaNTest {
    private float value = Float.NaN;

    public void setValue(float newValue) {
        if (value == Float.NaN) // wrong, never do this!
            value = newValue;
    }

    public float getValue() { return value; }
}

Unfortunately, value will never be set to newValue in the setValue() method, because (Float.NaN == Float.NaN) always returns false. In fact, if you look at the JDK implementation of Float.isNaN(), a number is not-a-number if it is not equal to itself (which makes sense because a number should be equal to itself). The same holds for Double.NaN.

This error is easy to make, because the == operator is what you will normally use to compare numbers and primitive types. This bug can go unnoticed for a long time, potentially giving disastrous consequences. For instance, if the code that uses the value returned by getValue() performs the same faulty equality check, and then performs some critical operations:

NaNTest test = new NaNTest();
test.setValue(4.0f);           // does not set it 4.0f
float value = test.getValue(); // returns Float.NaN
float result = 0.0f;
if (value != Float.NaN) {
    result = value;
}
System.out.println(result);    // prints NaN

Although not immediately obvious, the printed value will always be NaN, not 4.0. This is because value has the value Float.NaN, and (Float.NaN != Float.NaN) is always true!

The correct way to check if a number is NaN is to use Float.isNaN() and Double.isNaN(). For example, continuing with the NaNTest class:

public void setValue(float newValue) {
    if (Float.isNaN(value))
        value = newValue;

}

Equivalently, this will also work:

public void setValue(float newValue) {
    // works but don't do this
    if (value != value)    // yes, this check is weird!
        value = newValue;
}

but you should use Float.isNaN() and Double.isNaN() because they make clear the intention of the check, and they will work regardless of any changes to the underlying floating-point implementation of Java.

Finally, the same applies to checking for positive and negative infinity: always use Float.isInfinite() and Double.isInfinite().

The Edukators

This is one of the most provocative movies I've seen this year. It explores rebellion, capitalism, greed, grassroot revolutions, society, and morality, amongst other topics. I knew about it when it was nominated for the Palme d'Or at the 2004 Cannes Film Festival, and had always wanted to see it but never had the chance.

The movie is about two young men who break into rich people's houses, re-arranging the furniture, and leave a note say "The days of plenty are numbered" or "You have too much money". They call themselves 'The Edukators', to 'educate' rich people that it is 'crime' to hoard their wealth when many poor people are suffering. The girlfriend of one of them was indebted to a very rich CEO, Hardenberg, for 100,000 euros, after totalling his car during a car accident. She had to work her whole life to pay back the debt. When she found out they were The Edukators, she persuaded them to break into Hardenberg's mansion. Hardenberg eventually saw them breaking in, and the three of them kidnapped him to the mountains. There, Hardenberg revealed that he used to be a rebel like them when he was their age. A week later, the three realised that it was wrong for them to kidnap him, so they drove him back to his mansion. Hardenberg initially was not going to report to the police, but later changed his mind and reported them. Luckily, they knew he was going to report them early on, so they had left before the police came.

One of the most striking revelations in the movie was that Hardenberg was once a live-free-or-die rebel like the 3 youngsters, but eventually became a capitalist himself. How could someone so full of ideals and aspirations become such a confirmist? After he got married and have children, he had a lot of bills to pay, so he began wanting the next promotion and the money that comes with it; and before he knew it, he became a hard-hearted capitalist, chasing after wealth and material. He admitted that he once thought of giving it all up, moving to the suburbs with his wife and becoming a school teacher, but that thought never became reality. The 'crime' of being a capitalist today, as one of the young characters said, is that workers at the bottom are being exploited by people at the top to produce fat profits for the company, and therefore fat bonuses for people at the top. 'Factory workers in Vietnam who make 30 euros a year would also have appreciated a fair pay,' the girl said. The line, 'inventing the rifle is different from pulling the trigger', points out that the problem is not in capitalism itself, but in the people who exploits workers to achieve maximum profits in the name of capitalism. Unfortunately, in the current age, most capitalist systems are riddled with people who twists capitalism into something inhumane and unsustainable. The same has been true for communism, which historically has been twisted to achieve inhumane goals.

From Hardenberg's eventual conformity, it follows that one of the main contentions of the movie is how our surroundings shape our sense of morality. It is metaphorical that Hardenberg was kidnapped from his lavish mansion in the capitalist city, and brought to this basic wooden hut at the top of the mountains, where he can't even reach the nearest store without driving for half an hour. For a week, he had no access to money and the luxuries of urban living. He was 'removed' from the capitalist world. Living with The Edukators reminded him that he was once like them, a young anti-capitalism, against the system and surrounded by 'free love'. You can feel his gradual assimilation into the group of rebels, and voluntarily forgave the girl of her debt. One would almost think that the experience has cleansed him of capitalism. So it was not surprising that, upon returning to his lavish mansion, where he was alone with his material belongings, he almost became a wreck and plunged into a moral crisis, questioning his life and what he has become. In an unexpected twist of events, he reported The Edukators to the police. Surrounded again by material and capitalism, he can't help but act to protect his properties and way of life, forgetting his transformation in the mountains. Fortunately, The Edukators were one step ahead of him, and had long left their residences, going on a trip in exile.

Hardenberg's 'relapse' is a reminder that what we do and think are often shaped by our environment and what others think. It is very difficult to go against the flow and most people don't succeed. The Edukators left the note "Some people never change" in their residence before they left. In an interesting parallel, while Hardenburg was having his moral crisis, one of The Edukators had his fragile moment. The guilt from the kidnap had been too much, and he almost gave up the fight. Luckily he was rescued by friends who strongly believed in his ideals; if he were to fight it alone he would certainly have given up.

In a way the movie challenges not only the capitalist norm, but also the social and legal structures built to enforce capitalism. Is it right for the law to require a penniless person to payback debts incurred in an accident, to someone who is so rich he never needed the money? At the same time, why is it legal for a company to pay its workers close to nothing (e.g. 30 euros a year) when the company is making ridiculously huge profits? The movie frequently provokes questions about the concept of property (i.e., the legal ownership of material objects), most obviously by The Edukator's breaking into the lavish mansions, an act that 'breaks the law'. By simply rearranging and not stealing the objects (and one Edukator lecturing the other that it is immoral to steal), the movie cleverly tricks the audience into believing that it is a legal act, when it is clearly illegal to break into someone's house.

The ending of the movie was very cleverly done. For all I can tell, The Edukators have committed many acts worthy of prison terms under current legal frameworks, and the movie could easily have ended in a sour note. Instead, the ending became a moment of re-affirmation and even triumph for The Edukators. It was important for it to end that way, to inspire hope and to continue the fight. The movie started in a slightly chaotic fashion, with pieces of clues here and there, and the audience is slowly brought into this hugely criminal kidnapping act, where all parties involved start to reflect upon themselves, finally coming to a resolution, and even a surprisingly reassuring ending. The story seems unreal but the acting was convincing and, unlike Hollywood movies, the filming and the sets were so realistic the story felt real. At the same time, it provokes many thoughts and questions in the viewer's mind, which is what a good movie should do. It is certainly a movie worth seeing!

Sunday, 29 November 2009

10 Habits to Save the Environment (and Money) In Your Own Home.

I call these ‘habits’ because saving the environment is not a one-off endeavour, we need to be doing them everyday for it to work. These habits take a bit of effort to start with, but once it becomes your habit, they will become totally effortless.

Habit 1 - Switch Off All Standby Appliances In One Easy Flip
We all know that electrical appliances on standby consume ‘phantom power‘, the real hassle is going around the house to switch them off one by one. Instead, if you plug a number of these appliances into one extension cord which has a master switch, you can switch them off in one flip. Perfect candidates include your TV, cable box, DVD/music player combo, as they are usually co-located and can be easily grouped together. Its all about habit, once you’ve started flipping that switch a few times you will do it automatically every morning.

Habit 2 - Timer For Your Heater
Sometimes we forget to turn off our heater when we leave for work. The easiest solution is to install a timer to switch it off when you leave work, and switch it back on before you come home. That way, your house will stay nice and warm while conserving energy.

Habit 3 - Make Your Computer Energy Smart
Most computers come with an option to switch between balanced, power saver and high performance energy consumption modes. It lets you decide how much idle time should elapse before it switches off the monitor or puts the computer to sleep. If you are frequently leave your computer idle for long periods of time, set the time to 5 minutes or less.

Habit 4 - Wash Clothes With Cold Water
Most detergent on the market nowadays wash clothes in cold (~30C) water as clean as it does in hot/warm water. It takes a lot of energy to heat up the huge amount of water in the washing machine, so you will definitely save money washing cold. Of course, make sure you don’t wash just one or two pieces of clothing each time.

Habit 5 - Paperless Bills, Paperless Home
Most paper bills are at least 2 pages long, and if you have phone, mobile phone, electricity, gas, cable/internet, mortgage, and credit card bills, and bank account statements mailed each month, that’s 16 sheets of paper a month (plus the envelopes and stamps), 192 sheets a year. A city of 1 million households wastes 192 million sheets of paper a year! Most companies offer paperless billing options, and often give you financial incentives to enrol. Once enrolled, you will see a lot less paper stacked up, and you will receive the bill much quicker by email (you will also not be subject to possible postal service strikes).

You need a good system to make sure you don’t just ‘read and forget’ the bill email. If you will forget to pay it without seeing the bill, pay it the moment you receive the bill email, or enrol in direct debit. If you don’t pay it immediately, either mark the email ‘Unread’, or setup some monthly reminder in your mobile phone to pay the bills.

Note, however, that at times you will need a utility bill as proof of address. Switch all your bills to paperless, but leave the statement of one bank account as paper bill, as it will serve as both proof of address and of income. You will normally receive the paperless bill as an electronic PDF file, just remember to save it to your computer or to your email account, in case you need to print it out later. Back up your files regularly to one of those finger size USB drives, their advantage being rewritable, unlike CDs or DVDs.

Habit 6 - Reuse Receipts
You often cannot avoid getting receipts for grocery shopping or restaurants, but you can reuse the back of these receipts as notes instead of buying post-its, or at least recycle them. However, make sure you don’t give receipts that have credit card numbers to other people.

Habit 7 - Read Newspapers And Magazines Online
Most newspapers and magazines offer online subscription, and most of them are cheaper than the mail delivery option. A lot of people prefer reading on physical paper, but if you don‘t mind, going online can massively save the forests. These publications have lots of pages, and although most newspapers are printed on recycled paper, the process of recycling paper itself consumes energy and is therefore bad for environment.

Habit 8 - Recycle ALL Containers, Or Everything!
If you look at your trash, it consists mostly of containers you get from various places. Most people recycle, but only things that can be recycled without extra processing, e.g., paper and empty bottles. Items like plastic meat containers, used detergent/shampoo bottles, food cans, juice cartons, glass containers for sauces, and pizza boxes are often simply thrown away. Just a little extra effort to rinse them (takes at most 1 minute) will make recyclable. You will also be creating much less trash. In general, any type of container you get from the grocery store is recyclable with a little effort, and should not end up as trash. Only items like used tissue paper or food residues should end up as trash.

Habit 9 - Buy Just Enough Groceries, And Consume All Before Buying Again
Lets face it - we’ve all had food that turned bad in the fridge, because we bought too much. With proper planning, we should know how much food we will consume in the coming week or days. Not only are we wasting food and money, the more food there is in your fridge, the more energy it takes to keep them cool. Make sure you only buy groceries you will consume before its expiry date.

Habit 10 - Use Reusable Bag For Grocery Shopping, Or Use Plastic Bags As Trash Bags
I don’t think it’s a sin to get a plastic bag from the grocery store, as long as you will reuse ALL of them as trash bags, because then you don’t need to buy trash bags. However, make sure you don’t get too many plastic bags, and you can do that by buying only the groceries you need, and by packing more into one plastic bag. Say if you need 2 trash bags this week, then get 2 plastic bags, and put the rest of your groceries into a reusable shopping bag. In fact, if you are recycling all the containers from the grocery store, you really should not need more than 2 or 3 plastic bags for trash a week.