2

このコードを考えると:

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 回) 呼び出され、次に、文字列で満たされたリストと他のオブジェクト (たとえば、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(Object) の代わりに ps.println(String) に 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)

編集 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
4

2 に答える 2

4

ジャスト イン タイム コンパイラが ps.println(Object) の代わりに ps.println(String) に ps.println を「接続」できるかどうか疑問に思っていました。それはそのような問題を説明できますが、これが可能かどうかはわかりません。

それは不可能。または、少なくともバイトコード コンパイラまたは JIT コンパイラのバグがない限り、そうではありません。そして、これがそうであるという反論の余地のない証拠がある場合にのみ、コンパイラのバグを非難する必要があります。

ただし、最初に確認することは、実行中のコードが実際にあなたが見ているソース コードからコンパイルされたことです。これを確認する 1 つの方法は、ソースから再コンパイルしjavap、クラスのそれぞれのコピーで実行した結果を比較することです。printlnバイトコードを見ると、バイトコード コンパイラのどのオーバーロードを使用するように指示されているかがわかります。

編集-javap出力は、バイトコードのそのバージョンが呼び出す必要があることを明確に示しており、オペコードは見えprintln(Object)ません。checkcast間違ったメソッドを呼び出し、自発的にコードを挿入してクラスキャストを実行する JIT コンパイラのバグはますます信じられないように聞こえます。

于 2010-03-11T14:33:59.047 に答える
0

ErrorObject クラス内で文字列に変換する toString() メソッドを宣言し、println() 呼び出しに +"" を追加します。pintln(errorObjList+""); のように

于 2010-03-11T14:30:25.580 に答える