I have several times heard that one should not rely on finalizers (that is, code invoked after some object becomes garbage) to reclaim external resources (file descriptors, temporary files, etc.), on the grounds that there is no guarantee they will be promptly reclaimed and therefore one might run out.
Certainly for resources whose use has semantic significance to an outside system (e.g. a network connection or a locked file) or if there is a potential shortage of resources affecting other processes (e.g. free disk space), one should free them promptly whenever possible. (Finalizers are still important for error recovery unless you’re programming completely without nonlocal exits and extremely carefully, in which case you’re probably writing C and don’t have finalizers.)
But if the concern is for limited internal resources (most prominently, the limit on number of open file descriptors), and the process is entirely managed by the GC, would it not suffice to force a garbage collection and retry in the event that opening a file fails due to lack of file descriptors, just as if running out of memory while allocating memory?