IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

NoClassDefFound pour une inner classe dans une méthode de la classe


Sujet :

Java

  1. #1
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut NoClassDefFound pour une inner classe dans une méthode de la classe
    Bonjour,

    j'ai rencontré un problème que j'aimerais comprendre : si quelqu'un à une idée sur le pourquoi du comment

    bon, c'est pas évident de l'expliquer de manière concise et encore moins de fournir un code :
    - dans une application Eclipse RCP, globalement SWT donc, j'ai un composant AWT (Piccolo)
    - j'ai une classe maison utilisée par piccolo, dans laquelle il y a une inner interface :
    en gros :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public class PHeadBand extends PNode {
     
       ...
     
       public void setColor(Color color) {
          ...
          if ( color instanceof IColoredPaint ) {
             ...
          }
          ...
       }
     
       ...
     
       public interface IColoredPaint {
       }
     
    }
    il y a évidemment une erreur de conception : l'interface devrait être au moins statique, si ce n'est externe, mais bon, ce n'est pas la question que je me pose

    - la classe existe depuis un bail (2009), et j'ai un certain nombre de traitements qui réagissent a des événements diverses (changement de préférences, changement dans le modèle, etc...) qui provoque un traitement du type :
    1) changement d'états et calculs diverses (soit directement sur le thread SWT, soit dans un Job, soit dans un autre type de process parallèle
    2) relayout (dans un thread géré par un SingleThreadExecutor, pour éviter des relayout concurrent - donc toujours un seul relayout à un instant donné)
    3) repaint AWT/SWING

    le relayout étant une tâche pouvant créer ou supprimer des instances de PHeadBand dans un thread qui n'est donc pas le thread graphique AWT.

    évidemment, on peut avoir le thread graphique qui se déclenche pour faire un repaint, mais la méthode setColor n'est jamais invoquée dans aucune méthode susceptible d'être invoquée depuis le thread graphique :

    donc mon service de layout analyse le modèle, estime quelles instances de PHeadBand il doit créer ou supprimer, ou modifier et comment, et les ajoute ou supprime dans le canvas piccolo, ou les modifie. rien de spécial donc.

    j'ai mis en place cet après midi une énième preférence qui déclenche le traitement classique lorsqu'on change sa valeur

    pour le détail, PHeadBand a des bounds qui dépendaient de 2 valeurs
    - une hauteur mini et une hauteur standard calculée par une formule "truc divisé par machin"
    - hauteur mini est une préférence depuis un bail
    - truc est calculé en dynamique par rapport a des éléments du modèle mais change très rarement
    - machin était une constante
    et j'ai donc transformé cette constante machin en préférence

    et là lorsque je relayoute j'obtiens une java.lang.NoClassDefFoundError pour l'interface IColoredPaint sur la ligne "if ( color instanceof IColoredPaint ) {"

    donc
    - soit IColoredPaint est détruite alors que sa classe englobante existe encore
    - soit la classe englobante est détruire, donc IColoredPaint aussi, pendant qu'on exécute une méthode de cette classe (parce que je vois vraiement pas comment on pourrait appeler une méthode d'une instance qui n'existe plus)
    - soit il y a un truc qui m'échappe dans le fonctionnement des classloaders de OSGI qui pourrait expliquer qu'une inner interface et sa classe ne soit pas chargées par les mêmes classloader
    - soit il y a un autre comportement java que je connais pas qui expliquerait ce comportement étrange

    je peux préciser que d'après la stacktrace, la méthode setColor est appelée pour une instance de PHeadBand existente.

    je ne pense pas que ça puisse servir à grand chose, mais voilà quand même la stack trace :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    java.lang.NoClassDefFoundError: fr/wedia/noheto/zui/piccolo/PHeadBand$IColoredPaint
    	at fr.wedia.noheto.zui.piccolo.PHeadBand.buildColor(PHeadBand.java:315)
    	at fr.wedia.noheto.zui.piccolo.PHeadBand.setColor(PHeadBand.java:423)
    	at fr.wedia.noheto.engine.qual.zui.PQualificationNode.setNode(PQualificationNode.java:241)
    	at fr.wedia.noheto.engine.qual.zui.PQualificationNode.updatePNodes(PQualificationNode.java:223)
    	at fr.wedia.noheto.engine.qual.zui.PQualificationNode.setUserObject(PQualificationNode.java:216)
    	at fr.wedia.noheto.engine.qual.zui.PQualificationNode.setUserObject(PQualificationNode.java:1)
    	at fr.wedia.noheto.zui.flatplan.component.AWTSWTZuiHandler.setUserObject(AWTSWTZuiHandler.java:44)
    	at fr.wedia.noheto.zui.flatplan.component.AbstractFlatPlanLayout._doLayout_qualification(AbstractFlatPlanLayout.java:2000)
    	at fr.wedia.noheto.zui.flatplan.component.AbstractFlatPlanLayout._doLayout(AbstractFlatPlanLayout.java:1574)
    	at fr.wedia.noheto.zui.flatplan.component.AbstractFlatPlanLayout.access$1(AbstractFlatPlanLayout.java:1510)
    	at fr.wedia.noheto.zui.flatplan.component.AbstractFlatPlanLayout$LayoutTask.run(AbstractFlatPlanLayout.java:1193)
    	at fr.wedia.util.java.concurrent.SafeRunnableWrapper.run(SafeRunnableWrapper.java:28)
    	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:417)
    	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:269)
    	at java.util.concurrent.FutureTask.run(FutureTask.java:123)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
    	at java.lang.Thread.run(Thread.java:595)
      0  0

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par joel.drigo Voir le message
    il y a évidemment une erreur de conception : l'interface devrait être au moins statique, si ce n'est externe, mais bon, ce n'est pas la question que je me pose
    De toute manière les interfaces définies en interne sont implicitement statique...


    Citation Envoyé par joel.drigo Voir le message
    et là lorsque je relayoute j'obtiens une java.lang.NoClassDefFoundError pour l'interface IColoredPaint sur la ligne "if ( color instanceof IColoredPaint ) {"
    Comment est le code exact de IColoredPaint ?
    Hérite-t-elle d'autres interfaces ?
    Utilises-t-elle d'autres types d'objets ?


    Sinon le stacktrace indique plutôt que l'erreur survient dans la méthode buildColor()...


    a++
      0  0

  3. #3
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Salut,


    De toute manière les interfaces définies en interne sont implicitement statique...
    c'est ce qui me semblait aussi, mais je préfère être le plus souvent explicite, ça évite de se poser des questions.

    cela dit, étrangement, depuis que j'ai déclaré l'interface explicitement statique, je n'ai plus l'exception !?

    Citation Envoyé par adiGuba Voir le message

    Comment est le code exact de IColoredPaint ?
    Hérite-t-elle d'autres interfaces ?
    Utilises-t-elle d'autres types d'objets ?
    rien de spécial :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public interface IColoredPaint {
    	void setMainColor(Color color, Color defaultColor);
    }



    Citation Envoyé par adiGuba Voir le message
    Sinon le stacktrace indique plutôt que l'erreur survient dans la méthode buildColor()...
    j'ai juste un peu simplifié mon extrait de code,

    pour le détail, le composant a un jeu de couleurs : principale, fond, secondaire... et un style de rendu (configurable par plusieurs variables)
    les méthodes de configuration de couleurs et de styles appellent toutes buildColor qui créer les différents éléments qui vont permettre de faire le rendu final à partir des différents paramètres,...
      0  0

  4. #4
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 807
    Points
    48 807
    Par défaut
    Citation Envoyé par joel.drigo Voir le message
    - soit IColoredPaint est détruite alors que sa classe englobante existe encore
    Vu que les innerclass aboutissent, à la compilation, dans des .class séparés de la outer class, si le compilateur a merdouillé, tu peux perdre l'inner class => clean rebuild
    Citation Envoyé par joel.drigo Voir le message
    - soit la classe englobante est détruire, donc IColoredPaint aussi, pendant qu'on exécute une méthode de cette classe (parce que je vois vraiement pas comment on pourrait appeler une méthode d'une instance qui n'existe plus)
    Peux probable, les classes ne quittent jamais leur classloader une fois chargées.
    Citation Envoyé par joel.drigo Voir le message
    - soit il y a un truc qui m'échappe dans le fonctionnement des classloaders de OSGI qui pourrait expliquer qu'une inner interface et sa classe ne soit pas chargées par les mêmes classloader
    Peu probablem selon mon. Surtout si elle sont dans un .jar!
    - soit il y a un autre comportement java que je connais pas qui expliquerait ce comportement étrange
    Pareil. T'as essayé donc de faire un clean de ton projet? De retélécharger le jar de picolo?
      0  0

  5. #5
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Vu que les innerclass aboutissent, à la compilation, dans des .class séparés de la outer class, si le compilateur a merdouillé, tu peux perdre l'inner class => clean rebuild
    j'ai commencé par faire un clean/rebuild : sans parler des liens possibles entre éléments statiques dans les classes compilées, c'est en plus un réflexe avec Eclipse RCP, surtout quand on a 200 plugins

    Citation Envoyé par tchize_ Voir le message
    ... Surtout si elle sont dans un .jar!
    j'étais en exé sous Eclipse. Remarque j'ai pas testé la build (j'avais pas vraiment envie de commiter mon code pour faire une build pour tester ça, et j'avais encore moins envie de mettre en place une target locale de build rien que pour ça (j'avais surtout pas le temps))

    Citation Envoyé par tchize_ Voir le message
    Pareil. T'as essayé donc de faire un clean de ton projet? De retélécharger le jar de picolo?
    j'ai fait un clean global vu que le clean des plugins entrant en jeu ne changeait rien

    le jar de piccolo je l'ai rebuildé et donc changer y'a pas longtemps, mais je vois pas trop en quoi ce serait lié vu les méthodes par lesquelles on passe.

    j'ai bien entendu tester en modifiant d'autres prefs : on passe par la même stacktrace et on a pas l'exception !

    dans les possibilités de raisons j'ai pas cité le faisceau de neutrinos ni la poupée vaudou sous mon siège, ou encore de facétieux strangulos
    et je ne peux pas croire que c'est le calva dans la tarte aux pommes du restau de hier midi, le chef a dit qu'il en avait mis juste un peu
      0  0

Discussions similaires

  1. Réponses: 2
    Dernier message: 19/07/2011, 13h57
  2. Réponses: 8
    Dernier message: 05/04/2011, 08h06
  3. Réponses: 6
    Dernier message: 13/11/2009, 16h06
  4. Réponses: 4
    Dernier message: 16/05/2006, 23h15
  5. Réponses: 11
    Dernier message: 06/12/2005, 08h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo