제 시간에 버그로 인한 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 회)라고 불리며, 1st 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 ENABLED) DEV : WINXP, JDK 1.6 .0_16
이 코드가 실패 할 수있는 이유가 있습니까?
최근에 패치되었는데, 제작 팀이 항아리를 올바르게 업그레이드하지 않았을까 걱정되지만 상사는 이미 패치가 적용되었는지 확인했습니다 ...
Ps.Println (Object) 대신 Ps.Println을 Ps.Println (String)에 "와이어"할 수 있는지 궁금했습니다. 그것은 그러한 문제를 설명 할 수 있지만, 이것이 가능한지 전혀 모른다.
모든 조언을 환영합니다. 미리 감사드립니다
편집 : 나는 전체 스택 추적을 요청 받았으므로 여기에 있습니다.
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
해결책
Ps.Println (Object) 대신 Ps.Println을 Ps.Println (String)에 "와이어"할 수 있는지 궁금했습니다. 그것은 그러한 문제를 설명 할 수 있지만, 이것이 가능한지 전혀 모른다.
불가능합니다. 또는 바이트 코드 컴파일러 또는 JIT 컴파일러 버그가 없다면 최소한 그렇지 않습니다. 그리고 이것이 그렇지 않다는 증거가 없다면 컴파일러 버그를 비난해야합니다.
그러나 내가 확인할 첫 번째는 실행중인 코드가 실제로보고있는 소스 코드에서 컴파일되었다는 것입니다. 이것을 확인하는 한 가지 방법은 소스에서 다시 컴파일 한 다음 실행 결과를 비교하는 것입니다. javap
수업의 각 사본에서. 바이트 코드를 보면 어떤 오버로드가 println
바이트 코드 컴파일러는 사용한다고 말합니다.
편집하다 - javap
출력은 해당 버전의 바이트 코드가 호출해야 함을 분명히 보여줍니다. println(Object)
, 그리고 아니요 checkcast
시야에 OPCODE. 잘못된 메소드를 호출하는 JIT 컴파일러 버그 그리고 자발적으로 클래스 캐스트를하도록 코드를 삽입하면 점점 더 불가피하게 들릴 수 있습니다.
다른 팁
errorObject 클래스에서 내부 문자열로 변환하여 toString () 메소드를 선언하고 println () 호출에 +""를 추가하십시오. pintln (errorobjlist+"")처럼;