Возможно, следующая тестовая программа прояснит это:
Field fd = FileDescriptor.class.getDeclaredField("fd");
fd.setAccessible(true);
System.out.println("stdin: "+fd.get(FileDescriptor.in));
System.out.println("stdout: "+fd.get(FileDescriptor.out));
System.out.println("stderr: "+fd.get(FileDescriptor.err));
stdin: 0
stdout: 1
stderr: 2
Ideone , обратите внимание, что для JDK 8 это относится к Unix-подобным системамonly
Другими словами, вы смотрите на потоки файлов, инкапсулированные в System.in
и System.out
, и, конечно, они никогда не будут собираться мусором, и обычно вы тоже этого не делаетевызовите close()
для них.
Финализация не поддерживает какой-либо отказ, поэтому любой экземпляр класса с «нетривиальным finalize()
методом» получит ссылку на финализатор при построении, дажекогда создатель знает, что объект никогда не будет завершен.
В самых последних версиях JDK для этой цели используется Cleaner
, что позволяет не регистрировать очиститель при FileInputStream
или FileOutputStream
создается с использованием существующего FileDescriptor
, как в случае с stdin и stdout.Он также позволяет немедленную очистку и, следовательно, отмену регистрации в методе close()
, не требуя какой-либо посмертной очистки для программ с хорошим поведением.
Так что в новейших версиях Java вы должны видеть только очистители для реально используемых потоковна свалке.