# JComponent -> java.lang.NullPointerException



## 123456789 (31. Mai 2011)

Hallo,

ich arbeite zur Zeit an einer graphischen Oberfläche und während eines JUnit Test durchlaufs wird die folgende Exception geworfen. Im Testdurchlauf werden nur Daten innerhalb der JTable geändert und die entsprechenden Abhänigkeiten überprüft.


```
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
	at javax.swing.JComponent._paintImmediately(Unknown Source)
	at javax.swing.JComponent.paintImmediately(Unknown Source)
	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
	at javax.swing.RepaintManager.seqPaintDirtyRegions(Unknown Source)
	at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
	at java.awt.event.InvocationEvent.dispatch(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)
```

Besonders merkwürdig finde ich, dass die Exception nicht bei jedem Testdurchlauf geworfen wird, sondern nur sporadisch.
Kann mir bitte jemand einen Tipp geben, wie man an so ein Problem herangeht, bzw. damit umgeht?


----------



## Marco13 (31. Mai 2011)

Schwer zu sagen... aber ... die Tabelle ist währenddessen NICHT sichtbar? (Könnte damit zusammenhängen, wäre aber auch schon seltsam...)


----------



## 123456789 (31. Mai 2011)

Danke Marco, für deine Antwort

was mich noch interessiert ist, ob ich das Auftreten solch einer Exception ignorieren kann, oder versuchen soll, den Grund dafür zu finden?
Denn die Exception tritt ja nicht immer auf!

Vielen Dank


----------



## VfL_Freak (31. Mai 2011)

Moin,



123456789 hat gesagt.:


> was mich noch interessiert ist, ob ich das Auftreten solch einer Exception ignorieren kann, oder versuchen soll, den Grund dafür zu finden?



Auftretende Fehler (und auch Warnings  ) sollte man *NIE NIE NIE* ignorieren  

Gruß
Klaus


----------



## Marco13 (31. Mai 2011)

Najaaaa... JComponent._paintImmediately ist eine SO interne Methode, dass man davon ausgehen könnte, dass das nichts ist, was auch nur Ansatzweise mit diesem (oder irgendeinem!) Unit-Test abgedeckt wird. Vermutlich ist es wirklich nur ein Artefakt. 
Eigentlich würde ich meinen, dass es auch daher kommen könnte, dass die Sachen NICHT auf dem EDT gemacht werden, aber der Stack Trace sieht anders aus ... bin mir gerade nicht sicher... Machst du die Änderungen an der JTable und dem TableModel NUR auf dem EDT?


----------



## 123456789 (31. Mai 2011)

Der UnitTest initialisiert zuerst das gesamte GUI, und alle weiteren Operationen erfolgen auf Datenmodellebene. Events werden vom Test keine generiert. Aus meiner Sicht gesehen dürfte dann der EDT auch nicht mit Anweisungen aus dem Swing Framework gefüllt werden. Oder?
Was mich wirklich erstaunt ist, dass diese Exception wirklich nur hin und wieder auftritt (ca. bei jedem 10 Test. und dann genau 2 mal  ???:L  )  

Danke,


----------



## Marco13 (31. Mai 2011)

Es ging um die Frage, ob du irgendwo sowas machst wie table.setValueAt, und dieser Aufruf NICHT aus dem EDT gemacht wird. Wenn irgendein anderer Thread das macht, könnte(!) das zu solchen Problemen führen.


----------



## twseitex (2. Jun 2011)

Hier ein Beispiel, das mir passiert ist unter Java SE - eventuell ein Analogon

Es wird ein Vordergrundbild animiert per Routine, die rekursiv im Thread läuft
	und dort ausführt createImage(....);



