Releasing a direct buffer in java and possible pitfalls - java

we have the following piece of code:
long buffer = ((DirectBuffer) ByteBuffer.allocateDirect(256)).address();
It seems that there is no reference to direct buffer (as an object) on the thread's stack. So, it means that that object is phantom-reachable.
DirectByteBuffer becomes phantom-reachable.
Garbage collection is performed (in separate thread), DirectByteBuffer Java object is collected and an entry is added to the
ReferenceQueue.
Cleaner thread reaches this entry and runs the registered clean-up action (in this case, it's java.nio.DirectByteBuffer.Deallocator
object), this action finally frees the native memory.
The citation comes from: Java - When does direct buffer released?
So, it is possible that allocated memory that can be freed. However, we have a pointer to that, buffer of type long. Therefore it is possible that we've got SIGSEGV or something like that.
My question is:
Does it mean that we can hurt ourself using DirectBuffer in that manner?

Your assumption of danger here is correct, with a caveat.
The backing buffer of the direct buffer can be freed at any point after the containing ByteBuffer object becomes eligible for garbage collection (the exact moment the native memory is freed is implementation dependent, but typically it happens approximately when finalizer for the ByteBuffer runs).
From standard Java, this "dangling pointer" doesn't pose a real problem since it just a long like another other and you can't use unsafely. Of course if you pass it to some native or Unsafe code and try to use it as a pointer things can blow up.

Strictly speaking, not in the exact manner as you described because you just store a long value into a long variable. With this value you can do nothing harmful in Java.
As soon as you pass this to some native (C/C++) code and start using this as the address to write stuff to you get get yourself into problems as the object's memory may already have been reclaimed by the garbage collector.
Therefore all this access should be done in the native code (JNI) where you can use the native API to tell the virtual machine that your native code holds a reference (or not anymore). You can than use the address() function in your native code to get the address and use it.

Related

JNA memory clean up

As per documentation of JNA for Memory class, finalize() method needs to be called when memory need to release which has no longer reference. But in JNA example, it is mentioned that Memory object is getting released when it is out of scope.
// note: like Memory, StringArray will free the contiguous block of memory it copied the Strings into when the instance goes out of scope
The questions are :
Does it mean, Memory class object is calling finalize() internally when it is out of scope and frees the underlying native memory?
The StringArray class and Memory class are same in behavior w.r.t. memory management? and how?
Update:
As of JNA 5.12.1, JNA's Memory class no longer uses finalize() to free memory. It registers a Cleaner (custom internal class based on JDK9+ Cleaner implementation) which releases the native memory using a separate thread.
Along with this change, Memory was made Closeable (JDK6) which extends AutoCloseable in JDK7+ implementations. You may release the native memory simply by calling close() or better, allocating the memory in a try-with-resources block:
try (Memory m = new Memory(123)) {
// use m
}
Original answer:
To elaborate on Matthias Bläsing's answer in light of the specific questions asked, I want to add a few points:
You generally don't directly call finalize(). It is called by the JVM as part of the garbage collection process.
In Memory the finalize() method simply calls the dispose() method. If you really want to get rid of memory immediately this would be the preferred method to call. But dispose() is protected so you'd need to extend Memory to take advantage of this method if you really felt the need to clean up native memory allocations.
One such subclass you might consider is one that extends Closeable, where the close() method implementation calls dispose() from the superclass. Then you could, for example, use a try with resources block and have the native memory (resource) cleaned up at the end of the block. You'd still have the Java Object hanging around until GC, of course.
Note that freeing native memory comes with a processing cost, however, and unless you're really short on memory it doesn't gain much as you still have the Java heap memory associated with the object until it is GC'd. If you're that short of memory and going to that level of detail to control the timing of the native allocation cleanup, you probably want to go directly to the malloc() and free() calls yourself and control it at a higher level, perhaps recycling/reusing it...
You also asked about StringArray, but the closer parallel to Memory is the NativeString objects which are members of the array. And in fact their internal implementation is a StringMemory object which extends Memory so it would behave identically; that is, free() the native memory via dispose() via finalize() at the point the NativeString is garbage collected by the JVM.
The Memory implementation of JNA relies on the java garbage collection (GC). Java has no functions to explicitly acquire memory of objects, the memory necessary to hold object data is managed by the VM, allocated when an object is instantiated.
The GC is the process, that frees all memory not referenced anymore. All classes in Java can declare a method finalize, which will be called by the GC when the objects of that class are about to be cleared and gives objects the option to do some final cleanup work. In case of JNA this cleanup is releasing the native memory, that is allocated outside the GC controlled area.
It should be noted, that using finalize is being deprecated and should not be done anymore, but switch to alternative methods also means introducing slightly different behavior, which is one of the reasons, that JNA still relies on GC for cleanup.

