鉴于这段代码:
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
该问题在生产环境中出现,但在开发环境中无法重现: 产品:jvm=IBM J9 VM 2.4 J2RE 1.6.0 IBM J9 2.4 AIX ppc-32 jvmap3260-20081105_25433(启用 JIT,启用 AOT) 开发: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
最佳答案
I was wondering if the Just in Time compiler could "wire" the ps.println to the ps.println(String) instead of the ps.println(Object). That could explain such a problem, but I have no idea if this possible.
这是不可能的。或者至少不会,除非存在字节码编译器或 JIT 编译器错误。如果您有无可辩驳的证据表明情况确实如此,您应该只责怪编译器错误。
但是,我要检查的第一件事是正在执行的代码确实是从您正在查看的源代码编译而来的。确认这一点的一种方法是从源代码重新编译,然后比较在类的各个副本上运行 javap 的结果。查看字节码还会告诉您字节码编译器要使用哪个 println
重载。
编辑 - javap
输出清楚地表明该版本的字节码应该调用 println(Object)
,并且没有 checkcast
操作码在眼前。 JIT 编译器错误调用错误的方法并自发地插入代码来进行类转换,这听起来越来越难以置信。
关于java - ClassCastException 是由 Just In Time 中的错误引起的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2425487/