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();
}
(يرجى عدم وجود نصيحة حول كيفية إغلاق التدفقات بأمان، وهذا هو الرمز القديم والإصدار الجديد يستفيد من محاولة / أخيرا)
أحصل على ClasscastException في "ps.println (buffer.get (i))"
وتسمى هذه الطريقة عدة مرات (قل 5 مرات) مع قائمة مليئة فقط بأسلوتات إذن، يتم استدعاؤها بقائمة مليئة بالسلسلة وكائن آخر (Say ErrorObject) عند نقطة نصل إلى 1st 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.
هل هناك أي سبب يمكن أن يفشل هذا الرمز؟
تم تصحيحه مؤخرا، أخشى أن يقوم فريق الإنتاج بترقية الجرة بشكل صحيح، لكن مدربي فحص بالفعل أن التصحيح تم تطبيقه Correclty ...
كنت أتساءل عما إذا كان برنامج التحويل البرمجي الزمني فقط يمكن أن "سلك" ps.println إلى 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
المحلول
كنت أتساءل عما إذا كان برنامج التحويل البرمجي الزمني فقط يمكن أن "سلك" ps.println إلى ps.println (string) بدلا من ps.println (كائن). يمكن أن يفسر مثل هذه المشكلة، لكن ليس لدي أي فكرة إذا كان ذلك ممكنا.
ليس من الممكن. أو على الأقل ليس فقط ما لم يكن هناك مترجم bytecode أو خطأ محمول JIT. ويجب عليك إلقاء اللوم على البق المترجم فقط إذا كان لديك أدلة لا رجعة فيها على أن هذا هو كذلك.
ومع ذلك، فإن أول شيء أتحقق منه هو أن الكود الذي يتم تنفيذه تم جمعه حقا من التعليمات البرمجية المصدر التي تنظر إليها. طريقة واحدة لتأكيد ذلك سيكون لإعادة ترجمة المصدر، ثم قارن نتائج التشغيل javap
على نسخ المعنية من الفصل. لن يخبرك بالنظر إلى Bytecodes أيضا إلى الحمل الزائد println
مترجم bytecode يقول للاستخدام.
تعديل - ال javap
يوضح الإخراج بوضوح أن هذا الإصدار من ByTecode يجب أن يسميه println(Object)
, ، وليس هناك checkcast
Opcode في الأفق. خطأ محمول JIT الذي يستدعي الطريقة الخطأ و إدراج رمز تلقائيا للقيام بذكاء يكون سبر أكثر وأكثر من اللازم.
نصائح أخرى
تعلن طريقة ToString () مع تحويل إلى سلسلة داخل في فئة ErrorObject وإضافة + "" "إلى Println (). مثل pintln (errorobjlist + "")؛