Is there any way that I can free up memory in the java code that is generated to bind C code via JNI/JNA?

I am using a java library that use JNA to bind to the original C library (That library is called Leptonica). I encountered a situation where free(data) has to be called in the C code to free up the memory. But, is there any function in java that I can free up the memory?
In the C code
void ImageData::SetPixInternal(Pix* pix, GenericVector<char>* image_data) {
l_uint8* data;
size_t size;
pixWriteMem(&data, &size, pix, IFF_PNG);
pixDestroy(&pix);
image_data->init_to_size(size, 0);
memcpy(&(*image_data)[0], data, size);
free(data);
}
The function pixWriteMem() will create and allocate memory to the "data", which you need to do free(data) to free up the memory later.
In Java code, I can only access pixWriteMem(), not the SetPixInternal(), so I have no way to free up the "data", which create a memory leak.
The other comments and answers here all seem to be suggesting that you just rely on the garbage collector or tell the garbage collector to run. That is not the correct answer for memory allocated in C and being used in Java via JNI.
It looks like that execution() does free the memory. The last line you show us is free(data). Still, to answer your the question as you asked it, the answer is "not directly." If you have the ability to add to the C code, you could create another C function which frees the data and then call that using JNI. Perhaps there is more that we are not seeing which relates better to your concern about the memory leak?
Also, be careful about freeing memory allocated by a library you are using. You should make sure that the library doesn't still need it and is leaking it before you go trying to free it.
And now back to memory management in general...
Java is indeed a garbage-collected language. This means that you do not specifically delete objects. Instead, you make sure there are no references to it, then the garbage collector takes care of the memory management. This does not mean that Java is free from memory leaks, as there are ways to accidentally keep a reference hanging around such that the object never gets garbage collected. If you have a situation like this, you might want to read up on the different kinds of references in Java (strong/weak/etc.).
Again, this is not the problem here. This is a C/Java hybrid, and the code in question is in C being called by Java. In C, you allocate the memory you want to use and then you need to free the memory yourself when you are done with it. Even if the C code is being run by Java via the JNI, you are still responsible for your own memory. You cannot just malloc() a bunch of memory and expect the Java garbage collector to know when to clean it up. Hence the OP's question.
If you need to add the functionality yourself to do a free, even without the source code for the C part, you might still be able to write your own C interface for freeing the memory if you have access to the pointer to the memory in question. You could write basically a tiny library that just frees the memory for you, make the JNI interface for it, and pass the pointer to that. If you go this route then, depending on your OS, you might need to guarantee that your tiny free library's native code is running in the same process as the rest of the native code, or if not the same process then at least that the process you run it from has write access to the memory owned by the other code's process; this memory/process issue is probably not an issue in your case, but I'm throwing it out there for completeness.
In Java code, I can only access createData(), not the excution(), so I have no way to free up the "data", which create a memory leak.
Then it sucks to be you.
Seriously, if you want to free memory allocated by a native method and not freed before that method returns, then you need to maintain a handle of some kind on that memory and later pass it to another native method that will free the memory. If you do not presently have such a native method available, then you'll need to create one.
The other question is how to ensure that the needed native method is invoked. Relying on users to invoke it, directly or indirectly, leaves you open to memory leaks should users fail to do so. There are two main ways to solve that problem:
Give your class a finalizer that ensures the memory is freed. This is the core use case for finalizers, but even so, there are good reasons to prefer to avoid writing them. The other alternative is to
Create a reference object (SoftReference, WeakReference, or PhantomReference), associate the reference with a mechanism for freeing the native-allocated memory belonging to the referenced Java object (but not via that object), and register that object with a reference queue. The reference will be enqueued when the object is GC'd, at which point you know to free the native-allocated memory.
That does not necessarily mean that you should prevent users from explicitly freeing the memory, for with enough bookkeeping you can track whether anything still needs to be freed at any given time. Allowing users to release resources explicitly may help keep your overall resource usage lower. But if you want to avoid memory leaks then you need to have a fallback.
No there is no function like C's free() in Java. But you can suggest garbage collector to run by calling System.gc()

Java - Garbage collection