Exception in thread "Thread-10" java.lang.StackOverflowError
	at java.util.Hashtable.put(Unknown Source)
	at sun.java2d.Disposer.add(Unknown Source)
	at sun.java2d.Disposer.addRecord(Unknown Source)
	at sun.awt.image.BufImgSurfaceData.initRaster(Native Method)
	at sun.awt.image.BufImgSurfaceData.createDataIC(Unknown Source)
	at sun.awt.image.BufImgSurfaceData.createData(Unknown Source)
	at sun.awt.image.CachingSurfaceManager.<init>(Unknown Source)
	at sun.java2d.d3d.D3DCachingSurfaceManager.<init>(Unknown Source)
	at sun.java2d.SurfaceManagerFactory.createCachingManager(Unknown Source)
	at sun.awt.image.OffScreenImage.createSurfaceManager(Unknown Source)
	at sun.awt.image.OffScreenImage.initSurfaceManager(Unknown Source)
	at sun.awt.image.OffScreenImage.<init>(Unknown Source)
	at sun.awt.Win32GraphicsConfig.createAcceleratedImage(Unknown Source)
	at sun.awt.windows.WComponentPeer.createImage(Unknown Source)
	at java.awt.Component.createImage(Unknown Source)
	at java.awt.Component.createImage(Unknown Source)
	at java.awt.Component.createImage(Unknown Source)
	at java.awt.Component.createImage(Unknown Source)
	at java.awt.Component.createImage(Unknown Source)

	   Obwohl StackOverflowError KEINE Exception ist, erklärt Java den
     Error zur Exception. Aber NUR Exception sind vom Programmierer
     behandelbar. Error sind Stati der Virtuellen Maschine und unbehandelbar.

    Der Grund für Exception ist folgender:
		java.util.Hashtable.put(Unknown Source)   hat NullpointerException von .put()

		Wer jetzt hofft, dass die ERSTE Gefundene Nullpointer-Ausnahme

	         abfangbar ist, ohne das Stackoverflowerror entsteht, der irrt, denn
				Stackoverflowerror kommt vor dem Nullpointer, so dass mit
      				Nullpointer der Thread bereits gecrasht ist.


      try-catch wird bei Stackoverflow nicht mehr abgearbeitet


----------



## VfL_Freak (3. Jun 2011)

Moin,



twseitex hat gesagt.:


> Der Grund für Exception ist folgender:
> java.util.Hashtable.put(Unknown Source)   hat NullpointerException von .put()


Zeig doch mal den relevanten Code ....



twseitex hat gesagt.:


> try-catch wird bei Stackoverflow nicht mehr abgearbeitet


Das ist klar, wenn Dein Speicher voll ist, dan geht nichts mehr ....
Probier mal den Parameter -Xss4M (setzt den Stack pro Thread auf 4 MB), kann natürlich variiert werden.

Aber ich denke mal, dass das eigentliche Problem schon früher auftritt!

Gruß
Klaus


----------



## SlaterB (3. Jun 2011)

twseitex hat gesagt.:


> Obwohl StackOverflowError KEINE Exception ist, erklärt Java den
> Error zur Exception. Aber NUR Exception sind vom Programmierer
> behandelbar. Error sind Stati der Virtuellen Maschine und unbehandelbar.


'Exception' ist hier doch nur eine Ausgabe, ein Log, ob da nun 'Error' oder 'Exception' steht..

und gerade dieser StackOverflowError ist doch wohl behandelbar? als der Stack voll war schmiss Java den Error, die Methodenkette wurde durchbrochen,
jetzt ist der Stack wieder leer, das Programm in einem so guten Zustand wie jedes andere auch,
das Fehler ist behandelbar, das Programm darf weiterlaufen, man sollte sich nur bis zum nächsten Update merken, Knopf X nicht mehr zu klicken


----------



## Ebenius (3. Jun 2011)

Du initialisierst Deine GUI im JUnit-Test. Mach das doch auf dem EDT und guck mal, ob der Fehler dann weg ist. In etwa:

