Различное поведение, выполняемое и отлаживающее программу Java, Eclipse
У меня есть этот код (отложите в сторону его целесообразность на данный момент):
Class<?> cacheClass = Class.forName("java.lang.Integer$IntegerCache");
Field cacheField = cacheClass.getDeclaredField("cache");
cacheField.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(cacheField, cacheField.getModifiers() & ~Modifier.FINAL);
Integer betterCache[] = new Integer[255];
for (int i = 0; i < betterCache.length; i++) {
betterCache[i] = 20;
}
cacheField.set(null, betterCache);
System.out.println(10);
System.out.println((Integer) 10);
Я ожидаю, что второй println
будет печатать 20, поскольку я заменил кешированный Integers
на 20. Когда я отлаживаю программу в Eclipse, она делает то, что я ожидаю, она получает значение из кеша и печатает 20, тогда как она печатает 10 в обоих случаях, когда я просто запускаю его либо из IDE, либо путем вызова java
. Как объяснить это поведение?
UPD:
Он работает таким образом, если скомпилирован с 1.8 javac. Он печатает 10 и 20, если скомпилирован с версией 1.6.
Ответы
Ответ 1
Это определенно вызвано компилятором Just in Time. Вы должны добавить -XX: + PrintCompilation в JVM-параметры, это также более заметно, если вы выполните итерацию
System.out.println((Integer) 10);
много раз.
Вы заметите, что компиляция
java.lang.Integer::valueOf (32 bytes)
и
java.nio.ByteBuffer::arrayOffset (35 bytes)
влияет на результат.
Ответ 2
ИЗМЕНИТЬ
Я был совершенно не прав
Определенно, вы играете с огнем, с моей точки зрения, это для условий гонки (небезопасная нить в java 8). Если вы проверите это:
Class<?> cacheClass = Class.forName("java.lang.Integer$IntegerCache");
Field cacheField = cacheClass.getDeclaredField("cache");
cacheField.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(cacheField, cacheField.getModifiers() & ~Modifier.FINAL);
Integer firstCache[] = (Integer[])cacheField.get(null);
Integer betterCache[] = new Integer[255];
for (int i = 0; i < betterCache.length; i++) {
betterCache[i] = 20;
}
System.out.println(firstCache == betterCache);
cacheField.set(null, betterCache);
System.out.println(10);
for (int i = 0; i < 1000000; i++) {
System.out.println((Integer) 10);
}
Вы увидите ожог Java.