I found very less understanding in web about java gc. I request you to answer or correct my questions possibly by providing some reliable sources. I hope this post will be helpful to many people like me.
Q1) Please correct or improve my understanding about garbage collection:
gc will automatically be called by jvm during the execution of an application. Calling gc explicitly may only make the gc happen little early than it may happen without explicit call. JVM may call gc at irregular intervals, probably frequently.
gc may collect an object when (i) It's not being referenced by. and (ii) It's not referencing to.
but before destroying an object it will call finalize method of that object class where it can execute some code, normally cleanup operations wrt that object. Finalize method will be called only once per one object. If object is saved by finalize method at the first time, next time it can't escape from death.
If there are memory blocks allocated but not reclaimed due to exceptions/thread abortions they are called as memory leaks which may result in scarcity of memory in the system. OS may tackle with it but not in expected response time of running applications which need memory immediately on demand in which case applications may halt/hang with insufficient memory resource error dumps.
Q2) Garbage collection will only be for heap? ( That means, only to collect unreferenced objects? ) If so, what about static variables/constants/objects which are stored in class-method area?
Q3) How can we make a java object imperishable? Meaning... No matter what happens in the application, the object should not be reclaimed by gc through out the application life. Is it possible?
Q4) I am guessing there will be some occasions in program where gc may go wrong...meaning reclaim an object which shouldn't reclaim because it may gonna be used but gc didn't see the future use. Do such mistakes possible about what programmer should suspect or take care of this auto gc provided by java?
There are many wrong facts in your understanding.
Exceptions and thread abortions don't cause memory leaks. Memory leaks only happen when you keep references to objects for too long. A memory leak is thus caused by a bug in your code (or in a library that you're using), but not by the JVM.
A GC collects objects when the object is not reachable from any chain of references from a root object (variable on a thread stack or static variable). An object which still has references to other objects is not a problem at all. An object which is still referenced by other objects, but not reachable anymore is eligible to GC as well. That's what allows building complex graphs of objects with cyclic references without any problem.
Calling gc explicitly may cause GC to execute immediately, later, or not have any effect.
If the GC was buggy, it would be useless. It's not buggy. If it reclaims an object, then this object is not used anymore by the application.
To make an object not perishable, just make sure it's always reachable through a chain of references from a root. It could b referenced from a static variable, or by a local variable from a thread that never ends.
Q1 and Q2 I will try explaining how the variables get stored in JAVA, thus u can see how GC works.
If you declare
Object a ;
you have created a pointer to an object. It gets stored in the STACK but not in the HEAP.
If you later say
a = new Object();
The object gets placed into the HEAP. The pointer in the stack points to the place in the heap where your object is.
Further more, if you later write
a = null;
you have set the pointer in the STACK to nowhere. GC will destroy the item in the HEAP. Please note that the pointer is still in the STACK. Now if that all was a local variable ( inside function ) and the function exits at some time, the pointer in the STACK will be removed too, if it points at something in the heap, it gets removed too.
However if the variable belongs to an object that is let's say instance variable, the pointer will stay until the object itself exists - the object has memory allocated in the HEAP.
I hope you see what's going on here. It's a bit like chain reaction.
Q3 - You can make an object last until the program exits by making it STATIC.
About Q4 I am not quite sure.
On the topic of 4) the only time the GC can reclaim object you don't expect is when you play with References such as WeakReference and SoftReference. These wrapper allow the GC to clean up objects either on a collection, or when memory is low respectively. While this sounds like a great idea for caching it often doesn't behave quite the way you would expect and they are not as useful as they first appear.
Q1) Please correct or improve my understanding about garbage collection
(Most of your assumptions are correct)
A big problem in programming was memory management . At the begining the developers were responsible for its allocation
and release manually, which led to many bugs and memory leaks. Today , in
all modern platforms , including Java , the memory management is done by GC algorithms.
The Garbage Collector ( GC ) is a major component of the JVM and responsible
by releasing the memory that is no longer being used. When the
application releases all references to an object, it can be collected by the GC at any time, but the time is not determined. It depends entirely on the algorithm the garbage collector . In general , the GC will not make collections for each object. It will wait to release
blocks of objects, for optimization.
JVM may call gc at irregular intervals, probably frequently. (realy depends on the algorithm)
Q2) Garbage collection will only be for heap?
NO. The PermGen is out of the HEAP. Is where Class objects, Method, and the pool of strigs are allocated.
This space is also collected by the GC (when the FullGC is executed).
Q3) How can we make a java object imperishable?
If you have an objected that is never dereferenced, then it will always exist. (For example, in a web app, you add an object
in the applicationContext and you never take it from there. It will exist for the entire application, until it is shutdown).
Q4) Do such mistakes possible about what programmer should suspect or take care of this auto gc provided by java?
You should be aware of which GC algorithm your JVM is using, and choose one that best suit your needs.
(you can choose UseParallelGC / UseSerialGC / UseParallelOldGC / UseConcMarkSweepGC)
See here :
http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html
Your understanding seem to be right except that OS doesn't do anything to reclaim the memory. When jvm starts you provide with the max heap that program can use and once that is completely used you will get an Out of Memory Error if there is a leak in the system. I also don't think that if you save your object in finalize it will cleaned up next time for sure. I think if you make finalize to reference your object back then it might never be cleaned up, i am not sure though.
The class and other static information goes to perm gen space. Once the program is restarted this area gets cleared up, but its possible to keep an handle of these information leaking which might result into Out of memory in perm gen space.
Make your object global and it will stay forever
GC has a small pause time where it rescues the objects which have been reference back. So NO you don't have to worry about GC claiming objects that are not supposed to.

