Keine NullPointerExceptions in nebenläufigen Threads

Sekundentakt

Bekanntes Mitglied
Hallo,

ich habe heute über mehrere Stunden versucht, einen Bug zu eliminieren, bis ich am Schluss festgestellt habe, dass die betroffenen Objekte Null waren.

Ein Beispiel war

Java:
if(arrayX.length == arrayY.length)
{
  //do something here
}

Das Programm blieb buchstäblich stehen. Es geschah nichts mehr nach diesem Block. Normalerweise hätte ich hier ne NullPointerException erwartet oder ähnliches.

Es gibt auch noch andere Situationen, wo mir ähnliches untergekommen ist.

Da wird man ja verrückt bei.
Das ist mir übrigens noch nie passiert und ich arbeite bereits seit Dezember mit Java.

Was mache ich hier falsch?

Danke für jeden Tipp!

Btw.: Ja, ich arbeite mit Eclipse und nicht im Editor! :)
 

Sekundentakt

Bekanntes Mitglied
EDIT:
Hier mal eine einfache Klasse, die das Problem reproduziert.

Java:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test {
	
	public static void main(String[] args)  {
		
		ExecutorService executor = Executors.newFixedThreadPool(5);
		executor.submit(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				String[] arrayX = null;
				
				System.out.println("Until this line, you expect at least one additional line of text. . . ");
				if(arrayX.length > 0)
					System.out.println("impossible");
				else
					System.out.println("I thought so");
			}
		});
	}
}
 
Zuletzt bearbeitet:

tfa

Top Contributor
Dein submit()-Aufruf liefert dir ein Future-Objekt (was du in deinem Programm einfach ignorierst). Exceptions die bei der Ausführung des Tasks auftreten, werden von diesem Future gekapselt. Wenn du auf das Ergebnis des Future zugreifen willst, fliegt dir dann auch die NullPointerException um die Ohren:

Java:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class NullThread {

	public static void main(String[] args) throws Exception {

		ExecutorService executor = Executors.newFixedThreadPool(5);

		Future f = executor.submit(new Runnable() {

			@Override
			public void run() {
				String[] arrayX = null;

				System.out.println("Until this line, you expect at least one additional line of text. . . ");
				if (arrayX.length > 0)
					System.out.println("impossible");
				else
					System.out.println("I thought so");
			}
		});
        Thread.sleep(1000);
		System.out.println(f.get());
	}
}
 
Zuletzt bearbeitet:

Sekundentakt

Bekanntes Mitglied
Danke für Dein Feedback.
Das klingt nach einem "Anfängerfehler" - irgendwie ärgert es mich jetzt nur umso mehr ;-).

Dann muss ich wohl noch an die Futures ran.

Gibt's ne Möglichkeit die auch im Thread selbst abzufangen? In manchen Fällen würde ich dann nämlich gerne Alternativen ausführen.
 

tfa

Top Contributor
Gibt's ne Möglichkeit die auch im Thread selbst abzufangen? In manchen Fällen würde ich dann nämlich gerne Alternativen ausführen.
Na klar. Du kannst doch überall try-catch drum herum machen. Auch in der run()-Methode.
In diesem Fall kann man das durch ein einfaches if() allerdings vermeiden.
 

Sekundentakt

Bekanntes Mitglied
Na klar. Du kannst doch überall try-catch drum herum machen. Auch in der run()-Methode.
In diesem Fall kann man das durch ein einfaches if() allerdings vermeiden.
Ich hab das heute schon mal durchgehabt:

InputStream auf null gesetzt und direkt unter der Null-Deklaration (in einem Try-Catch-Block) .read() aufgerufen.
Im Catch-Block sollte die Exception + System.out.println("Fehler") ausgegeben werden. Allerdings kam es dazu nicht.

Stattdessen blieb der Testaufbau genauso hängen, wie der Rest.
Oder muss ich die NullPointerException extra catchen?
 

nrg

