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 :
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
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 { } }
- 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)
Partager