Preventing native memory leak by customizing garbage collector?

Let's say I'm writing an API in java that refers to some native C libraries, that requires destructors to be called explicitly. If the destructors are not called, I run out of native memory.
Is there a way to protect users of my API from calling the destructors explicitly, by having the garbage collector call the destructors somehow? (perhaps based on some estimate I make of the size of the used native memory?)
I know Java doesn't have its garbage collector as part of the Java API, but perhaps there is some way to get this implemented?
One alternative if you have control over creation of your objects is to reference them with a WeakReference using the constructor that takes a ReferenceQueue. When they get out of scope, the Reference will be queued and you can have your own thread polling the queue and call some clean up function.
Why?
Well, it is slightly more efficient than adding finalizers to your classes (because it forces the gc to do some special handling of them).
Edit: The following two (variations of the same article) describes it:
http://java.sun.com/developer/technicalArticles/javase/finalization/
http://www.devx.com/Java/Article/30192
Peter Lawrey has a very good point when he says:
Even so, waiting for the GC to cleanup can be inefficient and you may want to expose a means of explicitly cleaning up the resource if its required.
Whenever you can assume your users to be on Java7, take a look at java.lang.AutoCloseable as it will help them do that automatically when using the new try-with-resources.
In addition to use finalize(), you may need to trigger a GC if you run out of resources to make the call, however a GC hasn't been run.
The ByteBuffer.allocateDirect() has this issue. It need the GC to clean up its ByteBuffers, However, you can reach your maximum direct memory before a GC is triggered, so the code has to detect this and triggers a System.gc() explicitly.
Even so, waiting for the GC to cleanup can be inefficient and you may want to expose a means of explicitly cleaning up the resource if its required.
Garbage collector will call finalize() of Java objects when the Java object is about to be GCd, and inside the finalize, you could call the destructor. Just make a new Java object for every destructor that needs to be called, and keep reference to that Java object until when you want to call the destructor.
In practice, finalize() will be called sooner or later (even though technically Java makes no guarantee that any particular object will ever be GCd). The only exception is if the object is still around when the process is shutting down: then it may indeed never get GCd.

GC.AddMemoryPressure equivalent in Java

Project: Java, JNI (C++), Android.
I'm going to manage native C++ object's lifetime by creating a managed wrapper class, which will hold a pointer to the native object (as a long member) and will delete the native object in it's overridden finalize() method. See this question for details.
The C++ object does not consume other types of resources, only memory. The memory footprint of the object is not extremely high, but it is essentially higher than 64 bit of a long in Java. Is there any way to tell Java's GC, that my wrapper is responsible for more than just a long value, and it's not a good idea to create millions of such objects before running garbage collection? In .NET there is a GC's AddMemoryPressure() method, which is there for exactly this purpose. Is there an equivalent in Java?
After some more googling, I've found a good article from IBM Research Center.
Briefly, they recommend using Java heap instead of native heap for native objects. This way memory pressure on JVM garbage collector is more realistic for the native objects, referenced from Java code through handles.
To achieve this, one needs to override the default C++ heap allocation and deallocation functions: operator new and operator delete. In the operator new, if JVM is available (JNI_OnLoad has been already called), then the one calls NewByteArray and GetByteArrayElements, which returns the allocated memory needed. To protect the created ByteArray from being garbage collected, the one also need to create a NewGlobalRef to it, and store it e.g. in the same allocated memory block. In this case, we need to allocate as much memory as requested, plus the memory for the references. In the operator delete, the one needs to DeleteGlobalRef and ReleaseByteArrayElements. In case JVM is not available, the one uses native malloc and free functions instead.
I believe that native memory is allocated outside the scope of Java's heap size. Meaning, you don't have to worry about your allocation taking memory away from the value you reserved using -Xmx<size>.
That being said, you could use ByteBuffer.allocateDirect() to allocate a buffer and GetDirectBufferAddress to access it from your native code. You can control the size of the direct memory heap using -XX:MaxDirectMemorySize=<size>

Categories