ClassCastExceptionがジャスト・タイムのバグによって引き起こされますか?
-
19-09-2019 - |
質問
このコードの一部を考える:
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();
}
(安全にストリームをクローズする方法についてのアドバイスは、これは既存のコードではありませんし、新しいバージョンでは、/ついに試しを利用してください)。
私は
"ps.println(BUFFER.GET(I))" でClassCastExceptionが取得しますこのメソッドは、文字列で埋めリストで数回(例えば5回)と呼ばれています そして、それは文字列およびその他のオブジェクトで満たさリストと呼ばれている(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ファイルをアップグレードしませんでしたが、私の上司はすでにパッチがcorrecltyに適用されたことを確認することを恐れて...
ジャストインタイムコンパイラ場合、私は思っていた「ワイヤ」の代わりにps.println(オブジェクト)のps.println(文字列)にps.printlnできました。 それは、このような問題を説明することができますが、これを可能ならば、私は考えている。
任意のアドバイスは歓迎し、
事前にあなたに感謝編集: 私はここで完全なスタックトレースを頼まれたことがあります:
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
解決
ジャストインタイムコンパイラ場合、私は思っていた「ワイヤ」の代わりにps.println(オブジェクト)のps.println(文字列)にps.printlnできました。それは、このような問題を説明することができますが、これを可能ならば、私は考えている。
それは不可能です。あるいは、少なくともバイトコードコンパイラやJITコンパイラのバグが存在しない場合を除きます。あなたはこれがそうであるという動かぬ証拠を持っている場合、あなたは唯一のコンパイラのバグのせいにする必要があります。
しかし、私がチェックする最初の事は、実行されているコードは本当にあなたが見ているソースコードからコンパイルされたということです。これを確認する一つの方法は、ソースから再コンパイルし、クラスのそれぞれのコピーにjavap
の実行結果を比較することであろう。バイトコードを見るとまたバイトコードコンパイラを使用するように言っているprintln
のどの過負荷を教えてくれます。
編集 - javap
出力が明らかにバイトコードのバージョンがprintln(Object)
を呼び出す必要があることを示しており、見えないcheckcast
オペコードがありません。間違ったメソッドを呼び出すJITコンパイラのバグはとは自発的にclasscastを行うためにコードを挿入鳴っているより多くの信じ難います。
他のヒント
ErrorObjectクラスの内部文字列に変換して、toString()メソッドを宣言し、()コールをprintlnをする「」+加えます。 pintlnのような(errorObjList + "");