JetCracker

Life-time learner's blog

The Magic of 42

Hi there!

It’s been quite a long time since I posted here (more than one month). Honestly, I was really busy and there were some problems with the Internet in my dorm.

The month was full of events!

Firstly, I got a position of software engineer (intern) in NetCracker in department Solution Delivery. Secondly, we almost finished with the first release of Reshaka.Ru which is currently being tested. In addition, we moved to another room at the dormitory. I changed my roommates – now they all programmers and my friends too. Some time I will tell you more about all these events. But now let’s get down to business!

Hacking Java Integer class

Investigation

Consider the following code example:


public class Simple {
    public static void main(String[] args) {
        Integer a = 20;
        System.out.println("a = " + a);
    }
}

It is obvious that the code prints 20 in the output. Is it possible to make Java always print a particular number instead of  the value of  the variable “a”? This question is often asked at the interviews for position of a Java developer.

To answer that question let’s have a look at the implementation of the class java.lang.Integer.


public final class Integer extends Number implements Comparable {

   // code...

       /**
     * Cache to support the object identity semantics of <a class="zem_slink" title="Object type (object-oriented programming)" href="http://en.wikipedia.org/wiki/Object_type_%28object-oriented_programming%29" rel="wikipedia" target="_blank">autoboxing</a> for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the -XX:AutoBoxCacheMax= option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */

    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low));
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);
        }

        private IntegerCache() {}
    }

    /**
     * Returns an {@code Integer} instance representing the specified
     * {@code int} value.  If a new {@code Integer} instance is not
     * required, this method should generally be used in preference to
     * the constructor {@link #Integer(int)}, as this method is likely
     * to yield significantly better space and time performance by
     * caching frequently requested values.
     *
     * This method will always cache values in the range -128 to 127,
     * inclusive, and may cache other values outside of this range.
     *
     * @param  i an {@code int} value.
     * @return an {@code Integer} instance representing {@code i}.
     * @since  1.5
     */
    public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

}

Notice the inner class IntegerCache. According to Javadoc, it is used to speed up autoboxing of integer values between -128 and 127. Due to autoboxing mechanism the following code

Integer a = 20;

is automatically converted into

Integer a = Integer.valueOf(20);

The method Integer.valueOf(int value) returns the value from the predefined array which is stored inside Integer.IntegerCache class. Having changed this array, we would affect the returned result of the Integer.valueOf() method and hence affect the work of entire program.

Hacking the Integer

To alter the integer cache we can use the Java Reflection. Here is my implementation.

public class Main {

    static void setFieldValue(Field field, Object newValue)
            throws IllegalAccessException, IllegalArgumentException, NoSuchFieldException {
        field.setAccessible(true);

        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

        field.set(null, newValue);
    }

    static {
        try {
            Class ic = Class.forName("java.lang.Integer$IntegerCache");
            if (ic != null) {
                Field f = ic.getDeclaredField("cache");
                Integer ar[] = new Integer[1024];
                Arrays.fill(ar, 42);
                setFieldValue(f, ar);
            }
        } catch (Exception ex) {
        }
    }

    public static void main(String[] args) {
        Integer a = 20;
        System.out.println("a = " + a);
    }
}

The method setFieldValue is used for changing the value of a particular field of an object. The static block of code is executed the first (before main). It finds the class java.lang.Integer.IntegerCache and substitutes the array with a new one. And from now on this code always prints “42” instead of “20”.

I hope the topic wasn’t boring and useless. Have fun!

Advertisements

One response to “The Magic of 42

  1. Pingback: Spring 2012: Overall stats « JetCracker

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: