I've got an Android project that heavily uses C++ JNI shared objects. In fact, I've got a Java object that manages resources allocated from JNI calls. On that particular Java object, I'm using a finalize() call to handle the freeing of those native resources when the object gets destroyed.
This all seems to work and I don't see any memory leaks, however, I've heard that you using Java finalizers is frowned upon (Effective java, 2nd edition page 27. Item 7: Avoid finalizers, etc.). Are there cases, such as the one I've described above, where using finalize() is appropriate? I'm not sure what else to do to ensure that those native resources get cleaned up.
I believe your case is one of the few where it's appropriate to use a finalizer.
Related
If you are running code that makes calls to a native library in Java, what is the usual way of freeing memory allocated by these libraries when the memory allocation should last for the lifetime of the object? In C++, I would use destructors, but Java never really had those and has them even less now.
The specific case I'm most interested in is JOCL, where I have an object that wraps a compiled OpenCL kernel and all of the arguments thereto that are always the same. Structures representing the compiled kernel and the arguments are all allocated on the library side, and JOCL provides a method clReleaseMemObject that you call to decrement a reference counter indicating when the object should be deleted (note that this is a bit different from directly freeing the memory, but I don't think substantially so in this case).
I presume that if the object is still around when the program terminates, everything is cleaned up by the OS, but I'm not so sure about about objects created in a thread. So:
If you want the native memory deallocated when the object is garbage collected, is there a proper place to call the method that releases this memory?
If the object is one that will last for the duration of a thread, is there a proper place to make this call, or is this even necessary?
What you can do is use a Cleaner. This is a more official API in Java 9 but is available in Java 1.4+.
Essentially you give it a Runnable to execute when the resource is cleaned up.
One advantage of using a Cleaner is you can call it to clean up deterministically, but if you forget or fail to do so, the GC will call it after it runs.
There isn't a safe way to clean up an object when a thread dies as the Thread object can live for the life of the program even if dead. A simpler approach is to clean up as you know it is not needed or after the GC determines it is not required.
Another approach is to use a reference queue and a background thread. It's not as elegant but works across Java 8 and later versions.
To use exit(0) in C is not a good practice, if there are alternatives, since it does not free resources for example. But to use System.exit(0) in Java - how is it here? Could one trust the garbage collector in this context?
C language:
exit(0);
Java:
System.exit(0)
But to use System.exit(0) in java - how is it here? Could one trust the garbage-collector in this context?
When you call System.exit in Java, the garbage collector is not normally run1. However, in any JVM that I've ever heard of, there is something else that reclaims all of the objects that were allocated. (Typically it is handled at the operating system level.)
The fact that the GC doesn't run is only significant if you are relying on object finalizers to so something important before the JVM terminates.
Hypothetically, if your Java application used JNI (etc) to call native methods, then those methods could access system resources that might be problematic. However:
As a general rule the operating system does take care of such things. At least it does for modern versions of Linux and UNIX, AFAIK.
The garbage collector has no knowledge of those resources anyway. If the OS can't reclaim them, then the Java garbage collector won't help.
If you did need to clean up such resources acquired by a Java program (via native code) then the best approach would be to implement the cleanup in native code methods, and use a "shutdown hook" to run them. The shutdown hooks will be run if you call System.exit.
1 - A garbage collection will be performed on JVM exit if you have previously called runFinalizersOnExit(true). However, this is a deprecated method. The Oracle site explains it like this:
Q: Why is Runtime.runFinalizersOnExit deprecated?
A: Because it is inherently unsafe. It may result in finalizers being called on live objects while other threads are concurrently manipulating those objects, resulting in erratic behavior or deadlock. While this problem could be prevented if the class whose objects are being finalized were coded to "defend against" this call, most programmers do not defend against it. They assume that an object is dead at the time that its finalizer is called.
Further, the call is not "thread-safe" in the sense that it sets a VM-global flag. This forces every class with a finalizer to defend against the finalization of live objects!
In short, this is a dangerous approach, and it won't directly deal with the kind of resources that the OP is worried about.
Think of it like this. In C, you are building your source code into a binary file that will execute on it's own only conforming to the rules of logical programming and the rules set by your OS. The OS however does not manage your memory for you. It handles events and sends information to the hardware that tell it how to run, nothing more, nothing less. In java, all code is compiled into java's own bytecode. Upon execution it does not actually at any time communicate to the OS. The virtual machine designed to run that bytecode is what does the talking. When you call System.exit (0), you are telling the virtual machine that the app you are running is coming to a halt, from there the machine handles IT'S OWN MEMORY which just so happens to include anything you did not already remove via the garbage collector but only if the VM is exiting as well. Hope that helps
Is there any way to find that a specific object is still in the memory or not? For example I have a JFrame called GuiSearch. When I called some method it will be disposed. I want to find is it still in the memory or disposed. I am new to java. Please help me.
Edit: What I want to do is find that the specific object is still in the memory or not and if it is in the memory, I want to call a method and if it is not, call another method.
I assume disposed cleans up resources hidden by the object.
As long as you have a reference to it, the object is still in memory. Depending on what disposed does, you could have an object which is "disposed" and still in be memory as you still have a reference to it.
I am assuming you want to do this for debugging and not via the code. If that's the case, what you want to is dump the heap memory and check it via tools such as Eclipse Memory Analyzer.
This is a bad programming practice and you never do it. To see objects in memory you can use jvisualvm - which comes Sun JDK it self. This provides a visual interface for viewing detailed information about Java application while they are running on a Java Virtual Machine.
I'm using Tomcat and after stopping my web application there's still a reference to the classloader instance of my web application.
With the consequence that a notable amount of memory (mostly related to static data) will not be freed. Sooner or later this results in an OutOfMemoryError.
I took a heap dump and I realized that its held by a JNI global reference which prevents that the classloader will be garbage collected.
My application does not use JNI. I am also not using the Apache Tomcat Native Library. I am using a Sun/Oracle JDK.
I'd like to track down the cause/origin of this global reference.
(My guess is that the JVM internally references the classloader - but why/where?).
Question:
Which approaches/toolsets exists to achieve this?
UPDATE
It seems that bestsss is right and the JNI global references has been introduced by the jvm debug mode. This helped me out but it does not answer the question so I am still curious to get an answer to the question which might be helpful in the future.
Besides the obvious case: Threads, there is one more:
Are you using your application in debug mode?
The JVM does not hold references to any classloader besides the system one, but it doesn't concern you. The rest of JNI references are either Threads or just debug held objects (provided you don't use JNI and lock the objects down yourself).
JNI references are just roots, edit your answer and post what exactly objects are held by those references.
The first thing i'd do is run with -Xcheck:jni on and see if it comes up with anything. I wouldn't expect it to; it doesn't sound there's anything weird happening with JNI, just incorrect use being made of it. However, it's good to make sure of that.
If you're on a Sun JVM, i think you can do -XX:TraceJNICalls to get an overwhelming listing of JNI calls as they happen. That should let you get an idea of what calls are being made, and from there work towards what is making them, and why this is causing a problem.
JRockit mission control: http://download.oracle.com/docs/cd/E13150_01/jrockit_jvm/jrockit/tools/index.html
A nice GUI tool that should help you find it pretty quick.
You could try jstack.
Maybe one of the listed stacktraces will show you the origin of the global reference.
This question already has answers here:
Why would you ever implement finalize()?
(21 answers)
Closed 5 years ago.
This is mostly out of curiosity.
I was wandering if anyone has encountered any good usage for Object.finalize() except for debugging/logging/profiling purposes ?
If you haven't encountered any what would you say a good usage would be ?
If your Java object uses JNI to instruct native code to allocate native memory, you need to use finalize to make sure it gets freed.
Late to the party here but thought I would still chime in:
One of the best uses I have found for finalizers is to call explicit termination methods which, for what ever reason, were not called. When this occurs, we also log the issue because it is a BUG!
Because:
There is no guarantee that finalizers will be executed promptly (or technically at all), per the language specification
Execution is largely dependent on the JVM implementation
Execution can sometimes be delayed if the GC has a lower thread priority
This leaves only a handful of tasks that they can address without much risk.
close external connections (db, socket etc)
close open files. may be even try to write some additional information.
logging
if this class runs external processes that should exist only while object exists you can try to kill them here.
But it is just a fallback that is used is "normal" mechanism did not work. Normal mechanism should be initiated explicitly.
Release resources that should be released manually in normal circumstances, but were not released for some reason. Perhaps with write a warning to the log.
I use it to write back data to a database when using soft references for caching database-backed objects.
I see one good use for finalize(): freeing resources that are available in large amounts and are not exclusive.
For example, by default there are 1024 file handles available for a Linux process and about 10000 for Windows. This is pretty much, so for most applications if you open a file, you don't have to call .close() (and use the ugly try...finally blocks), and you'll be OK - finally() will free it for you some time later. However for some pieces of code (like intensive server applications), releasing resources with .close() is a must, otherwise finally() may be called too late for you and you may run out of file handles.
The same technique is used by Swing - operating system resources for displaying windows and drawing aren't released by any .close() method, but just by finalize(), so you don't have to worry about all .close() or .dispose() methods like in SWT for example.
However, when there is very limited number of resources, or you must 'lock' resource to use it, also remember to 'unlock' it. For example if you create a file lock on a file, remember also to remove this lock, otherwise nobody else will be able to read or write this file and this can lead to deadlocks - then you can't rely on finalize() to remove this lock for you - you must do it manually at the right place.