jdk9+版本的bug-阿里云开发者社区

开发者社区> 杨俊明> 正文

jdk9+版本的bug

简介: 今天从jvm大神"你假笨"的公众号上,看到一个jdk 9+版本的编译bug,记录一下: public class JavacEvalBug{ private static String[] array = {""}; static int test(){ System.
+关注继续查看

今天从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;
    }
}

就正常了

 

2018-07-28 更新,在jdk 10.0.2版本上,该bug已修复

作者:菩提树下的杨过
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
冬季实战训练营-第一期-学习报告
冬季实战训练营-第一期-学习报告
11 0
Caffeine缓存 最快缓存 内存缓存
Caffeine是一个进程内部缓存框架 最快缓存 内存缓存
16 0
【mockito】单元测试之mockito简单使用
项目使用的是springmvc+mybatis 开发; mock包为 mockito-all;虽然也引用了powermock,但截至目前,还未使用到;如果使用到后续再补相关笔记。
14 0
flutter项目如何打包(android)
打包前要做的 1.更换图标 andriod–》app–app–》src—》main-》Java----》res–》minpmap
11 0
学习报告 冬季实战营第一期:从零到一上手玩转云服务器
冬季实战营第一期:从零到一上手玩转云服务器-本期学习报告
14 0
云起第一期学习体会(报告)
云起第一期学习体会(报告)
22 0
云起实验室学习报告之LAMP搭建
云起实验室学习报告之LAMP搭建
14 0
flutter开发之必须掌握的dart知识点:list,set,map
要说,List在我的开发使用中,确实是最为频繁的了,那么如何使用list,也就成了一个问题,list提供的方法又有哪些 这些都是需要掌握理解的。 首先第一个, 对于固定长度的list,如何删除添加元素呢
7 0
+关注
杨俊明
菩提树下的杨过 http://yjmyzz.cnblogs.com/
1105
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载