Top Contributor
klar gibt es den:
Java:
                try {
                	 if(arrayX.length > 0)
                         System.out.println("impossible");
                     else
                         System.out.println("I thought so");
                } catch (Throwable t) {
                	t.printStackTrace();
                }
                System.out.println("Mach hier weiter");

musst du wissen, was du catchen willst. mit throwable solltest alles haben...

Achja zu "ich arbeite mit Eclipse". Also Eclipse wirft bei mir da eine Warnung aus...
 

nrg

Top Contributor
unbenannt77s1.jpg
 

Sekundentakt

Bekanntes Mitglied
In dem konkreten Beispiel, ja. Aber das ist zugegebenermaßen auch etwas sinnfrei ;-).

Dein Gedanke mit dem Throwable fängt wirklich alles hervorragend ab, ohne den ganzen Thread zu zerschießen.

Danke noch mal an alle Beteiligten. Wieder was dazugelernt!
 

Murray

Top Contributor
Throwable zu fangen ist nicht ganz ungefährlich. Damit fängt man u.a. auch den ThreadDeath ab, den man tunlichst wieder werfen sollte, wenn sich der Thread wirklich beenden soll.
 

tfa

Top Contributor
Throwable zu fangen sollte man normalerweise bleiben lassen. Damit fängst du wirklich alles, auch irgendwelche OutOfMemoryErrors, VirualMachineError, InternalError etc. Alles Sachen, die du nicht sinnvoll beheben kannst.
Es gilt die Regel, nur möglichst konkrete Exceptions zu fangen. Solche, die man erwartet und sinnvoll bearbeiten kann. Alles andere sollte weitergeworfen und an zentraler Stelle behandelt werden. Ich kenne dein kronkretes Problem nicht, aber vielleicht ist auch ein UncaughtExceptionHandler sinnvoll.
 

Sekundentakt

Bekanntes Mitglied
Throwable zu fangen ist nicht ganz ungefährlich. Damit fängt man u.a. auch den ThreadDeath ab, den man tunlichst wieder werfen sollte, wenn sich der Thread wirklich beenden soll.
Throwable zu fangen sollte man normalerweise bleiben lassen. Damit fängst du wirklich alles, auch irgendwelche OutOfMemoryErrors, VirualMachineError, InternalError etc. Alles Sachen, die du nicht sinnvoll beheben kannst.
Danke für die Hinweise. Ich habe das jetzt mal konkretisiert.

Ich kenne dein kronkretes Problem nicht, aber vielleicht ist auch ein UncaughtExceptionHandler sinnvoll.
Ich führe asynchrone Requests über das Netzwerk aus. Ich wollte dabei eigentlich vermeiden, irgendetwas zu sammeln, allerdings wäre es für's Logging denke ich praktischer, so etwas einzurichten?

Ich habe keine Produktiverfahrung, daher wäre ich hier für jede Idee dankbar.
 

tfa

Top Contributor
Auf dem Server würde ich nur konkrete, behandelbare Exceptions mit try-catch fangen (normalerweise sind das genau null). Zuviel try-catch ist absolut ungesund.
Der Rest (also praktisch alles) wird zentral in einem Exception-Handler bearbeitet. Mehr als Loggen und den betreffenden Thread abzuschießen kann man wahrscheinlich nicht.
Auf dem Client im Prinzip genauso, nur dass hier dem Anwender ein netter Fehlerdialog präsentiert wird mit der Empfehlung, sich an den Admin zu wenden. Zusätzlich könnte man optional die Fehlermeldung auch gleich an den Support schicken.
 

Sekundentakt

Bekanntes Mitglied
Der Rest (also praktisch alles) wird zentral in einem Exception-Handler bearbeitet. Mehr als Loggen und den betreffenden Thread abzuschießen kann man wahrscheinlich nicht.
Sprichst Du jetzt generell von Exception Handling oder speziell vom UncaughtExceptionHandler?

Ich glaube ich muss mich diesbezüglich noch etwas intensiver belesen.

