I need to reference an activity in several static methods. I'm curious to know the best practices to avoid memory leaks. Let's use examples:
Example 1:
static void hideKeyboard(Activity activity) {
WeakReference<Activity> activityReference = new WeakReference<>(activity);
// ... Call activityReference.get() when needed, check if null...
}
Example 2:
static void hideKeyboard(WeakReference<Activity> activityReference) {
// ... Call activityReference.get() when needed, check if null...
}
So three questions:
Do example 1 or 2 make any difference?
I haven't seen methods being called this way much outside of subclasses of Thread or AsyncTask. Any reason why? Am I missing something?
If the weak reference is used in a Thread or AsyncTask inside one of those methods, could memory still leak?
No, it doesn't make a difference. Garbage collection in Java works on the idea of GC roots. If a variable is a GC root or references by a GC root (including transitively) it cannot be garbage collected. Parameters to a function are a GC root- until the function returns none of its parameters can be collected. Since Activity is a parameter to your function, it will be uncollectable as long as that function is in the call stack. Using a WeakReference won't speed it up.
Threads and AsyncTasks (which are just wrappers around Thread really) are slightly different. Every running thread is also a GC root. But threads can have a long lifetime and exist beyond the lifecycle of the object. Here, using a WeakReference does possibly help because there isn't another reason it needs to be kept around (like the parameter in your sample).
Your example 2 is a bit better, it isn't blatantly unnecessary. But I question why its needed. In general when doing a Thread the pattern should be:
run() {
do_async_work()
update_ui()
}
update_ui() {
Activity activity = weakReference.get()
if(activity == null) {
return
}
//update the UI
}
Doing it like this will prevent a lot of problems like needing to check the weak reference a dozen times.
There is absolutely no reason to use WeakReference in a parameter passed to a method, unless this parameter is being stored. If the parameter is only used in the method, you can just pass in the Activity reference.
Related
I sometimes see the code of this kind in some library APIs and just in someone's code:
class SomeClass {
private WeakReference<SomeObject> objectWeakReference; // initialized elsewhere
public boolean isObjectAttached() {
return objectWeakReference.get() != null;
}
public SomeObject getObject() {
return objectWeakReference.get();
}
}
and
public void checkAndGetWeakReference() {
SomeClass someClass = new SomeClass();
if (someClass.isObjectAttached()) {
someClass.getObject().doSomethingDirectlyOnReturnedObject(); // can the returned reference be null here ?
}
}
And I'm always worried if there could be NullPointerException once in a blue moon, assuming there are no strong reference to the underlying object at this point.
I don't really know when exactly Garbage Collector can start deleting objects from memory and how does it correlate with the basic thread flow.
It would be nice if someone can shed the light on this particular subject and/or provide some information about the topic.
P.S. I would personally get reference only once and assign it to strong reference. The point of the question is to get some proof the code above is wrong.
The whole point of the WeakReference (and SoftReference as well) is that the referred object may be gc'd at any time no strong reference to the object exists.
Since there exists no strong reference when isObjectAttached() returns, yes it can be garbage collected before it actually gets to execute getObject(). The whole idom is faulty for this use case.
The only safe way is to first get the reference (e.g. to a local variable) and then check it against null. The object can then not be garbage collected in that case, because a local variable is a strong reference.
As per java doc. You should not rely on Garbage collector. Its not sure when it will be executed. Though you are trying explicitly System.gc()
Its always been a lowest priority for JVM for garbage collector. When JVM is free or when your program is around to ran out of memory it can execute GC.
In other case when your program will exit. It will be garbage collected before it is flushed out of JVM memory.
Please refer javadoc for detailed explanation for GC.
http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
I would like to add something to all answers.
Your object can be null when you call below method :
public SomeObject getObject() {
return objectWeakReference.get();
}
about garbage collection of this object.
If you do something like below :
public static void main(String args[]) {
SomeClass oSomeClass = new SomeClass();
// this one is strong reference "obj"
// this object can be null. Best practice is to null check before you use it.
// Or i will suggest to call isObjectAttached() method before you use it
Object obj = oSomeClass.getObject();
}
When you do obj = null; somewhere in code after above statement.
This object memory is available for garbage collection. Whenever JVM feels to clean memory. Yes it can collect this object.
Regarding proof of code you are asking.
public boolean isObjectAttached() {
return objectWeakReference.get() != null;
}
This method is made for you to check whether this object is present in memory or it has a valid reference for you.
If it returns true you will never get nullpointer exception.
but if you are not using this method i will suggest to use null check always before you use your object.
Hope I am on right direction and making some sense in my answer. Please respond accordingly.
We all are here to learn ;-)
Enjoy Java, OOP concepts.
Garbage collector internally has its heuristics to collect soft/weak/phantom references. It will not collect those objects in subsequent GC calls. It tracks these objects until it reaches the threshold of that heuristics, GC is not allowed to collect these references.
For a library that involves asynchronous operations, I have to keep a reference to an object alive until a certain condition is met.
(I know, that sounds unusual. So here is some context, although it may not strictly be relevant: The object may be considered to be a direct ByteBuffer which is used in JNI operations. The JNI operations will fetch the address of the buffer. At this point, this address is only a "pointer" that is not considered as a reference to the byte buffer. The address may be used asynchronously, later in time. Thus, the buffer has to be prevented from being garbage collected until the JNI operation is finished.)
To achieve this, I implemented a method that is basically equivalent to this:
private static void keepReference(final Object object)
{
Runnable runnable = new Runnable()
{
#SuppressWarnings("unused")
private Object localObject = object;
public void run()
{
// Do something that does NOT involve the "localObject" ...
waitUntilCertainCondition();
// When this is done, the localObject may be garbage collected
}
};
someExecutor.execute(runnable);
}
The idea is to create a Runnable instance that has the required object as a field, throw this runnable into an executor, and let the runnable wait until the condition is met. The executor will keep a reference to the runnable instance until it is finshed. The runnable is supposed to keep a reference to the required object. So only after the condition is met, the runnable will be released by the executor, and thus, the local object will become eligible for garbage collection.
The localObject field is not used in the body of the run() method. May the compiler (or more precisely: the runtime) detect this, and decide to remove this unused reference, and thus allow the object to be garbage collected too early?
(I considered workarounds for this. For example, using the object in a "dummy statement" like logger.log(FINEST, localObject);. But even then, one could not be sure that a "smart" optimizer wouldn't do some inlining and still detect that the object is not really used)
Update: As pointed out in the comments: Whether this can work at all might depend on the exact Executor implementation (although I'd have to analyze this more carefully). In the given case, the executor will be a ThreadPoolExecutor.
This may be one step towards the answer:
The ThreadPoolExecutor has an afterExecute method. One could override this method and then use a sledgehammer of reflection to dive into the Runnable instance that is given there as an argument. Now, one could simply use reflection hacks to walk to this reference, and use runnable.getClass().getDeclaredFields() to fetch the fields (namely, the localObject field), and then fetch the value of this field. And I think that it should not be allowed to observe a value there that is different from the one that it originally had.
Another comment pointed out that the default implementation of afterExecute is empty, but I'm not sure whether this fact can affect the question of whether the field may be removed or not.
Right now, I strongly assume that the field may not be removed. But some definite reference (or at least more convincing arguments) would be nice.
Update 2: Based on the comments and the answer by Holger, I think that not the removal of "the field itself" may be a problem, but rather the GC of the surrounding Runnable instance. So right now, I assume that one could try something like this:
private static long dummyCounter = 0;
private static Executor executor = new ThreadPoolExecutor(...) {
#Override
public void afterExecute(Runnable r, Throwable t) {
if (r != null) dummyCounter++;
if (dummyCounter == Long.MAX_VALUE) {
System.out.println("This will never happen", r);
}
}
}
to make sure that the localObject in the runnable really lives as long as it should. But I can hardly remember ever having been forced to write something that screamed "crude hack" as loud as these few lines of code...
If JNI code fetches the address of a direct buffer, it should be the responsibility of the JNI code itself, to hold a reference to the direct buffer object as long as the JNI code holds the pointer, e.g. using NewGlobalRef and DeleteGlobalRef.
Regarding your specific question, this is addressed directly in JLS §12.6.1. Implementing Finalization:
Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. …
Another example of this occurs if the values in an object's fields are stored in registers. … Note that this sort of optimization is only allowed if references are on the stack, not stored in the heap.
(the last sentence matters)
It is illustrated in that chapter by an example not too different to yours. To make things short, the localObject reference within the Runnable instance will keep the life time of the referenced object at least as long as the life time of the Runnable instance.
That said, the critical point here is the actual life time of the Runnable instance. It will be considered definitely alive, i.e. immune to optimizations, due to the rule specified above, if it is also referred by an object that is immune to optimizations, but even an Executor isn’t necessarily a globally visible object.
That said, method inlining is one of the simplest optimizations, after which a JVM would detect that the afterExecute of a ThreadPoolExecutor is a no-op. By the way, the Runnable passed to it is the Runnable passed to execute, but it wouldn’t be the same as passed to submit, if you use that method, as (only) in the latter case, it’s wrapped in a RunnableFuture.
Note that even the ongoing execution of the run() method does not prevent the collection of the Runnable implementation’s instance, as illustrated in “finalize() called on strongly reachable object in Java 8”.
The bottom line is that you will be walking on thin ice when you try to fight the garbage collector. As the first sentence of the cite above states: “Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable.” Whereas we all may find ourselves being thinking too naively…
As said at the beginning, you may rethink the responsibilities. It’s worth noting that when your class has a close() method which has to be invoked to release the resource after all threads have finished their work, this required explicit action is already sufficient to prevent the early collection of the resource (assuming that the method is indeed called at the right point)…
Execution of Runnable in a thread pool is not enough to keep an object from being garbage collected. Even "this" can be collected! See JDK-8055183.
The following example shows that keepReference does not really keep it. Though the problem does not happen with vanilla JDK (because the compiler is not smart enough), it can be reproduced when a call to ThreadPoolExecutor.afterExecute is commented out. It is absolutely possible optimization, because afterExecute is no-op in the default ThreadPoolExecutor implementation.
import java.lang.ref.WeakReference;
import java.util.concurrent.*;
public class StrangeGC {
private static final ExecutorService someExecutor =
Executors.newSingleThreadExecutor();
private static void keepReference(final Object object) {
Runnable runnable = new Runnable() {
#SuppressWarnings("unused")
private Object localObject = object;
public void run() {
WeakReference<?> ref = new WeakReference<>(object);
if (ThreadLocalRandom.current().nextInt(1024) == 0) {
System.gc();
}
if (ref.get() == null) {
System.out.println("Object is garbage collected");
System.exit(0);
}
}
};
someExecutor.execute(runnable);
}
public static void main(String[] args) throws Exception {
while (true) {
keepReference(new Object());
}
}
}
Your hack with overriding afterExecute will work though.
You've basically invented a kind of Reachability Fence, see JDK-8133348.
The problem you've faced is known. It will be addressed in Java 9 as a part of JEP 193. There will be a standard API to explicitly mark objects as reachable: Reference.reachabilityFence(obj).
Update
Javadoc comments to Reference.reachabilityFence suggest synchronized block as an alternative construction to ensure reachability.
The below class is initialised on the init() method of a servlet.
objA is only used for reading, the refreshA-method needs to be called periodically to replace it with a new instance of A.
The problem :
After periodical updates, a memory leak appears. (I am guessing there are some dangling references multiple copies of the A existing)
public Class A {
private static volatile A objA;
public static A getA(){
if(objA == null){
synchronized (A.class){
if(objA == null){
objA = new A(); //takes a long time to initialise and memory heavy
return objA;
}
}
}
return objA;
}
public static void refreshA (A newObjA){
// best way to do this ?
/*
objA = newObjA;
*/
}
}
Kind of hacky :
I could use
ConcurrentHashMap<String,A> -> get("OBJ-A"), replace("OBJ-A", newObjA)
this would use the ReentrantReadWriteLock but I havent tried it yet.
So what would be the best way to implement refreshA()? Keeping in mind that the GC should remove the old reference.
First of all, double-checked locking is not recommended
, see en.wikipedia.org/wiki/Double-checked_locking.
As for the replacable field, you can use an AtomicReference.
And regarding the memory leak, consider giving out a proxy to the actual object. This way you can swap out the backing instance and be sure that noone keeps a reference to the old backing object.
It looks like you have figured out how to (re-)implement the singleton and the refresh operation.
I want to focus on some of the other things in your Question.
(Pure) Java cannot have dangling references. The values in any reference in any live object in Java will either be null or valid reference to an existing object. This even applies to unreachable objects.
Dangle references (i.e. pointers that no longer point to a valid object) don't cause storage leaks. Rather they are a sign of heap corruption. In Java, if the JVM (including the GC) attempted to use a dangling reference, the result would most likely be a hard crash.
If is not entirely clear what you think the connection between the memory leak and your periodic update is. However:
The periodic update is almost certainly not the cause of this memory leak. Certainly it is not, on the evidence of the code you have shown us.
A periodic update is not guaranteed to cure a memory leak, unless the A static holds the one and only long-term reference to the A instance that is leaking. Indeed, if you "refresh" the A singleton in this way, there is a distinct possibility that you will cause a leak. For example, if some other code calls the getA() method and caches the result somewhere, when A.refreshA() is called you will end up with TWO A instances in existence, and the first one has effectively leaked.
Finally your refresh operation is breaking the implicit singleton semantics of A. That could cause all sorts of other problems, including threading issues.
If you suspect that your A class is the cause of a memory leak, then a better approach to fixing the problem is to:
figure out what part of A's state is the dangerous part of the leak, and
add a synchronized instance method to A to clear that state.
Note that not all leaks are harmful. An object that exists for the lifetime of the application (e.g. a static) could appear to be a leak (to a leak detector) but is not going to cause any problems.
I'm slowly working through Bruce Eckel's Thinking in Java 4th edition, and the following problem has me stumped:
Create a class with a finalize( ) method that prints a message. In main( ), create an object of your class. Modify the previous exercise so that your finalize( ) will always be called.
This is what I have coded:
public class Horse {
boolean inStable;
Horse(boolean in){
inStable = in;
}
public void finalize(){
if (!inStable) System.out.print("Error: A horse is out of its stable!");
}
}
public class MainWindow {
public static void main(String[] args) {
Horse h = new Horse(false);
h = new Horse(true);
System.gc();
}
}
It creates a new Horse object with the boolean inStable set to false. Now, in the finalize() method, it checks to see if inStable is false. If it is, it prints a message.
Unfortunately, no message is printed. Since the condition evaluates to true, my guess is that finalize() is not being called in the first place. I have run the program numerous times, and have seen the error message print only a couple of times. I was under the impression that when System.gc() is called, the garbage collector will collect any objects that aren't referenced.
Googling a correct answer gave me this link, which gives much more detailed, complicated code. It uses methods I haven't seen before, such as System.runFinalization(), Runtime.getRuntime(), and System.runFinalizersOnExit().
Is anybody able to give me a better understanding of how finalize() works and how to force it to run, or walk me through what is being done in the solution code?
When the garbage collector finds an object that is eligible for collection but has a finalizer it does not deallocate it immediately. The garbage collector tries to complete as quickly as possible, so it just adds the object to a list of objects with pending finalizers. The finalizer is called later on a separate thread.
You can tell the system to try to run pending finalizers immediately by calling the method System.runFinalization after a garbage collection.
But if you want to force the finalizer to run, you have to call it yourself. The garbage collector does not guarantee that any objects will be collected or that the finalizers will be called. It only makes a "best effort". However it is rare that you would ever need to force a finalizer to run in real code.
Outside of toy scenarios, it's generally not possible to ensure that a finalize will always be called on objects to which no "meaningful" references exist, because the garbage collector has no way of knowing which references are "meaningful". For example, an ArrayList-like object might have a "clear" method which sets its count to zero, and makes all elements within the backing array eligible to be overwritten by future Add calls, but doesn't actually clear the elements in that backing array. If the object has an array of size 50, and its Count is 23, then there may be no execution path by which code could ever examine the references stored in the last 27 slots of the array, but there would be no way for the garbage-collector to know that. Consequently, the garbage-collector would never call finalize on objects in those slots unless or until the container overwrote those array slots, the container abandoned the array (perhaps in favor of a smaller one), or all rooted references to the container itself were destroyed or otherwise ceased to exist.
There are various means to encourage the system to call finalize on any objects for which no strong rooted references happen to exist (which seems to be the point of the question, and which other answers have already covered), but I think it's important to note the distinction between the set of objects to which strong rooted references exist, and the set of objects that code may be interested in. The two sets largely overlap, but each set can contain objects not in the other. Objects' finalizers` run when the GC determines that the objects would no longer exist but for the existence of finalizers; that may or may not coincide with the time code they cease being of interest to anyone. While it would be helpful if one could cause finalizers to run on all objects that have ceased to be of interest, that is in general not possible.
A call to garabage collecter (System.gc()) method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse (i.e its just a suggestion to the jvm, and does not bind it to perform the action then and there, it may or may not do the same). When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects. finalize() is called by the garbage collector on an object when garbage collection determines that there are no more references to the object
run new constructor() and System.gc() more than twice.
public class Horse {
boolean inStable;
Horse(boolean in){
inStable = in;
}
public void finalize(){
if (!inStable) System.out.print("Error: A horse is out of its stable!");
}
}
public class MainWindow {
public static void main(String[] args) {
for (int i=0;i<100;i++){
Horse h = new Horse(false);
h = new Horse(true);
System.gc();
}
}
}
Here's what worked for me (partially, but it does illustrate the idea):
class OLoad {
public void finalize() {
System.out.println("I'm melting!");
}
}
public class TempClass {
public static void main(String[] args) {
new OLoad();
System.gc();
}
}
The line new OLoad(); does the trick, as it creates an object with no reference attached. This helps System.gc() run the finalize() method as it detects an object with no reference. Saying something like OLoad o1 = new OLoad(); will not work as it will create a reference that lives until the end of main(). Unfortunately, this works most of the time. As others pointed out, there's no way to ensure finalize() will be always called, except to call it yourself.
In what situations in java is explicit nulling useful. Does it in any way assist the garbage collector by making objects unreachable or something? Is it considered to be a good practice?
In Java it can help if you've got a very long-running method, and the only reference to the an object is via a local variable. Setting that local variable to null when you don't need it any more (but when the method is going to continue to run for a long time) can help the GC. (In C# this is very rarely useful as the GC takes "last possible use" into account. That optimization may make it to Java some time - I don't know.)
Likewise if you've got a member field referring to an object and you no longer need it, you could potentially aid GC by setting the field to null.
In my experience, however, it's rarely actually useful to do either of these things, and it makes the code messier. Very few methods really run for a long time, and setting a variable to null really has nothing to do with what you want the method to achieve. It's not good practice to do it when you don't need to, and if you do need to you should see whether refactoring could improve your design in the first place. (It's possible that your method or type is doing too much.)
Note that setting the variable to null is entirely passive - it doesn't inform the garbage collector that the object can be collected, it just avoids the garbage collector seeing that reference as a reason to keep the object alive next time it (the GC) runs.
In general it isn't needed (of course that can depend on the VM implementation). However if you have something like this:
private static final Map<String, String> foo;
and then have items in the map that you no longer need they will not be eligible for garbage collection so you would need to explicitly remove them. There are many cases like this (event listeners is another area that this can happen with).
But doing something like this:
void foo()
{
Object o;
// use o
o = null; // don't bother doing this, it isn't going to help
}
Edit (forgot to mention this):
If you work at it, you should find that 90-95% of the variables you declare can be made final. A final variable cannot change what it points at (or what its value is for primitives). In most cases where a variable is final it would be a mistake (bug) for it to receive a different value while the method is executing.
If you want to be able to set the variable to null after use it cannot be final, which means that you have a greater chance to create bugs in the code.
One special case I found it useful is when you have a very large object, and want to replace it with another large object. For example, look at the following code:
BigObject bigObject = new BigObject();
// ...
bigObject = new BigObject(); // line 3
If an instance of BigObject is so large that you can have only one such instance in the heap, line 3 will fail with OutOfMemoryError, because the 1st instance cannot be freed until the assignment instruction in line 3 completes, which is obviously after the 2nd instance is ready.
Now, if you set bigObject to null right before line 3:
bigObject = null;
bigObject = new BigObject(); // line 3
the 1st instance can be freed when JVM runs out of heap during the construction of the 2nd instance.
From "Effective Java" : use it to eliminate obsolete object references. Otherwise it can lead to memory leaks which can be very hard to debug.
public Object pop(){
if(size == 0)
throw new EmptyStatckException();
Object result = elements[--size];
elements[size] = null; //Eliminate Object reference
return result;
}
If you are nulling an object that is about to go out of scope anyway when your method block closes, then there is no benefit whatsoever in terms of garbage collection. It is not unusual to encounter people who don't understand this who work really hard to set a lot of things to null needlessly.
Explicit nulling can help with GC in some rare situations where all of the following are true:
The variable is the only (non-weak) reference to the object
You can guarantee that the object will no longer be needed
The variable will stay in scope for an extended period of time (e.g. it is a field in a long-lived object instance)
The compiler is unable to prove that the object is no longer used, but you are able to guarantee this though your superior logical analysis of the code :-)
In practice this is quite rare in good code: if the object is no longer needed, you should normally be declaring it in a narrower scope anyway. For example, if you only need the object during a single invocation of a method, it should be a local variable, not a field in the enclosing object.
One situation where explicit nulling is genuinely useful: if null is used to indicate a specific state then setting to a null value is sometimes going to be necessary and useful. Null is a useful value in itself for a couple of reasons:
Null checks are extremely fast, so conditional code that checks for null is typically more efficient than many alternatives (e.g. calling object.equals())
You get an immediate NullPointerException if you try to dereference it. This is useful because it is good Fail Fast coding style that will help you to catch logic errors.
See also WeakReference in J2SE.