Home of The JavaSpecialists' Newsletter

102Mangling Integers

Posted: 2005-01-31Category: LanguageJava Version: 1.5+Dr. Heinz M. Kabutz
 

Abstract: 

 

Welcome to the 102nd edition of The Java(tm) Specialists' Newsletter. I am in Johannesburg this week, presenting my first Java 5 Delta Course - Letting the Tiger out of the cage. This course is for professional Java programmers, who have already managed the nuances of JDK 1.4. Java Tiger has many pitfalls, and the syntax is at times, well, strange. Today we learned what this means:

    public static <T extends Comparable<? super T>> void sort(List<T> list)
  

A few words about Johannesburg. It is a young city, and bustling with activity. I arrived much too early this morning since the chauffeur service overestimated the traffic, and even at 6:30am, my customer's building was a hive of activity. It is also a dangerous place to be, so the chauffeur is not a luxury. For example, you should not walk down the road carrying a notebook, a wallet or even a mobile phone. You could be relieved of your burdens! On the positive side, the people here are very friendly and welcoming.

NEW: Refactoring to Java 8 Lambdas and Streams Workshop Are you currently using Java 6 or 7 and would like to see how Java 8 can improve your code base? Are you tired of courses that teach you a whole bunch of techniques that you cannot apply in your world? Check out our one day intensive Refactoring to Java 8 Lambdas and Streams Workshop.

Mangling Integers

When I was a kid, I enjoyed fiddling with computers, so my aunt Elke gave me a sign that read: "To err is human, to really louse things up requires a computer."

I believe that Java misses a feature, that would make it a lot safer. It should be possible to make the contents of arrays immutable. A final handle does not help at all, since the elements of the array can still be changed.

In Issue 14, I gave an example of how it was possible to have ("hi there".equals("cheers !")) == true. This could easily have been made impossible by adding a language feature to prevent users from modifying the contents of an array.

However, this gets much worse with auto-boxing. Integer, Long, Short and Byte have now got a new function called Integer valueOf(int). This follows the Flyweight Pattern, similar to String objects, but only caches Integer objects from -128 to 127, inclusive. It either returns an Integer object from the cache, or creates a new object.

Nice function this valueOf(int), but I wondered what would happen if that cache were to get corrupted? The interesting part about this function is that it is called by all the autoboxing code generated by the compiler. So if it returned incorrect values, the entire number system of Java would be corrupted ... for example ...

public class Arithmetic {
  public static void main(String[] args) {
    CoolClass.makeExcellentCuppaCoffee(); // hmmm - we all need that!
    int upto = 1000;

    // using Integer
    Integer total1 = 0;
    for(int i=1; i<=upto; i++) {
      total1 += i;
    }
    System.out.println("total1 = " + total1);

    // using int
    int total2 = 0;
    for(int i=1; i<=upto; i++) {
      total2 += i;
    }
    System.out.println("total2 = " + total2);

    System.out.println("Should be " + ((upto+1)*upto)/2);
  }
}
  

The output on my machine is:

  Hmmm, the first cuppa in the morning is the best!
  total1 = 492372
  total2 = 500500
  Should be 500500
  

I have not shown you the fantastic coffee-making method in the CoolClass. Here goes:

import java.lang.reflect.Field;

public class CoolClass {
  static {
    try {
      Class[] classes = Integer.class.getDeclaredClasses();
      for (Class clazz : classes) {
        if (clazz.getName().endsWith("IntegerCache")) {
          Field cacheField = clazz.getDeclaredField("cache");
          cacheField.setAccessible(true);
          Integer[] cache = (Integer[]) cacheField.get(null);
          for (int i = 0; i < cache.length; i++) {
            cache[i] = new Integer(0);
          }
        }
      }
    } catch (Throwable e) {
      // we silently pretend we didn't want to destroy Java...
    }
  }

  public static void makeExcellentCuppaCoffee() {
    // let's pretend this function does something amazing,
    // like make a good cup of coffee
    System.out.println("Hmmm, the first cuppa in the morning is the best!");
  }
}
  

Of course, this is not Java's fault, but of lax security procedures. First off, you should always run your programs with a security manager, even if you do not think you need it. And of course, any libraries that you use should be checked for malicious code.

It is a pity though that you cannot turn autoboxing off, and that you are not able to easily find all places that use autoboxing, just to know what code to verify. Who knows, maybe in future we will have a -Xlint option to show us where autoboxing is used.

Kind regards

Heinz

 

Related Articles

Browse the Newsletter Archive

About the Author

demo

Java Champion, author of the Javaspecialists Newsletter, conference speaking regular... About Heinz

Java Training

We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.

Java Consulting

Nobody ever wants to call a Java performance consultant, but with first-hand experience repairing and improving commercial Java applications - JavaSpecialists are a good place to start...

Threading Emergency?

If your system is down, we will review it for 15 minutes and give you our findings for just 1 € without any obligation.