为什么Java有GC还需要自己来关闭某些资源?

比如socket和io。 我知道GC只能关闭new在堆上的对象,但是类似于InputStream那些对象不也是new出来的吗? 还有一点疑问就是都说G…
关注者
177
被浏览
26,217

12 个回答

1、为什么要自己来关闭某些资源?

因为GC只管内存不管别的资源。假如有内存以外的其它资源依附在Java对象上,如native memory(DirectByteBuffer)、file(FileInputStream)之类,那当然自己关闭最合适。

为了“避免”程序员忘了自己释放那些资源,Java提供了finalizer、PhantomReference之类的机制来让程序员向GC注册“自动回调释放资源”的功能。但GC回调它们的时机不确定,所以只应该作为最后手段来使用,主要手段还是自己关闭最好。

放个传送门:

Java使用JNI调用C写的库时,使用malloc分配的内存是由谁来管理? - RednaxelaFX 的回答

2、GC回收怎样算不确定?

JVM规范其实只要求所有活着的对象要活着,并没有说死掉的对象要咋处理。甚至特意指明“不限制如何实现自动内存管理”。

所以符合规范的JVM只要保证活对象是活的就好了,这是确定的。

而不确定的是GC何时被唤起,死对象何时被收集,有finalizer的对象的finalizer何时被调用、被PhantomReference引用的对象何时通知PhantomReference之类。

虽然执行时机不确定,但合理的GC实现通常会保证“死掉的对象终将被收集”,所以算不上有内存泄漏。

当年 Sun 被「一流企业做标准」的神话深深荼毒,造成话不会好好说。写标准的时候什么都模棱两可,美其名曰 vendor-specific behavior。好像多大度,大家风范,其实屁用没有。

结果就是 GC 的行为不确定,System.gc( ) 仅仅是个 hint。Finalizer 也不保证被调用。然后就只好在语言上打补丁。

其实就像 Lua 那样清晰明确的 GC,collectgarbage ( ) 肯定回收,__gc meta-function 确定被调用。有什么难的?