Java、Python都采取了常量实例池优化的技术,也就是预先生成-128~127之间的所有常量对象,每次创建这个范围内的对象时直接返回其引用即可。在一般的程序中,这个范围内的常量使用很频繁,因此,这个常量池可以取得非常好的效果。

然而,Java、Python都会允许程序员做一些很Hacker的事情,例如,利用常量池优化使得2+2=5

代码实现

Java的实现

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);
    }
}

对于这段代码的解释是这样的:

You need to change it even deeper than you can typically access. Note that this is designed for Java 6 with no funky parameters passed in on the JVM that would otherwise change the IntegerCache.

Deep within the Integer class is a Flyweight of Integers. This is an array of Integers from −128 to +127. cache[132] is the spot where 4 would normally be. Set it to 5.

Since you’re already using reflection, you could easily make this independent of the cache size (which does depend on runtime flags after all): Field f = Integer.class.getDeclaredField(“value”); f.setAccessible(true); f.set(4, 5) Could be made even more reliable by just grabbing the first non-static field - any reasonable implementation will only have a single field after all.

Python的实现

>>> patch = '\x312\x2D7'
>>> import ctypes;ctypes.c_int8.from_address(id(len(patch))+8).value=eval(patch)
>>> 2 + 2
5

这也是通过使用ctypes去改变运行时(Runtime)的常量池。

Like Java, CPython uses the same memory location for any copy of the first few small integers (0-255 if memory serves). This goes in and directly edits that memory location via ctypes. patch is just an obfuscated “12-7”, a string with len 4, which eval’s to 5.

C的实现

除了考虑改变常量池来改变引用的结果以外,在C/C++这一类较为底层的语言中还可以根据构造特定的数据结构来实现这一点:

int main() {
    char __func_version__[] = "5";  // For source control
    char b[]="2", a=2;
    printf("%d + %s = %s\n", a, b, a+b);
    return 0;
}

Doesn’t work with optimization.

参考

文中所有代码都经过了测试,代码和解释来源于http://codegolf.stackexchange.com/questions/28786/write-a-program-that-makes-2-2-5

  1. write-a-program-that-makes-2-2-5