Dzieje się tak, ponieważ klasa BufferedInputStreamjest przeznaczona do użytku wielowątkowego.
Tutaj widzisz deklarację in, która jest umieszczona w klasie nadrzędnej FilterInputStream:
protected volatile InputStream in;
Ponieważ tak jest protected, jego wartość może zostać zmieniona przez dowolną podklasę FilterInputStream, w tym BufferedInputStreami jej podklasy. Ponadto jest zadeklarowana volatile, co oznacza, że jeśli którykolwiek wątek zmieni wartość zmiennej, ta zmiana zostanie natychmiast odzwierciedlona we wszystkich innych wątkach. Ta kombinacja jest zła, ponieważ oznacza, że klasa BufferedInputStreamnie może kontrolować ani wiedzieć, kiedy inzostanie zmieniona. W związku z tym wartość można nawet zmienić między sprawdzeniem wartości null a instrukcją return in BufferedInputStream::getInIfOpen, co skutecznie sprawia, że sprawdzanie wartości null jest bezużyteczne. Odczytując wartość intylko raz w celu buforowania jej w zmiennej lokalnej input, metoda BufferedInputStream::getInIfOpenjest zabezpieczona przed zmianami z innych wątków, ponieważ zmienne lokalne są zawsze własnością jednego wątku.
Oto przykład w programie BufferedInputStream::close, który ustawia inwartość null:
public void close() throws IOException {
byte[] buffer;
while ( (buffer = buf) != null) {
if (bufUpdater.compareAndSet(this, buffer, null)) {
InputStream input = in;
in = null;
if (input != null)
input.close();
return;
}
// Else retry in case a new buf was CASed in fill()
}
}
Jeśli BufferedInputStream::closejest wywoływana przez inny wątek podczas BufferedInputStream::getInIfOpenwykonywania, spowodowałoby to sytuację wyścigu opisaną powyżej.
Eclipsenie można wstrzymać debugera naifinstrukcji. Może być powodem tej zmiennej aliasu. Chciałem tylko to wyrzucić. Oczywiście spekuluję.