由Just In Time中的错误导致的ClassCastException?

鉴于这段代码:

public static void writeFile(File file,List buffer)throws IOException{
    File fic = new File(file.getCanonicalPath());
    cat.debug("writing file : "+fic.getAbsolutePath());
    FileOutputStream out = new FileOutputStream(fic);
    PrintStream ps = new PrintStream(out);
    for(int i=0;i<buffer.size();i++){
        ps.println(buffer.get(i));
    }
    ps.flush();
    ps.close();
    out.close();
}

(关于如何安全关闭流,请不要提供任何建议,这是遗留代码,新版本使用try / finally)

我在“ps.println(buffer.get(i))”处得到一个ClassCastException异常“

这个方法被调用几次(比如说5次),只有一个列表中填充了字符串,然后调用一个用String和其他对象(比如ErrorObject)填充的列表。在我们到达第一个ErrorObject的时候,我们得到了ClassCastException 。

com.mycompany.ErrorObject incompatible with java.lang.String

此问题发生在生产环境中,但无法在Dev环境中重现:Prod:jvm = IBM J9 VM 2.4 J2RE 1.6.0 IBM J9 2.4 AIX ppc-32 jvmap3260-20081105_25433(已启用JIT,已启用AOT)Dev:WinXP,JDK 1.6 .0_16

这段代码可能会失败吗?

它最近被修补了,我担心生产团队没有正确升级jar,但是我的老板已经检查过修补程序是否正确应用...

我想知道,即时编译器是否可以将ps.println“连线”到ps.println(String)而不是ps.println(Object)。 这可以解释这样的问题,但我不知道这是否可能。

任何意见欢迎,提前谢谢

编辑:我被问到完整的堆栈跟踪,所以这里是:

java.lang.ClassCastException: com.mycompany.util.ErrorObject incompatible with java.lang.String
    at com.mycompany.util.FileUtils.writeFile(FileUtils.java:91)
    at com.mycompany.util.FileUtils.writeFile(FileUtils.java:50)
    at com.mycompany.itools.task.DBCompareInits.doDBTask(DBCompareInits.java:959)
    at com.mycompany.itools.task.DBTask.doTask(DBTask.java:115)
    at com.mycompany.itools.task.TaskGroup.startGroup(TaskGroup.java:115)
    at com.mycompany.runner.Runner.main(Runner.java:209)

编辑2:javap -c

   65:  invokeinterface #20,  1; //InterfaceMethod java/util/List.size:()I
   70:  if_icmpge   92
   73:  aload   4
   75:  aload_1
   76:  iload   5
   78:  invokeinterface #21,  2; //InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
   83:  invokevirtual   #31; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
   86:  iinc    5, 1
   89:  goto    62
   92:  aload   4
   94:  invokevirtual   #32; //Method java/io/PrintStream.flush:()V
   97:  aload   4
   99:  invokevirtual   #33; //Method java/io/PrintStream.close:()V
   102: aload_3
   103: invokevirtual   #28; //Method java/io/FileOutputStream.close:()V

我想知道,即时编译器是否可以将ps.println“连线”到ps.println(String)而不是ps.println(Object)。 这可以解释这样的问题,但我不知道这是否可能。

这不可能。 或者至少不要除非有字节码编译器或JIT编译器错误。 如果你有无可辩驳的证据证明这是事实,你应该只怪责编译器错误。

但是,我要检查的第一件事是,正在执行的代码是从您正在查看的源代码真正编译的。 确认这一点的一种方法是从源代码重新编译,然后比较在类的相应副本上运行javap的结果。 查看字节码也会告诉你字节码编译器要使用哪个println重载。

编辑 - javap输出清楚地表明该字节码的版本应该调用println(Object) ,并且没有checkcast操作码在视线中。 调用错误方法并自发插入代码来进行类推的JIT编译器错误听起来越来越难以理解。


在ErrorObject类中声明toString()方法并将其转换为字符串,并向println()调用添加+“”。 像pintln(errorObjList +“”);

链接地址: http://www.djcxy.com/p/85045.html

上一篇: ClassCastException caused by bug in Just In Time?

下一篇: What is the macro for std::string/std::wstring in vc++?