A few years ago, I found a video by podcaster Lex Friedman where he demonstrates that it's possible to make 2+2 equal five in Java using some tricks.
import java.lang.reflect.Field;
public class Main {
public static void main(String[] args) throws Exception {
Class cache = Integer.class.getDeclaredClasses()[0];
Field c = cache.getDeclaredField("cache");
c.setAccessible(true);
Integer[] array = (Integer[]) c.get(cache);
array[132] = array[133];
System.out.printf("%d",2 + 2);
}
}
Out of curiosity, I decided to run the code available in the video links and encountered the following error:
Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make field static final java.lang.Integer[] java.lang.Integer$IntegerCache.cache accessible: module java.base does not "opens java.lang" to unnamed module @8efb846
at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:391)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:367)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:315)
at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:183)
at java.base/java.lang.reflect.Field.setAccessible(Field.java:177)
at Old2Plus2.main(Old2Plus2.java:7)
I realized that, for the newer versions of Java, this hack was no longer possible. Therefore, in this article, I will demonstrate how to perform this trick for Java 21.
The error message says that the java.base module is not open. This means that it is not possible to use reflection from the Main class created for this example. If you are not very familiar with modules, I recommend refreshing your memory.
In other words, in Java 21, it's harder to perform this kind of hack with the language. Fortunately, there is a class that allows us to neglect the module system: the sun.misc.Unsafe. This class is used to perform low-level operations and is not recommended for the everyday use of ordinary programmers.
Thus, the new version of the code that makes 2+2 = 5 would look like this:
import java.lang.reflect.Field;
public class New2Plus2 {
public static void main(String[] args) throws Exception {
Class usf = Class.forName("sun.misc.Unsafe");//pega o objeto que representa a classe Unsafe
Field unsafeField = usf.getDeclaredField("theUnsafe");//pega o campo theUnsafe da classe Unsafe
unsafeField.setAccessible(true);//define o campo theUnsafe como público
sun.misc.Unsafe unsafe = (sun.misc.Unsafe)unsafeField.get(null);//pega o valor do campo theUnsafe, como ele é static é passado o parâmetro null
Class<?> clazz = Class.forName("java.lang.Integer$IntegerCache");// pega o objeto que representa a classe IntegerCache
Field field = clazz.getDeclaredField("cache");//pega o campo cache da classe IntegerCache
Integer[] cache = (Integer[])unsafe.getObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field));//utiliza a classe Unsafe para pegar o cache de Integer
cache[132] = cache[133];// troca o valor 4 pelo 5
System.out.printf("2+2 = %d",2 + 2);
}
}
Running the code above, you will see that the result of the addition will be 5. Obviously, I do not recommend using this code in production if you want to maintain your sanity and your job.
References:
https://github.com/joao9aulo/2plus2equals5
https://javax0.wordpress.com/2017/05/03/hacking-the-integercache-in-java-9/
https://www.youtube.com/watch?v=amXXYgu0eFY
https://www.oracle.com/br/corporate/features/understanding-java-9-modules.html
Top comments (0)