使用反射覆盖 2 + 2 = 5

Using reflection to override 2 + 2 = 5

请耐心等待,我知道这是一个奇怪的问题。

我刚刚偶然发现了 Java 的反射库,特别是来自 a video by Lex Fridman 的这段代码覆盖了 2 + 2 = 5:

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

我试图通过将其翻译成等效的 Scala 形式来了解它在做什么,但它没有编译为 Int.getClass.getDeclaredClasses returns 一个空数组:

import java.lang.reflect.Field

val cache: Class[_] = Int.getClass.getDeclaredClasses.head
// above line throws java.util.NoSuchElementException: next on empty iterator

val c: Field = cache.getDeclaredField("cache")
c.setAccessible(true)
val array = c.get(cache).asInstanceOf[Array[Int]]
array(132) = 5

println(2+2)

classgetClass 都不是 Integer 下的方法,当我尝试使用它时,所以我尝试使用 Int ;我的印象是 Scala 的 Int 只是 Java 的 Integer 的包装 - 不是这样吗?

我也试过:

为什么它在不使用 Scala 编译的 Java 中有效?我怎样才能在 Scala 中实现 2 + 2 = 5 的愚蠢目标?

如果勾选IntegerCache inner class inside Integer class。部分实现如下:

        high = h;

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

默认情况下 -128(低)和 127(高)之间的整数(可能被选中是因为这些是典型应用程序中最常用的整数)。缓存大小为 256(因此 - 和 + 值将保持在一起)

在你的应用程序中,你得到 Integer class 的“缓存”字段,它是从 -128 到 127 的值。但是在数组中它们保持在一起,所以值 0 索引实际上是 128(因为有首先是 -128 个值) + 0.

0 -> 128
1 -> 129
2 -> 130
3 -> 131
4 -> 132
5 -> 133

你的数组[132] = 数组[133];表达式使缓存中有 4 = 5。所以每当应用程序从缓存中调用4的索引时,都会返回整数5。

对于 Scala 部分,我没有使用 Scala 的经验,但它使用 JVM 不只是为了将自身编译为字节码吗?所以也许 Scala 不使用 JDK 并且它的 Int 实现是不同的,这就是你得到错误的原因(似乎可以根据@Dmytro Mitin 的回答使用 JDK 中的整数)

java.lang.Integer 应该代替 scala.Int.

Int.getClassgetClass 在 class Int 的伴随对象上调用的,这是错误的。

将代码翻译成 Scala 是

val cache = classOf[Integer].getDeclaredClasses.apply(0)
val c = cache.getDeclaredField("cache")
c.setAccessible(true)
val array = c.get(cache).asInstanceOf[Array[Integer]]
array(132) = array(133)
println(2 + 2) // 5

I was under the impression that Scala's Int is just a wrapper around Java's Integer - is this not the case?

不是。通常scala.Int对应Javaint.

https://github.com/scala/scala/blob/2.13.x/src/library/scala/Int.scala