views:

158

answers:

1

I'm hunting a memory error in an application, and it seems to be related to the byte[] buffers generated by ServerSocketChannel.accept(). According to jvisualvm, of the 505 megs in use by the application, over 90% of the memory is being used by byte[] arrays. Tracking it further, there are 68k+ instances of byte[] and by far the most common size is 16681.

I've done a random sampling of these byte arrays, and they all without exception have been related to either an InputRecord or an OutputRecord. If I follow all the references, I can't find any that don't lead back to a Finalizer which, in my limited understanding, means that the object is ready to be garbage-collected but it hasn't for some reason or other.

I wish I could attach a screen capture of the jvisualvm output. Anyway, the referent objects include:

  • InputRecord
  • AppInputStream
  • SSLSocketImpl
  • SocketInputStream
  • SocksSocketImpl
  • SocketOutputStream
  • AppOutputStream
  • DelegateHttpsURLConnection
  • HttpsURLConnectionImpl

This only seems to happen to customers using Apple's VM. Anybody have any idea why these buffers aren't getting garbage collected? Am I reading the heap profile wrong? Hacks or workarounds?

TIA, Dan

+1  A: 

finalize is called sometime after the object has been spotted by the garbage collector. The Sun implementation is mixed up with java.lang.ref. Closing resources properly should release their memory. If objects with finalize fail to null out references to buffers when they are closed, then those buffers will hang around until the relevant GC after the finaliser has executed.

Generally there is only one finaliser thread, although the spec allows many. If this is blocked due to a blocking operation, an inappropriate held lock or other reason, then GC of finalisable objects is going to be held up. I suggest checking the finaliser thread in visualvm to see if it is blocked.

Tom Hawtin - tackline