运行和调试Java、Eclipse程序的不同行为
我有以下代码(暂时不考虑其适当性):运行和调试Java、Eclipse程序的不同行为,java,eclipse,debugging,Java,Eclipse,Debugging,我有以下代码(暂时不考虑其适当性): Class cacheClass=Class.forName(“java.lang.Integer$IntegerCache”); 字段cacheField=cacheClass.getDeclaredField(“缓存”); cacheField.setAccessible(true); 字段修饰符字段=Field.class.getDeclaredField(“修饰符”); modifiersField.setAccessible(true); setI
Class cacheClass=Class.forName(“java.lang.Integer$IntegerCache”);
字段cacheField=cacheClass.getDeclaredField(“缓存”);
cacheField.setAccessible(true);
字段修饰符字段=Field.class.getDeclaredField(“修饰符”);
modifiersField.setAccessible(true);
setInt(cacheField,cacheField.getModifiers()&~Modifier.FINAL);
整数betterCache[]=新整数[255];
for(int i=0;i
我希望第二个println
打印20,因为我用20替换了缓存的整数。当我在Eclipse中调试程序时,它会按照我的预期执行,它从缓存中获取值并打印20,而在这两种情况下,当我从IDE或通过调用java
运行它时,它都会打印10。如何解释这种行为
UPD:
如果用1.8javac编译,它就是这样工作的。如果使用1.6版本编译,它将打印10和20。编辑
我完全错了
在我看来,您肯定是在玩火,这是针对竞争条件(Java8中的不安全线程)。如果您选中此项:
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);
}
Class cacheClass=Class.forName(“java.lang.Integer$IntegerCache”);
字段cacheField=cacheClass.getDeclaredField(“缓存”);
cacheField.setAccessible(true);
字段修饰符字段=Field.class.getDeclaredField(“修饰符”);
modifiersField.setAccessible(true);
setInt(cacheField,cacheField.getModifiers()&~Modifier.FINAL);
Integer firstCache[]=(Integer[])cacheField.get(null);
整数betterCache[]=新整数[255];
for(int i=0;i
您将看到Java烧录。这肯定是由即时编译器造成的。您应该将-XX:+printcomilation添加到JVM选项中,如果您进行迭代,它也会更加可见
System.out.println((Integer) 10);
很多次。
你会注意到
java.lang.Integer::valueOf (32 bytes)
及
影响结果。两种情况下都打印10。那么它为什么要打印20呢?在第二种情况下,它是一个对象,所以它调用Integer.valueOf
方法来打印它,在该方法中,它从缓存中获取值,我刚才用一个填充了20的数组来替换。有趣的问题(尽管你正在玩火)。你试过maven或java-jar吗?我认为一些IDE的缓存可能会导致这个问题。你可能会在有趣的网站上找到答案,因为你正在处理像那个问题一样的最终问题。谢谢你的回答。我仍然不明白为什么将20
(基本上调用valueOf
)更改为创建新的值会改变这种行为。它似乎不是在编译时计算的(虽然字节码的内容对我来说非常不清楚),因为在两个版本的字节码中,第二个版本的println
有相同的语句bipush 10
。请参阅我的question@cliffroot我不知道,但我可以看到在调试模式下使用断点与不使用断点的区别。我开始考虑竞争条件。Art Taylor:“我有两条新规则。1)如果你的应用程序运行缓慢,请添加缓存。2)如果你的应用程序有缺陷,请删除缓存。”哈哈,你知道有什么好笑的。我试了100圈。有时它写下20作为第一个值,然后全部写下10,有时它不(全部10)@cliffroot当我尝试1000000时,它显示158,WTF!你介意解释一下-xx:+printcomployment
的输出吗。。。我经历过,但真的不太明白。。。
java.lang.Integer::valueOf (32 bytes)
java.nio.ByteBuffer::arrayOffset (35 bytes)