java.lang.NullPointerException bei Threadprogrammierung

Status
Nicht offen für weitere Antworten.

jobu0101

Bekanntes Mitglied
Java:
while (t1.bytes.size() > 0 && t2.bytes.size() > 0) {
    iden=true;
    for(int i=0;i<t1.bytes.get(0).length;i++){
        if(t1.bytes.get(0)[i]!=t2.bytes.get(0)[i])
            iden=false;
    }
    if (iden) {
        counter -= t1.bytes.get(0).length;
        t1.lock.lock();
        t1.bytes.remove(0);
        t1.lock.unlock();
        t2.lock.lock();
        t2.bytes.remove(0);
        t2.lock.unlock();
    } else {
        t1.interrupt();
        t2.interrupt();
        System.out.println("Dateien unterscheiden sich beim "
                + (size - counter + 1) + ". Array");
        return false;
    }
}

Das ist ein Teil des Programms. Der Teil der mir Probleme bereitet. Manchmal geht alles gut, manchmal tritt in der Zeile: "if(t1.bytes.get(0)!=t2.bytes.get(0))" eine Exception in thread "Thread-0" java.lang.NullPointerException auf. Ich kann aber nicht verstehen wieso. Zwar fügen die Threads t1 und t2 den ArrayListen t1.bytes und t2.bytes über add Elemente zu, doch löscht alleine diese Schleife hier Elemente raus. Beim Löschen (kann man ja hier sehen), aber auch beim Adden wird gelockt. Bei den Leseoperationen nicht. Die While-Schleife fragt ganz oben ab, ob die beiden Listen noch Elemente haben. Wie kann es dann manchmal später beim Zugriff zu einer NullPointerException kommen?
 
Zuletzt bearbeitet:
Wenn dort eine NullPointerException auftritt, gibt es mehrere Möglichkeiten:
t1 ist null
t2 ist null
t1.bytes ist null
t2.bytes ist null
t1.bytes.get(0) ist null
t2.bytes.get(0) ist null
(theoretisch glaubich noch zwei mehr, wenn da das Auto-Unboxing zuschlägt)

Insbesondere die letzten beiden sind durch die while-Bedingung obendrüber ja nicht ausgeschlossen. Aber selbst wenn, dann könnte ein anderer Thread zwischen dem Überprüfen des while-Bedinung und dem "if" irgendwelchen Mist mit t1 und t2 machen...
 
Wenn dort eine NullPointerException auftritt, gibt es mehrere Möglichkeiten:
t1 ist null
t2 ist null
t1.bytes ist null
t2.bytes ist null
t1.bytes.get(0) ist null
t2.bytes.get(0) ist null
(theoretisch glaubich noch zwei mehr, wenn da das Auto-Unboxing zuschlägt)

Insbesondere die letzten beiden sind durch die while-Bedingung obendrüber ja nicht ausgeschlossen. Aber selbst wenn, dann könnte ein anderer Thread zwischen dem Überprüfen des while-Bedinung und dem "if" irgendwelchen Mist mit t1 und t2 machen...

Das Einzige, was dazwischen passieren kann, ist das Hinzufügen eines neuen Elements...
 
Aber es ist nicht sichergestellt, dass nicht während des Hinzufügens ein anderer Thread Daten liest? Poste mal den Stack trace.
 
Exception in thread "Thread-0" java.lang.NullPointerException
at compare.Compare.compare(Compare.java:41)
at compare.Compare.run(Compare.java:69)
 
Hier zur Analyse mal das komplette Programm:

Das Programm dient dem Vergleichen zweiter Dateien:

Java:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ReadFile extends Thread {

	File f;
	InputStream in;
	public ArrayList<byte[]> bytes;
	public Long size;
	int step = 100000;
	int maxSize = 100;
	final Lock lock;

	ReadFile(File file) {
		f = file;
		if (!f.exists())
			throw new IllegalArgumentException("File does not exist!");
		bytes = new ArrayList<byte[]>();
		lock = new ReentrantLock();
	}

	void read() {
		size = f.length();
		byte[] buffer;
		try {
			in = new FileInputStream(f);
		} catch (FileNotFoundException e) {
			System.err.println("File does not exist!");
		}
		for (long i = size; i > 0 && !isInterrupted(); i -= step) {
			while (bytes.size() > maxSize) {
				try {
					sleep(1);
				} catch (InterruptedException e) {
					System.err.println("Interrupted!");
				}
			}
			buffer = new byte[(int) Math.min(i, step)];
			try {
				in.read(buffer);
			} catch (IOException e) {
				System.err.println("Fehler beim Lesen!");
			}
			lock.lock();
			bytes.add(buffer);
			lock.unlock();
		}
		try {
			in.close();
		} catch (IOException e) {
			System.err.println("Fehler beim Schließen!");
		}
	}

	public void run() {
		read();
	}

}

Java:
import java.io.File;

public class Compare extends Thread {

	ReadFile t1, t2;
	long size, counter;

