ClassCastException causado por erro no Just In Time?
-
19-09-2019 - |
Pergunta
Dado este pedaço de código:
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();
}
(por favor, nenhum conselho sobre como fluxos perto com segurança, este é o código legado ea nova versão faz uso de try / finally)
Eu recebo um ClassCastException no "ps.println (BUFFER.GET (i))"
Este método é chamado várias vezes (digamos, 5 vezes) com uma lista única cheia de Cordas em seguida, ele é chamado com uma lista cheia de cordas e um outro objeto (digamos ErrorObject) No ponto chegamos ao 1º ErrorObject, temos o ClassCastException.
com.mycompany.ErrorObject incompatible with java.lang.String
Este problema ocorre em ambiente de produção, mas não pode ser reproduzido no ambiente Dev: Prod: jvm = J9 IBM VM 2.4 J2RE 1.6.0 IBM J9 2,4 ppc AIX-32 jvmap3260-20081105_25433 (JIT activado, activado AOT) Dev: WinXP, JDK 1.6.0_16
Há alguma razão este código poderia falhar?
Foi corrigida recentemente, temo que a equipe de produção não atualizar o jar corretamente, mas meu chefe já verificado que o patch foi aplicado correclty ...
Eu queria saber se o Just in Time compilador poderia "fio" do ps.println ao ps.println (String) em vez do ps.println (Object). Isso poderia explicar um problema tão grande, mas eu não tenho idéia se isso possível.
Qualquer conselhos bem-vindo, agradeço antecipadamente
EDIT: i foi perguntado rastreamento de pilha completo por isso aqui está:
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)
EDIT 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
Solução
Eu queria saber se o Just in Time compilador poderia "fio" do ps.println ao ps.println (String) em vez do ps.println (Object). Isso poderia explicar um problema tão grande, mas eu não tenho idéia se isso possível.
Não é possível. Ou pelo menos não a menos que haja um compilador bytecode ou JIT compilador bug. E você só deve culpar os erros do compilador se você tiver provas irrefutáveis ??de que isso é assim.
No entanto, a primeira coisa que eu iria verificar é que o código está sendo executado foi realmente compilado a partir do código-fonte que você está olhando. Uma maneira de confirmar isso seria para recompilar a partir da fonte, e então comparar os resultados da execução javap
nas respectivas cópias da classe. Olhando para os bytecodes também irá dizer-lhe que a sobrecarga de println
o compilador bytecode está dizendo para uso.
Editar - a saída javap
mostra claramente que essa versão do bytecode deve chamar println(Object)
, e não há opcode checkcast
à vista. Um erro compilador JIT que chama o método errado e espontaneamente insere código para fazer um classcast está soando cada vez mais implausível.
Outras dicas
Declare método toString () com a conversão para string dentro na classe ErrorObject e adicionar + "" para println call (). Como pintln (errorObjList + "");