Ich entwickle zurzeit einen Webservice, dabei fände ich es für eine Produktivanwendung, wenn es denn eine wäre, absolut unverantwortlich, wenn der User Exception-Nachrichten sehen könnte.

Kurz mal zur Architektur:

Im Servlet instantiiere ich ein Objekt. Dieses eine Objekt kapselt die gesamte Applikation.

Über doGet, doPost etc. lasse ich das Servlet Befehle an die Applikation weiterleiten.

Unter Rücksichtnahme darauf, dass ich mich mit ExceptionHandling noch nicht sehr intensiv auseinandergesetzt habe, würde ich - im Moment - so vorgehen: Die Exceptions werden geworfen oder gecatcht - je nachdem, was an welcher Stelle Sinn macht, aber das Servlet nutzt bei der Applikation Code, der in etwa so aussieht:

Java:
try {
   Answer a = myApp.getAnswer();
} catch (Exception e) {
    logger.log(e); 
    out.write("We are sorry! It seems like we currently can not give you an answer. Please, try again later or contact an administrator and provide detailed information about your request. Thank you!");
}

Ist das - ungefähr - der richtige Weg?
 

tfa

Top Contributor
Ja, so kann man das machen. Da du die Exception loggst, geht auch keine Information verloren.
Dem Anwender präsentiert man natürlich keine Stacktraces. Man kann die Exception aber so gut es geht in Klartext übersetzen und dann z.B. sagen "Es steht kein Speicher mehr zur Verfügung" oder "Die Verbindung konnte nicht aufgebaut werden" oder "Die Festplatte ist voll".
 

Murray

Top Contributor
Hilfreich könnte es auch sein, eine eindeutige ID zu vergeben, die man dann sowohl im Log (zusammen mit der Exception) ablegt als auch in der Fehlermeldung ausgibt. Wenn dann der betroffenen Anwender dem Support gegenüber diese ID angeben kann, hat man es leichter, die entsprechende Stelle im Log zu finden.
 

Sekundentakt

Bekanntes Mitglied
Alles was ich nicht mit catch sinnvoll abfangen kann, sollte demnach immer geworfen werden, richtig?

Das bedeutet, wenn immer wieder geworfen wird, erhält am Ende der - von der Ablaufreihenfolge - der den Befehl myApp.getAnswer() aufgerufen hat den kompletten StackTrace?
Oder gibt es hier auch Ausnahmen?

Ich bin nämlich gerade am Überlegen, wie ich systemkritische Exceptions sinnvoll abfangen kann, ohne das ich bestimmte Sicherheitsmechanismen blockiere. Hier wurden ja z.B. Sachen wie VirtualMachineError & Co, also sehr kritische Fehler, angesprochen. Wenn ich die jetzt alle über eine Methode catch (Exception e) abfange, gehe ich ein Sicherheitsrisiko ein, weil Prozesse dann von der JVM nicht mehr abgeschossen werden - sofern ich das richtig verstanden habe.
Irgendwie ist der Ansatz noch nicht so ganz das gelbe vom Ei... oder mache ich es mir gerade zu kompliziert?
 

Murray

Top Contributor
Die kritischen Fehler, die man besser nicht abfangen sollte, sind zwar Throwables, aber keine Exceptions. Insofern fängst Du sie mit catch( Exception e) auch nicht ab, wohl aber mit catch ( Throwable t).
 

Sekundentakt

Bekanntes Mitglied
Danke für den wertvollen Tipp.

Werden die systemkritischen Throwables dennoch ausgeworfen, oder kann ich die auch vor den Augen des Users verstecken?
 

Sekundentakt

Bekanntes Mitglied
Ich komme wieder nicht wirklich weiter.

Folgendes: Wenn meine Applikation, die für das Servlet nur ein einziges Objekt darstellt, instantiiert wird, startet sie intern einen Prozess, der über einen ScheduldedExecutorService ausgeführt wird.

Das geht so:
ScheduldedProcess p = new ScheduldedProcess(params);
p.startLookUp() -> startet einen Schedulded Thread. Der wird z.B. alle 30 Sekunden durchgeführt und schreibt in eine Queue, ob es etwas zu machen gibt und wenn ja, was.

