jdk9+版本的bug
Posted 菩提树下的杨过
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jdk9+版本的bug相关的知识,希望对你有一定的参考价值。
今天从jvm大神"你假笨"的公众号上,看到一个jdk 9+版本的编译bug,记录一下:
public class JavacEvalBug{ private static String[] array = {""}; static int test(){ System.out.println("evaluated!"); return 0; } public static void main(String[] args) { //相当于int index=test(); array[index] +="a"; array[test()] += "a"; } }
test()方法里输出了一个固定字符串,上面这段代码,如果是在jdk8版本里,执行后,只会输出:evaluated! 一次(这符合预期,因为test()只调用了1次)
但如果把jdk升级到jdk9或10,再次编译运行,evaluated!就会输出2次,即test()方法会多执行了1次,如果test()方法是复杂的业务逻辑,比如创建订单/库存扣减之类,这就成大问题了。
原因在于jdk8与jdk9+的编译机制不同,javap -verbose JavacEvalBug 使用这个命令,可以看到编译细节:
public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=5, locals=1, args_size=1 0: new #5 // class java/lang/StringBuilder 3: dup 4: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V 7: getstatic #7 // Field array:[Ljava/lang/String; 10: invokestatic #8 // Method test:()I 13: dup2_x1 14: aaload 15: invokevirtual #9 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 18: iconst_1 19: invokevirtual #10 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 22: invokevirtual #11 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 25: aastore 26: return
jdk8上,从第10行看,只调用了1次,如果切换到jdk9+,则会变成:
public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=4, locals=1, args_size=1 0: getstatic #5 // Field array:[Ljava/lang/String; 3: invokestatic #6 // Method test:()I 6: getstatic #5 // Field array:[Ljava/lang/String; 9: invokestatic #6 // Method test:()I 12: aaload 13: invokedynamic #7, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String; 18: aastore 19: return LineNumberTable:
明显可以看到Method test:()I 调用了2次。具体详情分析,大神说是以后会详细分析,大概是字符串拼写的方式,jdk9以后做了变化。如果把string数组换成其它类型比如int
public class JavacEvalBug{ private static int[] array = {0}; static int test(){ System.out.println("evaluated!"); return 0; } public static void main(String[] args) { //相当于int index=test(); array[index] +=1; array[test()] += 1; } }
就正常了
以上是关于jdk9+版本的bug的主要内容,如果未能解决你的问题,请参考以下文章