```
try {
  SwingUtilities.invokeAndWait(new Runnable() {
    @Override
    public void run() {
      initializeGUI();
    }
  });
} catch (InterruptedException ex) {
  System.err.println("JUnit test has been interrupted");
  Thread.currentThread().interrupt();
}
```
HTH, Ebenius


----------



## twseitex (3. Jun 2011)

Hi,

Das Problem aus meinem Beispiel habe ich gelöst. Es sollte nur eine Anregung sein.

Threads müssen explizit so kodiert werden, dass Speicher nicht kumulativ
gefüllt wird (z.B. klassenglobale Variablen nutzen im Thread, Threads vor
Parallelaufruf schützen, Speicher im Thread erzeugt auch dort aufräumen,
möglichst keine Parameter der Funktionen).
Die Speichereinstellung per Parameter habe ich explizit weggelassen, da
das Applet so wie das jeweilige Java SE vorsieht, laufen soll (welcher
Standarduser kann Java konfigurieren ..)

Den Quellcode zu diesem Fehler kann ich nicht hier angeben, da zu komplex:
Es laufen 3 Klassen parallel, die jeweils eigene Threadverwaltung haben und
sich synchronisieren müssen. Wer die JAR rekompiliert, erhält den Quellcode
aber ohne Kommentare.

Das Applet ist ein Javaplayer für Audio mit Bildanimation und konfigurierbarer
GUI - also laufen die Appletklasse, die GUI-Klasse und die Audioklasse parallel
und werden synchronisiert (alle diese Klassen haben je Unterklassen). Und Java
räumt Audio- und GUI-Klasse nicht synchron auf: Die Audioklasse braucht länger
als das Entsorgen der GUI. Beide Klassen laufen mit mehreren getrennten Threads,
wobei ein dritter Thread synchronisiert (Aktionen der Klassen aktivieren lässt).

Was mir also nicht gelungen ist: Wenn das Applet endet, dann sollten
die 3 Klassen synchron enden - tun sie aber nicht, da Java SE aufräumt, wann es will.
Ich vermute: Parallele Threads  und Ressourcen sind der Grund, so dass
irgendwann ein o.g. Fehler auftritt, wenn man Threads nicht gründlich genug
programmiert und jede Fehlerquelle ausschliesst.

Das Applet findet man auf meiner Webseite twseiten.com (audio, flash and java).
Interessant ist übrigens, dass der MS Internet Explorer 8 wieder mal zickig ist
(so wie bei Flash (Flash-Player auch auf der Webseite zu finden)).
Die dynmamische Ansteuerung des Applets per Javascript ist ebenfalls
etwas zickig.

Cu.


----------



## 123456789 (6. Jun 2011)

Hallo, und danke für eure Antworten.

@Marco13: setValue wird definitiv im JUnittest aufgerufen. Danke das könnte die Ursache sein.

@Ebenius:  Ich hab das jetzt mit SwingUtilities versucht, und seitdem ist der Fehler nicht mehr aufgetreten. Ich denk das war die Lösung für mein Problem.

Jetzt hab ich nur noch eine Bitte. Kann mir jemand erklären was 

SwingUtilities.invokeAndWait(new Runnable()     und auch  
SwingUtilities.invokeLater(new Runnable()

genau macht. Bitte nur eine einfache Erklärung.

Vielen Dank!


----------



## Marco13 (6. Jun 2011)

Das mit den SwingUtilities war das, was aus meinen Fragen zum EDT oben folgte  Aber um weiter auzuholen: JEDE Operation, die den Zustand einer Swing-Component verändert (oder vom aktuellen Zustand abhängt) muss vom Event-Dispatch-Thread (EDT) gemacht werden. Der EDT ist praktisch der "Haupt-Thread" von Swing, der sich um Benutzereingaben, Zeichnen und alles andere GUI-spezifische kümmert (siehe auch Threads and Swing )

Mit SwingUtilties.invoke... wird sichergestellt, dass as übergebene Runnable auf dem EDT ausgeführt wird.


----------