p.startAsyncProcessing() -> startet alle 30 Sekunden ebenfalls einen Thread. Die Klasse heißt z.B. AsyncExecutor.

Innerhalb von AsyncExecutor wird die Queue über eine While-Schleife ausgelesen. Für jeden Eintrag wird ein Thread von einem normalen ExecutorService gestartet. Dieser verarbeitet immer genau einen Queue-Eintrag.

Für das ExceptionHandling habe ich mir jetzt folgendes ausgedacht: Jeder asynchrone Prozess erstellt ein StatusMessage-Objekt, in dem unter anderem auch die geworfenen Exceptions (die StackTraces) gespeichert werden. Dieses StatusMessage-Objekt schreibe ich in die Datenbank.
Das Problem ist, wenn die Exception bei der Datenbank auftreten würde, würde ich über die StatusMessage nie davon erfahren. Ich könnte sie jetzt noch auf Platte schreiben - das klingt designtechnisch aber nach ner schlechten Idee, weil StatusMessage dann Zugang zu einem zweiten DAO bräuchte.

Da das ApplicationObject, welches p instantiiert und ausführt, p eigentlich nicht mehr aufruft, weiß ich nicht, wie ich über p entstandene Exceptions abfangen soll.
Was ich mir vorstellen könnte wäre ein Hack. Ich glaube, dass UncaughtExceptionHandler (UEH) in diesem Falle Abhilfe schaffen könnte, oder? Wenn ich den UEH im AsyncExecutor unterbringe und er aber außerhalb von p referenziert wird, kann ich auf UEHs Exceptions zurückgreifen.
Jetzt stellt sich nur noch die Frage, wer holt die dort geworfenen Exceptions ab?
Ich könnte jedesmal wenn myApp.getAnswer() aufgerufen wird, checken, ob der UEH Exceptions enthält und diese dann ignorieren - haben mit .getAnswer() ja nichts zu tun -, aber in ein .log-File schreiben. Ich empfinde es aber als schlechten Stil, wenn .getAnswer, nur weil es die am stärksten frequentierte Methode wäre, das ExceptionHandling für Prozesse übernimmt, die nichts mit .getAnswer() zu tun haben.

Ich könnte mir nur vorstellen, noch einen Schedulded-Thread bei der Instantiierung von myApp zu starten. Der schaut z.B. alle 60 Sekunden nach, ob's ne Exception gibt, die aufgrund eines SQL-Fehlers (oder eines anderen DAO-Fehlers) nicht über die üblichen Kanäle behandelt werden konnte. Diese Exception holt er aus dem UEH und schreibt sie auf Platte.

Es könnte jetzt nur noch eine IOException in die Quere kommen. Wenn die Datei, die geschrieben wird, aber einen eindeutigen Namen erhält, dann ist die einzige Möglichkeit für einen IO-Fehler eigentlich nur noch defekte Hardware. Und wenn das der Fall ist, meckert Tomcat (bei einem Servlet) oder der Rechner, bei einer Desktopanwendung, bereits von selbst.

Denke ich hier zu kompliziert?

Danke für jede Anregung!

EDIT: Lösungsansatz: Logger
Ich habe bei weiteren Recherchen in den letzten Stunden was interessantes entdeckt: Den Java Logger.

Statt das Ganze so komplex aufzusetzen, wie ich es eben beschrieb, kann man es ja auch mit einem Logger lösen.
Alle run() Methoden werden grundsätzlich von einem Try-Catch-Block umschlossen, wenn future.get() vermieden werden soll. Im Catch-Block wende ich dann einen Logger an, der die geworfenen Exceptions via logger.throwing() mitloggt.
Falls die Exception auch außerhalb des Threads abgefangen werden kann, weil man future.get() verwenden will, könnte man auf logger.throwing() verzichten und stattdessen dort via logger.log() die uncatched Exception abfangen.

