How to prevent an object from getting garbage collected?
Are there any approaches by finalize or phantom reference or any other approaches?
I was asked this
The best way is to use Unsafe, although ByteBuffer
might be a possible workaround for some cases.
Also search for the keyword "off-heap" memory.
Unsafe
Advantages over ByteBuffer
:
It is not however easy to get working. The method is described in the following articles:
They all consist of the following steps:
we need a sizeof
operator, which Unsafe does not have. How to make one was asked at: In Java, what is the best way to determine the size of an object?. The best options is likely the instrument
API, but that requires you to create a Jar and use special command line options...
once we have sizeof
, allocate enough memory with Unsafe#allocateMemory
, which is basically a malloc
and returns an address
create a regular on heap object, copy it to the allocated memory with Unsafe#copyMemory
. To do this, you need to the address of the on-heap object, and the size of the object
set an Object
to point to the allocated memory, then cast the Object
to your class.
It does not seem possible to set the address of a variable directly with Unsafe, so we need to wrap the object into an array or wrapper object, and use Unsafe#arrayBaseOffset
or Unsafe#objectFieldOffset
.
once you are done, free the allocated memory with freeMemory
If I ever get this to not segfault I will post an example :-)
ByteBuffer
Advantages over Unsafe:
JLS says:
The contents of direct buffers may reside outside of the normal garbage-collected heap.
Example of usage with primitives:
ByteBuffer bb = ByteBuffer.allocateDirect(8);
bb.putInt(0, 1);
bb.putInt(4, 2);
assert bb.getInt(0) == 1;
assert bb.getInt(4) == 2;
// Bound chekcs are done.
boolean fail = false;
try {
bb.getInt(8);
} catch(IndexOutOfBoundsException e) {
fail = true;
}
assert fail;
Related threads: