Reference counting in Java

Viewed 7749

I have a system that keeps running out of disk space because that garbage collector doesn't free the objects that hold the file handles fast enough. (Files are created and deleted all the time, but since the process still has an open file handle, the OS keeps it on the disk).

The objects are shared, so a simple try { ... } finally { close(); } will not do.

It seems to me that my best option is to implement reference counting on the objects, and close the file handles when the reference count goes to 0. However, I'm reluctant to implement it all by myself, as I suspect there are subtle issues with regards to concurrency.

Sadly, googling for "reference counting in java" doesn't bring any useful results. So my question is: are there any resources (articles, sample code, libraries) that can help implement reference counting?

3 Answers

Sadly, googling for "reference counting in java" doesn't bring any useful results.

Sadly, this continues to be true 8 years later.

But, no longer! I've pulled out Netty's reference counting bits, polished them off quite a bit, and made them into a separate library, almson-refcount.

The basic reference counting functionality is simple and straightforward. There is a single base class, ReferenceCountedObject. It has a single overrideable method, destroy. It provides retain and release which manage an internal reference counter using a thread-safe and efficient AtomicFieldUpdater. release will call destroy on the same thread, and because of memory ordering semantics between different calls to release, you shouldn't need to worry about the thread-safety of your destroy even in a multi-threaded application. The class implements AutoCloseable and provides a method close which simply calls release. This allows it to be used in try-with-resources.

There is no finalization mechanism which tries to call destroy in case you forget to call release! Finalization presents big challenges, including concurrency issues and even premature finalization, especially in the general case. (If you insist on having finalizers, you can still use them or the higher-performance java.lang.ref.Cleaner.)

Instead, there is a clever leak detection system. It uses a similar mechanism to finalization. Because its only responsibility is detecting leaks and recording debugging info, there is nothing you need to do to make it work correctly (except turn it on).

The main things changed vs Netty are:

  • An actual, usable base class for all of your reference-counted objects.
  • A more elegant interface with fewer methods.
  • Simpler, cleaner code with less cruft.
  • Improvements to the documentation, presets, and output of the leak detector.
Related