Falls der Ansatz hier ein positives Feedback erfährt, bereite ich dafür vielleicht auch mal ein komplexeres Tutorial vor.
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
berserkerdq2 Kann keine Labels erstellen, was ist hier syntaktisch falsch Allgemeine Java-Themen 5
berserkerdq2 Labels in IJVM sind keine lokalen Variablen oder? Allgemeine Java-Themen 2
O Warum kann ich so keine Elemente löschen und erhalte einen IllegalStateException? Allgemeine Java-Themen 4
pkm javax.script.ScriptEngineManager gibt mir keine Engine Allgemeine Java-Themen 4
N iText keine Sonderzeichen und Umlaute unter Windows Allgemeine Java-Themen 13
Tobero Eclipse Runnable jar exportiert keine Textures? Allgemeine Java-Themen 12
S createTempFile erstellt keine temporäre Datei Allgemeine Java-Themen 13
O xlsx Datei auslesen mit POI Apache liest keine LEERZELLEN Allgemeine Java-Themen 6
C javax.mail.Message message.setreplyto() null setzen (keine replyto Adresse) Allgemeine Java-Themen 25
Thallius Keine Ahnung Allgemeine Java-Themen 15
M WSDL: Doppelte Typenames (Keine Verwendung möglich) Allgemeine Java-Themen 5
L JPA keine shared primary key Allgemeine Java-Themen 11
M Keine weitere Eingabe in der Main möglich. Eventueller Ansatz über while. Allgemeine Java-Themen 8
P Datenbank-MiniGUI fügt keine Daten ein Allgemeine Java-Themen 4
T Input/Output Konsole gibt trotz printf keine Umlaute aus Allgemeine Java-Themen 17
N Warum habe ich keine Spaltenüberschriften? Allgemeine Java-Themen 6
W Thread sleep 30 sekunden - wenn keine Antwort bis dahin neu senden Allgemeine Java-Themen 2
Thallius Bekomme keine Exception mit Stacktrace mehr. Was habe ich getan? Allgemeine Java-Themen 13
H jid3lib nach schreiben keine Tags im Folder angezeigt Allgemeine Java-Themen 1
0 Code startet nicht (Keine Warnung/Fehlermeldung) Allgemeine Java-Themen 4
A Swing FileWriter schreibt keine Daten in Datei Allgemeine Java-Themen 13
J Programm meldet "Keine Rückmeldung" nach Verbindung zum Server Allgemeine Java-Themen 4
Z Eclipse hängt sich alle paar Sekunden auf (Keine Rückmeldung). Allgemeine Java-Themen 4
Bluedaishi Input/Output Bluetooth Bondrucker MZ220 keine Verbindung Allgemeine Java-Themen 0
F Cardlayout prüfen ob schon vorhanden, keine doppelten Allgemeine Java-Themen 3
R Es gibt keine dummen Fragen (hab ich mal gehört) Allgemeine Java-Themen 11
M Eclipse Keine Ausgabe mehr bei Fehlern Allgemeine Java-Themen 3
S Java Applet Crash - Keine Exception Allgemeine Java-Themen 8
V Files mit Umlauten ergeben keine Größe Allgemeine Java-Themen 9
S Bekomme mit Scanner und URL keine Html-Seite ausgelesen Allgemeine Java-Themen 3
127.0.0.1 Subversion neues SVN Projekt, keine Main gefunden ?! Allgemeine Java-Themen 7
A Collections HashMap.containsKey findet keine immutablen Objekte Allgemeine Java-Themen 3
M keine Bilder in .jar-Datei (java) Allgemeine Java-Themen 23
D Chat - keine Schrift sichtbar Allgemeine Java-Themen 4
J Eclipse Elipse gibt mir keine Vorschläge mehr :( Allgemeine Java-Themen 6
S Objekte die Objekte enthalten: Keine Vererbung Allgemeine Java-Themen 4
S Tomcat java.util.logging - keine Logs Allgemeine Java-Themen 12
Guybrush Threepwood Warten, bis keine Taste gedrückt Allgemeine Java-Themen 11
T Batch-File / keine Verbindung zur DerbyDB Allgemeine Java-Themen 3
O Zugriff auf Serielle Schnittstelle - Keine Ports gefunden. Allgemeine Java-Themen 8
X Warum kann ich keine ZIP Datein mit renameto() in was anderes benennen? Allgemeine Java-Themen 13
B warum keine nested blocks Allgemeine Java-Themen 2
GilbertGrape Jetty-Dienst startet keine Programme mit Oberfläche Allgemeine Java-Themen 2
S Keine Exception-Warning in Eclipse Allgemeine Java-Themen 3
D Warum keine Mehrfachvererbung? Allgemeine Java-Themen 5
tfa Keine Closures in Java 7 (?) Allgemeine Java-Themen 17
J Probleme wenn man keine serialVersionUID definiert? Allgemeine Java-Themen 27
G PrintWriter in .jar erstellt keine Datei Allgemeine Java-Themen 4
F Kann man keine Arrays von generischen Typen erstellen? Allgemeine Java-Themen 2
G Javadoc generiert keine Links zu java.lang Klassen? Allgemeine Java-Themen 4
A ArrayListe :Doppelte entfernen -> keine Referenzen Allgemeine Java-Themen 26
ARadauer Random keine Zahlen doppelt Allgemeine Java-Themen 4
T Wieso erfolgt keine Ausgabe. /Excel Allgemeine Java-Themen 19
F GregorianCalendar wirft keine Fehler bei z.b. Monat 17 Allgemeine Java-Themen 3
G Jarfile gibt keine Textnachrichten aus Allgemeine Java-Themen 2
J java vnc client verbessern: KeyEvent.VK_ALT keine Wirkung? Allgemeine Java-Themen 12
J jar-Datei enthält keine Main-Class Allgemeine Java-Themen 22
N Keine Klassen startbar/mit Abhängigkeiten erstellbar Allgemeine Java-Themen 2
WMaerz Der neue JDK 6 enthält keine javac.exe, tool.jar usw. Allgemeine Java-Themen 6
P Webhosting-Paket unterstützt nur .war Dateien keine jsp Allgemeine Java-Themen 4
A Kann keine neue Klasse erstellen. Allgemeine Java-Themen 3
D TextPane nach Laden keine Styles Allgemeine Java-Themen 2
A JSP include - keine Fehlermeldung Allgemeine Java-Themen 2
H Vektoren nehmen keine neuen Werte an Allgemeine Java-Themen 5
N Applet übernimmt keine Änderungen Allgemeine Java-Themen 13
C Vier Stellen Keine Doppelt (Zufall) Allgemeine Java-Themen 20
N Euklidischer Algorithmus in Java und keine Terminierung. Allgemeine Java-Themen 7
C Java zeigt keine Fensterinhalte Allgemeine Java-Themen 3
G Leere Fenster (Keine Schrift, Reiter/ Buttons) bei Java Allgemeine Java-Themen 5
G woher installiertes JDK? (keine Adminrechte) Allgemeine Java-Themen 3
R keine sqrt methode für bigintegers? Allgemeine Java-Themen 14
D NullPointerException wo keine sein sollte. Allgemeine Java-Themen 2
0 Keine clone-Methode für BigDecimal und BigInteger? Allgemeine Java-Themen 3
C Sound: Keine Line gefunden. Zu großer internal buffer? Allgemeine Java-Themen 3
Y Comm-API findet keine Ports Allgemeine Java-Themen 5
B Keine Musik bei Applikation Allgemeine Java-Themen 9
H Kann keine Zahlen von Buchstaben unterscheiden Allgemeine Java-Themen 4
V Javadoc ertellt keine korrekten links Allgemeine Java-Themen 3
B Alternative zu nebenläufigen Prozessen Allgemeine Java-Themen 4
M OutOfMemoryError in nebenläufigen Threads Allgemeine Java-Themen 6

Ähnliche Java Themen

Neue Themen


Oben