A little lesson learned from Java

A post about good books, language design and JIT compilation, in which one bug turns into another and than back…

Recently I started looking through an excellent book “Java™ Puzzlers”, where Joshua Bloch and Neal Gafter provide a list of Java’s “Traps, Pitfalls, and Corner Cases”, i.e. programs that make you think they do what they really don’t. My idea is to see how many of the puzzlers are ruled out or fixed by Kotlin. I’ve looked through the first 24 items, and 15 of them are fixed in Kotlin, which is over 60%.

Some of the puzzlers can’t be fixed without severe implications on compatibility with the rest of the world. For example, most of the tricky things about IEEE-745 floating-point numbers. But some other ones, though not fixed in Kotlin yet, may be fixed. One particular example is Puzzler 26 “In the Loop”:

/**
 * Bloch, Joshua; Gafter, Neal (2005-06-24). 
 * Java™ Puzzlers: Traps, Pitfalls, and Corner Cases (p. 57). 
 * Pearson Education (USA). Kindle Edition.
 */
public class InTheLoop {
    public static final int END = Integer.MAX_VALUE;
    public static final int START = END - 100;

    public static void main(String[] args) {
        int count = 0;
        for (int i = START; i <= END; i++)
            count++;
        System.out.println(count);
    }
}

Don’t read further until you figure what this program prints :)


This program prints nothing and simply loops forever, because variable ‘i’ is of type int, and ANY int is less or equal than Integer.MAX_INT.

Now, if I write this in Kotlin:

val end = Integer.MAX_VALUE
val start = end - 100
var count = 0
for (i in start..end)
  count++
println(count)

It does NOT loop. And prints “101″, which is the size of the range of iteration…

This is the point where you think: “Didn’t he say that this puzzler is not yet fixed by Kotlin?” Yes, I did.

This Kotlin program SHOULD loop forever. And it does not. Sigh. I have already opened the “New issue” dialog in our tracker when I got too curious and looked at the code our compiler emits. You know what? I found nothing bad there. Written in Java (I am your honest decompiler today), it would look like this:

    int end = Integer.MAX_VALUE;
    int start = end - 100;
    int count = 0;
    for (int i = start; i <= end; i++)
       count++;
    System.out.println("count = " + count);

And this TERMINATES and prints “101″. That’s where I really got puzzled.

After some experimentation, I discovered that making variable ‘end’ final makes the program loop forever. “It must be JIT, ” — I though, and was right: when run with “java -Xint”, this code loops forever, and so does the Kotlin code.

How come? Well, I run a 64-bit JVM. Most likely, JIT optimizer makes the loop variable 64-bit, because registers are this big, or something like this, and it does not overflow, but just becomes Integer.MAX_VALUE + 1.

Sigh. I closed our “New issue” dialog, and opened the HotSpot’s one… (Some technicalities prevent me from finishing the reporting process right now, but I will do it on Monday).

Now, what lesson can we learn from this? I don’t think I can learn much from hitting a JIT bug. Bugs happen — that’s the lesson here, I think.

But what about the initial puzzler? I teach Pascal at a high school, and one thing I really like about this language is that a for loop ALWAYS TERMINATES there. We cannot have the same in Kotlin, because in general for uses an iterator that may have arbitrary logic in it. But what we can do is guarantee that iteration over a range of numbers always terminates.

BTW, if a range was just a list of numbers, the loops would terminate, right? So it IS a bug in the Kotlin compiler, after all. :)

About Andrey Breslav

Andrey is the lead language designer working on Project Kotlin at JetBrains. He also works on making the Java language better, serving as a Java Community Process expert in a group for JSR-335 ("Project Lambda"), and occasionally speak at software conferences such as Devoxx or JavaOne.
This entry was posted in General and tagged . Bookmark the permalink.

2 Responses to A little lesson learned from Java

  1. Jan Kotek says:

    Scala does not have this problem, in this case it creates bunch of new instances: IntRange, Iterator, Closure… Which sucks when doing low level stuff. It is nice to see that Kotlin took hard road and implemented it correctly from beginning.

  2. Justin Malcolm says:

    @Jan – Why would this suck for doing low level stuff? I was surprised at the Java code the Kotlin generated and think that Scala is doing it better.

    I have written a couple of toyish compilers for the CLR (.NET/Mono) and I would have used an iterator. On the CLR, “start..end” would be great short-hand for “Enumerable.Range(start, end)”:

    http://msdn.microsoft.com/en-us/library/system.linq.enumerable.range.aspx

    This approach has a few strengths:
    - no overflows (as per this post)
    - potential lazy evaluation
    - ability to pass the range as a unit (eg. parameter to a function)
    - ability to chain with other expressions (fluent APIs)

    In LINQ for example, using a second expression to select a subset from this range could reduce the processing required or even result in a more efficient query to a database later on. The literal translation to an index-based for loop seems quite primitive in comparison.

    I hope that bringing up the CLR does not distract anybody. As C# has many of the features that Kotlin is proposing for the JVM it seems like a natural environment to contrast. Kotlin is looking really great and I am excited to see a compiler. I would love to lose the colons and put the types before the identifiers but hey, we cannot all agree about everything.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>