1 2 import java.security.*; 3 import java.lang.reflect.*; 4 import java.util.*; 5 6 public class Test 7 { 8 public static void main(String[] args) throws Exception 9 { 10 AccessController.doPrivileged( new PrivilegedAction<Object>(){ public Object run(){try { 11 Field field = Class.forName("java.lang.Integer$IntegerCache").getDeclaredFields()[0]; 12 field.setAccessible(true); 13 14 Integer[] cache = (Integer[])field.get(null); 15 16 cache[130] = 3; 17 18 Integer foo = 2; 19 20 System.out.println(foo + 2); 21 22 return null;} catch(Exception e) { throw new RuntimeException(e); } } }); 23 } 24 25 26 } 27
Integer maintains an internal cache of Integer objects for values from -128 to 127. This is stored on the inner class IntegerClass (this is what the Class.forName("java.lang.Integer$IntegerCache") line fetches) as an array. When you do Integer.valueOf(int) it will fetch an object from this cache rather than construct a new one if it is within the appropriate range. Because the cache starts at -128, 130 is the index of the entry for 2.
Autoboxing then takes care of the rest. When you declare Integer foo = 2 this gets autoboxed - i.e. converted to Integer.valueOf(2), which is now 3.
When we do 2 + 2 the Integer object is unboxed to an int rather than the other way round, so foo + 2 becomes foo.intValue() + 2, which is 3 + 2.
The rest of the code is just the neccessary hackery in order to beat the Java permissions system into submission.
I didn't come up with this, but unfortunately I've lost the original article where I found this hack in. The above is my attempt at recreating it.
You need to create an account or log in to post comments to this site.