Hi, On 09/03/2014 12:48 PM, Stanimir Simeonoff wrote: > Hi Andrew, > > On Wed, Sep 3, 2014 at 12:58 PM, Andrew Haley <[email protected]> wrote: > >> On 03/09/14 01:15, Stanimir Simeonoff wrote: >> >>> Like David Lloyd mentioned finalize() can be invoked concurrently to >>> some methods (if there is no reachability to 'this'). OTOH I see >>> finalize useful for managing native resources mostly and possibly >>> stopping (signaling) threads left unmanaged. In that particular case >>> synchronization is a must, so it comes naturally. >> >> But finalize isn't useful for managing native resources because >> finalizers may or may not run, as you note. People will test their >> programs with one implementation then discover, when their programs >> are deployed, that they sometimes mysteriously fail. In particular, >> you might run out of file handles. >> > I meant cleaning up rather than managing per se. To make it clear: > finalization is no substitute for proper lifecycle - anything that has > open() should have a following up close(), otherwise it's a bug. > Finalization still helps as safenet vs leaving native resources totally > unallocated and leaking.
But it doesn't help: as I discovered when trying to debug the PKCS1 crypto provider, long-lived objects move into the old gen, and until there is a real shortage of heap memory, there is no old gen collection, so native memory becomes exhausted. It is impossible to do it correctly; and we programmers comfort ourselves with the idea that we're doing our best. > Yet, finalizers have to run somehow since the direct (and mapped) > buffers very heavily rely on them. The direct/mapped buffers are > ones that don't have proper lifecycle, esp. the mapped ones > The latter don't offer munmap. True enough, but I suspect we only get away with it because it's not always necessary to munmap a file: if it's not in use it'll all be swapped out of memory, and the only significant resource leak will be a file handle. On 64-bit systems we still have plenty of address space for this. For now, anyway. I admit that it's quite hard to solve the MappedByteBuffer.close() problem efficiently while still providing security guarantees. To some extent this discussion comes down to personal preference: I don't think that incorrect solutions to the problem of resource management help, because they give a false sense of security. And I think some people are in denial about finalization. On a more positive note, I've had an idea. How about we change the generational collectors so that no object with a finalizer is ever moved into the old gen? this seems reasonable to me, given that the primary purpose of finalizers is to free resources. Andrew.
