Question

Compte tenu de ce morceau de code:

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

(s'il vous plaît pas de conseils sur la façon de fermer les flux en toute sécurité, c'est le code existant et la nouvelle version utilise try / finally)

Je reçois un ClassCastException au "ps.println (BUFFER.GET (i))"

Cette méthode est appelée à plusieurs reprises (disons 5 fois) avec une liste uniquement rempli de chaînes puis, il est appelé avec une liste remplie de chaîne et un autre objet (disons ErrorObject) Au point où nous atteignons le 1er ErrorObject, nous obtenons le ClassCastException.

com.mycompany.ErrorObject incompatible with java.lang.String

Ce problème se produit dans un environnement de production, mais ne peut être reproduit dans un environnement Dev: Prod: = IBM jvm J9 VM 2.4 J2RE 1.6.0 IBM AIX 2.4 J9 ppc-32 jvmap3260-20081105_25433 (JIT activé, activé AOT) Dev: Windows XP, 1.6.0_16 JDK

Y at-il raison de ce code pourrait échouer?

Il a été patché récemment, je crains que l'équipe de production n'a pas correctement mise à jour le pot, mais mon patron déjà vérifié que le patch a été appliqué correclty ...

Je me demandais si le Juste au compilateur JIT pourrait « fil » le ps.println au ps.println (String) au lieu de l'ps.println (Object).  Cela pourrait expliquer un tel problème, mais je ne sais pas si cela est possible.

Les conseils bienvenue, je vous remercie à l'avance

EDIT: on m'a demandé trace complète de la pile si elle est ici:

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
Était-ce utile?

La solution

  

Je me demandais si le Juste au compilateur JIT pourrait « fil » le ps.println au ps.println (String) au lieu de l'ps.println (Object). Cela pourrait expliquer un tel problème, mais je ne sais pas si cela est possible.

Il est impossible. Ou du moins pas moins qu'il y ait un compilateur bytecode ou JIT bug du compilateur. Et vous ne devriez blâmer les bugs du compilateur si vous avez des preuves irréfutables que tel est le cas.

Cependant, la première chose que je voudrais vérifier est que le code en cours d'exécution a été vraiment compilé à partir du code source que vous regardez. Une façon de confirmer que ce serait recompiler de la source, puis de comparer les résultats de l'exécution javap sur les copies respectives de la classe. En regardant le bytecode également vous dire que la surcharge de println le compilateur bytecode dit à utiliser.

EDIT - la sortie de javap montre clairement que cette version du bytecode doit appeler println(Object), et il n'y a pas checkcast opcode en vue. Un bug du compilateur JIT qui appelle la mauvaise méthode et insère spontanément code pour faire un classcast sonne de plus en plus invraisemblables.

Autres conseils

Déclarer toString () avec la conversion en chaîne à l'intérieur de la classe ErrorObject et ajouter + « » à l'appel println (). Comme pintln (errorObjList + "");

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top