Running on Java 24-ea+21-2447 (Preview)
Home of The JavaSpecialists' Newsletter

102Mangling Integers

Author: Dr. Heinz M. KabutzDate: 2005-01-31Java Version: 5Category: Language
 

Abstract: To optimize autoboxing, Java caches boxed integers in the range -128 to 127. We examine what happens if this cache were to get corrupted.

 

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.

javaspecialists.teachable.com: Please visit our new self-study course catalog to see how you can upskill your Java knowledge.

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

 

Comments

We are always happy to receive comments from our readers. Feel free to send me a comment via email or discuss the newsletter in our JavaSpecialists Slack Channel (Get an invite here)

When you load these comments, you'll be connected to Disqus. Privacy Statement.

Related Articles

Browse the Newsletter Archive

About the Author

Heinz Kabutz Java Conference Speaker

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

Superpack '23

Superpack '23 Our entire Java Specialists Training in one huge bundle more...

Free Java Book

Dynamic Proxies in Java Book
Java Training

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

Java Consulting

We can help make your Java application run faster and trouble-shoot concurrency and performance bugs...