11

I have a region of memory wrapped with JNI NewDirectByteBuffer. I would like to run free/release code in the cleaner of the ByteBuffer. Is there a way to do this or do I have to offer a custom free method that the user will have to call with the ByteBuffer?

Edit

To clarify, I allocated the memory myself and called NewDirectByteBuffer myself. I would like to know how I should coordinate the clean up with the cleaner.

Philippe Marschall
  • 4,452
  • 1
  • 34
  • 52
  • 2
    In Java 8's DirectByteBuffer you could call the Cleaner.clean() method though it's not a public API, so use knowing it's not portable. – Peter Lawrey Oct 20 '17 at 08:17
  • @PeterLawrey And that will call free() always? What if I need a other clean up function than free()? – Philippe Marschall Oct 20 '17 at 11:35
  • It will do whatever is appropriate to free the memory. You don't have any evidence that that involves calling `free()`. – user207421 Oct 23 '17 at 08:19
  • @EJP how does it know what is appropriate? `NewDirectByteBuffer` only takes a pointer and a length. There is no way to pass a free function pointer. – Philippe Marschall Oct 23 '17 at 10:06
  • @PhilippeMarschall Because the code is written by the same guys that wrote the code that allocated it. I don't know why you're so fixated on the `free()` function. – user207421 Oct 23 '17 at 11:13
  • @EJP I am the guy that the wrote the code who allocated the memory and I certainly did not write any part of the JVM. I am so fixated on the `fee()` function because I'm the one who allocated the memory in the first place. It is my responsibility to see it gets released. – Philippe Marschall Oct 23 '17 at 11:52
  • So, you create a direct byte buffer object in C, and let JVM control its lifecycle? Maybe you should extend DirectByteBuffer and override the clean method? – Alex Cohn Nov 01 '17 at 05:11
  • @AlexCohn DirectByteBuffer is package scoped and can not be extended. – Philippe Marschall Nov 26 '18 at 13:23
  • You are right, this [may be trickier](https://stackoverflow.com/a/26777380/192373) than I thought. – Alex Cohn Nov 26 '18 at 15:15

1 Answers1

1

You use JNI.newDirectByteBuffer, you can and you should free the memory manually, and do you clean up work at the same time.

If you want it clean up automatically, what you need is monitor the object's life cycle. And if you only want to work with API and don't use reflection, you can use a PhantomReference with ReferenceQueue, and create a demon thread to polling the queue. Do your clean up work once the reference be in the reference queue.

Dean Xu
  • 4,438
  • 1
  • 17
  • 44
  • Please read the question. I am not using `ByteBuffer.allocateDirect`, I am using `NewDirectByteBuffer` from JNI. Because `NewDirectByteBuffer` does not take a free function pointer the JVM has no way of knowing how to free the memory region. `free` may or may not be appropriate. – Philippe Marschall Oct 31 '17 at 06:10
  • `NewDirectByteBuffer ` returns a jobject which is `DirectByteBuffer` type. So the solution is the same, but from change the cleaner to create a cleaner. – Dean Xu Oct 31 '17 at 06:35
  • So how do you control which free function is called? – Philippe Marschall Oct 31 '17 at 06:46
  • @PhilippeMarschall I have edited my answer. Because I have no JNI environment, I use reflection to mock `newDirectByteBuffer`. And use `Unsafe` like `DirectByteBuffer` do. The core idea is same, do the clean up work when the object collected by gc. – Dean Xu Oct 31 '17 at 06:53
  • So you're saying there is no API or supported way to do this? Or any way that works reliably across Java versions or JVMs? Or even works with Java 9 and module checks enforced. – Philippe Marschall Oct 31 '17 at 09:24