Исключение ClassCastException, вызванное ошибкой в Just In Time?

StackOverflow https://stackoverflow.com/questions/2425487

  •  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();
}

(пожалуйста, никаких советов о том, как безопасно закрывать потоки, это устаревший код, и в новой версии используется функция try / finally)

Я получаю исключение ClassCastException в "ps.println(buffer.get(i))".

этот метод вызывается несколько раз (скажем, 5 раз) со списком, заполненным только строками затем он вызывается со списком, заполненным String и другим объектом (скажем, ErrorObject) В тот момент, когда мы достигаем 1-го 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, но мой босс уже проверил, что патч был применен правильно...

Мне было интересно, может ли компилятор Just in Time "подключить" 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
Это было полезно?

Решение

Мне было интересно, может ли компилятор Just in Time "подключить" ps.println к ps.println (String) вместо ps.println (Object).Это могло бы объяснить такую проблему, но я понятия не имею, возможно ли это.

Это невозможно.Или, по крайней мере, нет, если нет ошибки компилятора байт-кода или JIT-компилятора.И вы должны винить ошибки компилятора только в том случае, если у вас есть неопровержимые доказательства того, что это так.

Однако первое, что я бы проверил, это то, что выполняемый код действительно был скомпилирован из исходного кода, который вы просматриваете.Одним из способов подтвердить это было бы перекомпилировать файл из исходного кода, а затем сравнить результаты запуска javap на соответствующих экземплярах класса.Просмотр байт-кодов также подскажет вам, какая перегрузка println компилятор байт-кода предлагает использовать.

Редактировать - тот самый javap выходные данные ясно показывают, что эта версия байт-кода должна вызывать println(Object), и нет никакого checkcast код операции на виду.Ошибка JIT-компилятора, вызывающая неправильный метод и спонтанная вставка кода для создания classcast звучит все более и более неправдоподобно.

Другие советы

Объявите метод toString() с преобразованием в string внутри в классе ErrorObject и добавьте +"" к вызову println().Как pintln(errorObjList+"");

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top