	Compare(File f1, File f2) {
		t1 = new ReadFile(f1);
		t2 = new ReadFile(f2);
	}

	boolean compare() {
		t1.start();
		t2.start();
		while (t1.size == null || t2.size == null) {
			try {
				sleep(1);
			} catch (InterruptedException e) {
				System.err.println("Interrupted!");
			}
		}
		if (t1.size.longValue() != t2.size.longValue()) {
			t1.interrupt();
			t2.interrupt();
			System.out.println("Dateien haben nicht die selbe Größe");
		} else {
			counter = size = t1.size.longValue();
			boolean iden;
			while (counter > 0) {
//				System.out.println(100d-100d*counter/size);
				try {
					sleep(1);
				} catch (InterruptedException e) {
					System.err.println("Interrupted!");
				}
				while (t1.bytes.size() > 0 && t2.bytes.size() > 0) {
					iden=true;
					for(int i=0;i<t1.bytes.get(0).length;i++){
						if(t1.bytes.get(0)[i]!=t2.bytes.get(0)[i])
							iden=false;
					}
					if (iden) {
						counter -= t1.bytes.get(0).length;
						t1.lock.lock();
						t1.bytes.remove(0);
						t1.lock.unlock();
						t2.lock.lock();
						t2.bytes.remove(0);
						t2.lock.unlock();
//						System.out.println("Größe: "+t1.bytes.size()+" - "+t2.bytes.size());
					} else {
						t1.interrupt();
						t2.interrupt();
						System.out.println("Dateien unterscheiden sich beim "
								+ (size - counter + 1) + ". Array");
						return false;
					}
				}
			}
			return true;
		}
		return false;
	}

	public void run() {
		if (compare())
			System.out.println("Identisch");
		else
			System.out.println("Ungleich");
		System.out.println(System.currentTimeMillis());
	}

	public static void main(String[] args) {
		System.out.println(System.currentTimeMillis());
		File f1 = new File("")//Hier Pfad zu Datei 2 eintragen
		File f2 = new File("")//Hier Pfad zu Datei 2 eintragen
		Compare c = new Compare(f1, f2);
		c.start();
	}

}
 
> Exception in thread "Thread-0" java.lang.NullPointerException
> at compare.Compare.compare(Compare.java:41)


Zeile 41 nach Forum-Zählung ist
> iden=false;
ist das wirklich auch Zeile 41 in deiner Datei?
die package-Angabe fehlt auch,
bei sowas bitte extrem genau sein,

-------

wenn du die fragliche Zeile und das fragliche Objekt nicht erkennen kannst,
dann schreibe
try {

}catch(NullPointerException e) {

}

um den größeren problematischen Bereich und gib im Falle einer Exception wirklich jede Variable aus:
t1 ist: .. t1
t2 ist: ..
t1.bytes ist: ..

usw.

-------

bei mir läuft es,
vielleicht könntest du auch deine Testdateien hochladen (Anhang an Posting)
 
Zuletzt bearbeitet von einem Moderator:
Habe Dateien von einem GB benutzt. Aber der Fehler kam ja nicht immer an einer ganz bestimmten Stelle sondern auch bei manchen Durchläufen gar nicht. Also die Dateien produzieren den Fehler nicht.

Zeile 41 bei mir war: for(int i=0;i<t1.bytes.get(0).length;i++){
 
Dateien, bei denen der Fehler manchmal auftritt wären immer noch besser als meine Dateien, bei denen der Fehler (nach 10 Versuchen) nie auftritt 😉

aber ich habe dir umfassend erklärt, wie du den Fehler selber finden kannst:
das null-Objekt identifizieren
und dann noch prüfen, wann und wo es gesetzt wird,

selber kann ich leider keinen Fehler erkennen
 
Beispiel nach PM-Anfrage:
Java:
public class Test
{
    public static void main(String[] args)
    {
        Object o = null;
        Object o2 = null;
        for (int i = 0; i < 1000; i++)
        {
            try
            {
                o = (Math.random() < 0.004 ? null : "Test");
                o2 = (Math.random() < 0.004 ? null : "Test2");
                o.toString();
                o2.toString();

            }
            catch (NullPointerException e)
            {
                System.out.println("NPE in Durchgang " + i + ",   o ist hier: " + o + ", o2: " + o2);
            }
        }
    }
}
mögliche Ausgabe:
Code:
NPE in Durchgang 30,   o ist hier: null, o2: Test2
NPE in Durchgang 144,   o ist hier: Test, o2: null
NPE in Durchgang 419,   o ist hier: null, o2: Test2
NPE in Durchgang 439,   o ist hier: null, o2: Test2
NPE in Durchgang 489,   o ist hier: Test, o2: null
NPE in Durchgang 566,   o ist hier: Test, o2: null
NPE in Durchgang 856,   o ist hier: Test, o2: null
NPE in Durchgang 974,   o ist hier: Test, o2: null
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben