Tuesday, September 29, 2009

Intern Isn't Forever ... And Maybe Never Was

Today I managed to hit myself over the head with a cluebat, proof that there's always something to learn and that you should never accept dogma. In this case, the dogma was that interned strings never get garbage-collected. Like all good dogma, it combined a few facts with a leap of faith, and was plausible enough that I never challenged it.

The facts first (actually, only one fact): interned strings are stored in the same pool as literal strings. This is explicitly stated in the JavaDoc for String.intern(), and can be demonstrated with the following code:

String a = "Are we having fun yet?";
String b = new String(a);
System.out.println(a == b);

String c = b.intern();
System.out.println(a == c);

And now the leap of faith: the JVM doesn't clean up the constant pool. Seems plausible: after all, two literal strings are guaranteed to be the same. And intern() is a native method, so it must be doing something tricky behind the scenes. And everybody else says you'll cause bugs if you intern too many strings, so …

A skeptic might ask “how can you tell that two string literals aren't the same if you don't have references to both?” I even said as much when I wrote about canonicalizing maps (an article that got some edits today). Once all references to a string go out of scope (including any references within a class definition), then there's no need to keep that string in the pool. And the JVM doesn't — at least, the Sun JVM doesn't.

This particular cluebat entered the picture because I'm currently writing an article on out-of-memory exceptions, and wanted a program to demonstrate permgen failures. So I wrote a loop that interned big, random-content strings … and nothing happened. I killed the program after I finally realized that it wasn't going to die on its own.

But the dogma must have some basis in fact, right? It happens that I have a machine with Sun JVMs from version 1.2 on up. So I ran my test program on each revision, and while the -verbose:gc output changed, the result did not: all of these versions appear to clean up the string pool. Is it possible that a 1.1 release is the source of this dogma? Perhaps, and if someone still has one installed, here's the program:

public class InternExhaustion
{
    public static void main(String[] argv)
    throws Exception
    {
        while (true)
        {
            String str = generateRandomString(65536);
            str.intern();
        }
    }    
    
    private static String generateRandomString(int length)
    {
        char[] chars = new char[length];
        for (int ii = 0 ; ii < length ; ii++)
            chars[ii] = (char)(96 * Math.random() + ' ');
        return new String(chars);
    }
}

For myself, I have some edits to make. And a lump on the head to remind me to question dogma.

Thursday, September 24, 2009

Je vais m'amuser

If you're a native French speaker, you may be giggling to yourself at the title of this post. If, like me, you had two semesters of French in college, you may see nothing wrong — until your Parisian instructor starts giggling. “I will amuse myself.” The difference is idiom: in America, amusing oneself is harmlessly waiting for another; in France … well, it's still harmless, but that's not the point.

Programming idiomatically means understanding a language at a level deeper than its syntax. In Python, it means using list comprehensions rather than explicit iteration, or a generator rather than a physical list. In Java, it means using enum rather than constants. In any object-oriented language, it means “tell, don't ask.”

A hallmark of programmers who are new to a language is their lack of idiom. They write the new language as if it were the old, often bemoaning the loss of their familiar constructs (I'm no different: as I was learning Java I wished for C-style function pointers). There's an old saying that “You can write Fortran in any language.”

A danger of idioms is that they can turn into slang, used to add color rather than value, a way to signify membership in a clique. Duff's device is an extremely clever use of C's switch statement, and arguably a brilliant optimization (although I have trouble believing that the cycles saved from unrolling loops weren't immediately lost waiting for the IO register). But when used for copying memory, it loses all cleverness: replacing a CISC hardware instruction with discrete moves, or preventing a RISC compiler from applying its own optimizations.

More dangerous are the programmers who never spend enough time with a language to learn its idioms. They are the ones who code randomly: an ArrayList here, a LinkedList there, reading all rows from a database so that they can do a sum on the client. Exposure to different languages can be a great learning experience, as long as you learn enough to know when someone wants a little time alone.

Monday, September 14, 2009

Short Attention Span Theatre, or, What Happens When Your Page Becomes Delicious

Last week my article on Java reference objects managed to find its way to the “popular Java” page of delicious.com (and, within a day or two, drop off again). Normally, this article gets hit a dozen times a day, usually by people who are Googling for “how to fix out of memory errors.” During the week that it appeared on delicious.com (which was preceeded by a lot of tweeting), it was getting hit 150+ times a day — including 49 times in short order from one London-based ISP (which I assume was a proxy).

What was interesting to me, however, was that almost none of the people visiting this page went to any other page on the site — and of the ones that did, more went to the “food” section than to the “programming” section. And they tended to do so quickly: under a minute between initial page hit and moving on. I know that it takes longer than that to read about reference objects.

To an author, this should be a blow to the ego: is my writing so bad that people don't want to read more of it? It's like they picked up my book, read the dust jacket, and put it back down. But I refuse to accept that conclusion. For one thing, I have a strong ego. But more important, enough people bookmarked the page for it to appear as a popular link.

The real answer, I think, is that people in the software industry are very quick to jump on new ideas, but don't have a lot of follow-through. And why should they, when there's a plethora of well-known pundits saying they should explore as many new things as they can, and there's always a new popular link showing up on delicious.com?

The problem with this attitude is that exposure to a lot of ideas doesn't mean that any of them will stick. In fact, I'd say the opposite is true: if you don't take the time to examine an idea and see how it fits with your existing knowledge, you're not going to ever make use of it.