I'm passing a runnable to a service. The runnable duration may outlive the fragment / activity that passes it. I'm wondering if the following code snippet would leak the frag object by maintaining a reference inside the runnable? I realize I can move the whole line containing frag outside of the runnable (like I did with "String key = frag..."), but I'm asking simply to get an understanding of how/when an anonymous class would leak an object.
I'm really not certain. The runnable only needs frag to determine a variable upon initializing the instance, and it's initialized in-line here. So in theory, it doesn't need to have any reference to frag after creating the in-line instance.
If I had a reference to frag in the run() function, I would think a leak then would be guaranteed as it would need to keep frag alive to reference it sometime in the future (and frag might very well be gc'd at that point, but for the reference).
private static void fg_downloadFile(final FragMyDrive frag, final File file, final Drive drive){
final String key = frag.getCastedActivity().getKey();
Runnable rx_downloadFile = new Runnable() {
Context ServiceContext = frag.getCastedActivity().mService;
@Override
public void run() {
bg_downloadFile(ServiceContext, key, file, drive);
}
};
//.... Submit runnable to service...
}
As you might know, you must make variables final when declaring them outside but using them in an anonymous class. The Java trick here is to copy all those variables into implicitly generated instance fields of that anonymous class.
Having said this, it means that there are indeed instance fields (in your runnable) holding copies of all accessed variables of the outer scope. In your example, it would also have a reference to the
FragMyDrive
as you are simply accessing it.All those objects become eligible for garbage collection at the same time your runnable becomes eligible for garbage collection. That means the reference to your
FragMyDrive
inside your runnable keeps that object alive as long as it is running.It's always a good idea to narrow down those references to what you really need:
Here the only (implicitly generated) instance fields are:
I'm not sure I understand your use of the word inline correctly but in any case, I don't think anything is leaked here.
Var
final String key
is simply a local reference in your static functionfg_downloadFile()
so it's freed when going out of scope at the end of the function.The
Runnable
anonymous inner class may still hold a reference (again, not tofrag
but to some sub-property therein) for as long as theRunnable
thread lives. (More precisely, the compiler actually generates animplementation
ofRunnable
with a constructor andfinal
member variables that copy any implicitly used references to whatever is available infg_downloadFile()
's scope.)But in any case, once the all code has been executed, all references to (sub-members of)
frag
will be removed and the garbage collector can pick up the trash.Hope this helps.
Interesting question. Do you have some experience in programming without automatic garbage collection, like Objective C?
But to answer your question, I don't see why it would be a leak. What I suppose will happen is that the Runnable will keep a reference to frag for it's own use, but at some point in the future, frag will get garbage collected as well once the service does not need it anymore, and hence it's not refering to it.
As garbage collection works, once an object is no longer referenced, it will be subject to garbage collection and deallocated.