Life time of local variable in Java - java

public List<Map<String,class1>> methodName(String Parameter)
{
//create instance of List
List<Map<Strig,class1>> list1 = new ArrayList<Map<String,class1>>();
for(ArrayList arrayList : someGlobalList)
{
//create instance of class1
//Initialize class1 with values in arrayList
//Put this class1 as a value to tempMap which is created inside this loop
//Put that tempMap into List
}
return list1;
}
My doubt
I understand that we cannot guarantee garbage collection. But this question says that when we return a local reference that will not be garbage collected. In my case, class1 is a local Object. But I am returning list1. Is it safe to use those objects from the caller function as list1.get("key"). It will return the class1 Object. Can I safely use the class members?

An object is only eligible for garbage collection after the last reference to it is no longer reachable from your code.
Let's count the references to your newly created object. Each class1 object is only referenced from the list at the moment, so let's look at the references to the list itself.
You have one reference called list1.
Then you return a value. This creates a second reference, which is placed in the stack and passed up to the caller.
List<...> result = theObj.methodName("foo");
During that process the first reference (list1) is no longer accessible, but the reference that was returned back is still accessible - it will be assigned to the variable result in this case. So you still have one valid and accessible reference to the list. Therefore, every reference inside the list is also valid and accessible.
So yes, it is completely safe to use.
There are languages other than Java, where you can allocate an object in stack space. That is, the object itself is allocated locally. Returning a reference to such an object is unsafe as the stack frame is popped. Take this example in C, that returns a pointer to the beginning of a local array:
char *bad_string(void)
{
/* BAD BAD BAD */
char buffer[] = "local string";
return buffer;
}
But in Java, objects are always allocated in heap space (barring internal optimizations which are not visible to the programmer and are checked to be safe, as mentioned in the comments).
An object allocated by the new operator is never "popped", and always obeys the rules of garbage collection. Stack/local method space is only used for primitives and references, and you never get a reference to any of those, only to objects. Thus, if you have a reference to something, you can trust that its memory is safe.

Yes, you'll be able to access all the objects contained in the list object (list1) you are returning (including objects of type class1) as long as its reference is assigned to a reference variable in the method that called methodName.
This is because there is no such thing as a local object. Objects live in the heap (unlike local variables which live on the stack) and they will only be eligible for garbage collection if there are no more reachable references to it.

Yes. The moment list1 leaves the frame ( is returned by the function ), it and all of it's references stop being "local variables" and will not be candidates for garbage collection until there are no longer any references to "list1"

In my case, class1 is a local Object. But I am returning list1
If a reference leaks from a method, then that object can be used (safely? is again another question which is dependent on the exact definition of safe). In your case since you are returning list1, all local fields referenced by list1 (recursively) can be accessed without NPE (or the fear of them being GCed) because your list has a strong reference to those instances.
If you are talking about thread safety, then it depends on how many threads have access to this leaked reference(s).

You need to have only one reference. Objects referenced by this first referenced object will be free from GC as well.. and so on up the tree.

Related

Does a class hold references to its field objects?

I am a bit confused GC aspect when it comes to the instance variables, especially fields.
So, if an object holds references to its field objects, these won't be eligible for garbage collection until the object itself is. Since Threads are GC roots and every object must have been created on some Thread only, thread won't let go of any objects created on it and the entire object hierarchy from a Thread shall remain for a considerable time before getting garbage collected.
On the other hand, if an object lets go of the field objects, calling a getter for these objects will end up in returning null later.
So, what are the facts here?
Clarification for "field objects"(as asked in comments)
By field objects I mean, the field members of an object that are themselves objects
Edit 2: A bit more elaboration
So, you see Threads are execution units having representation in memory through the Thread object instance. Any code execution that is happening anywhere is happening on some Thread.
How would this execution happen?
Well, through the execution of some code in a method. What would that make this object created?
A Local variable
And, that would make it a GC root.
Btw, for a method call, there is a stack for that particular call and this is what I have been referring to here.
It ain't so simple as #louis-wasserman said - "Yes, naturally" or for that matter not that natural..(?)
I investigated some more and found the answer on...where you would expect it probably - Java Language Specification
2.7. Representation of Objects
The Java Virtual Machine does not mandate any particular internal
structure for objects.
In some of Oracle’s implementations of the Java Virtual Machine, a
reference to a class instance is a pointer to a handle that is itself
a pair of pointers: one to a table containing the methods of the
object and a pointer to the Class object that represents the type of
the object, and the other to the memory allocated from the heap for
the object data.
Yes, that settles it. Even though, JLS doesn't mandate on the internal structure of an java.lang.Object, it would be likely that a structure similar to Oracle's JVM might be used.
This has bigger implication that you might think. Imagine a very heavy object holding one very bulky member field object. Hmmm...a Bitmap maybe. A Bitmap of 10MB and the other object simply holds the image's title:
bulky_object = {bitmap, title}
If you create up this object as a local variable inside a method inside a nested scope(for example's sake), the container object is eligible for garbage collection after the scope gets over but if you decide to hold a reference to the bitmap(the field) object after the scope, the containing object won't have been collected fully:
void someMethod(){
// Outer block of the method
bitmap_ref;
// Nested block starts
{
some_object = new some_object();
// Hold a ref to the bitmap
bitmap_ref = some_object.bitmap;
}
// Nested block has ended. some_object is eligible for GC and is not accessible as a GC root
// anymore
// bitmap_ref shall remain available alive and well here as we are holding a ref to it
// Also, some_object garbage collection may have happened leaving bitmap_ref alive
}
This would seem like an object leak here.

Does making an object reference null, releases a memory occupied by that object [duplicate]

Lets assume, there is a Tree object, with a root TreeNode object, and each TreeNode has leftNode and rightNode objects (e.g a BinaryTree object)
If i call:
myTree = null;
what really happens with the related TreeNode objects inside the tree? Will be garbage collected as well, or i have to set null all the related objects inside the tree object??
Garbage collection in Java is performed on the basis of "reachability". The JLS defines the term as follows:
"A reachable object is any object that can be accessed in any potential continuing computation from any live thread."
So long as an object is reachable1, it is not eligible for garbage collection.
The JLS leaves it up to the Java implementation to figure out how to determine whether an object could be accessible. If the implementation cannot be sure, it is free to treat a theoretically unreachable object as reachable ... and not collect it. (Indeed, the JLS allows an implementation to not collect anything, ever! No practical implementation would do that though2.)
In practice, (conservative) reachability is calculated by tracing; looking at what can be reached by following references starting with the class (static) variables, and local variables on thread stacks.
Here's what this means for your question:
If i call: myTree = null; what really happens with the related TreeNode objects inside the tree? Will be garbage collected as well, or i have to set null all the related objects inside the tree object??
Let's assume that myTree contains the last remaining reachable reference to the tree root.
Nothing happens immediately.
If the internal nodes were previously only reachable via the root node, then they are now unreachable, and eligible for garbage collection. (In this case, assigning null to references to internal nodes is unnecessary.)
However, if the internal nodes were reachable via other paths, they are presumably still reachable, and therefore NOT eligible for garbage collection. (In this case, assigning null to references to internal nodes is a mistake. You are dismantling a data structure that something else might later try to use.)
If myTree does not contain the last remaining reachable reference to the tree root, then nulling the internal reference is a mistake for the same reason as in 3. above.
So when should you null things to help the garbage collector?
The cases where you need to worry are when you can figure out that that the reference in some cell (local, instance or class variable, or array element) won't be used again, but the compiler and runtime can't! The cases fall into roughly three categories:
Object references in class variables ... which (by definition) never go out of scope.
Object references in local variables that are still in scope ... but won't be used. For example:
public List<Pig> pigSquadron(boolean pigsMightFly) {
List<Pig> airbornePigs = new ArrayList<Pig>();
while (...) {
Pig piggy = new Pig();
...
if (pigsMightFly) {
airbornePigs.add(piggy);
}
...
}
return airbornePigs.size() > 0 ? airbornePigs : null;
}
In the above, we know that if pigsMightFly is false, that the list object won't be used. But no mainstream Java compiler could be expected to figure this out.
Object references in instance variables or in array cells where the data structure invariants mean that they won't be used. #edalorzo's stack example is an example of this.
It should be noted that the compiler / runtime can sometimes figure out that an in-scope variable is effectively dead. For example:
public void method(...) {
Object o = ...
Object p = ...
while (...) {
// Do things to 'o' and 'p'
}
// No further references to 'o'
// Do lots more things to 'p'
}
Some Java compilers / runtimes may be able to detect that 'o' is not needed after the loop ends, and treat the variable as dead.
1 - In fact, what we are talking about here is strong reachability. The GC reachability model is more complicated when you consider soft, weak and phantom references. However, these are not relevant to the OP's use-case.
2 - In Java 11 there is an experimental GC called the Epsilon GC that explicitly doesn't collect anything.
They will be garbage collected unless you have other references to them (probably manual). If you just have a reference to the tree, then yes, they will be garbage collected.
You can't set an object to null, only a variable which might contain an pointer/reference to this object. The object itself is not affected by this. But if now no paths from any living thread (i.e. local variable of any running method) to your object exist, it will be garbage-collected, if and when the memory is needed. This applies to any objects, also the ones which are referred to from your original tree object.
Note that for local variables you normally not have to set them to null if the method (or block) will finish soon anyway.
myTree is just a reference variable that previously pointed to an object in the heap. Now you are setting that to null. If you don't have any other reference to that object, then that object will be eligible for garbage collection.
To let the garbage collector remove the object myTree just make a call to gc() after you've set it to null
myTree=null;
System.gc();
Note that the object is removed only when there is no other reference pointing to it.
In Java, you do not need to explicitly set objects to null to allow them to be GC'd. Objects are eligible for GC when there are no references to it (ignoring the java.lang.ref.* classes).
An object gets collected when there are no more references to it.
In your case, the nodes referred to directly by the object formally referenced by myTree (the root node) will be collected, and so on.
This of course is not the case if you have outstanding references to nodes outside of the tree. Those will get GC'd once those references go out of scope (along with anything only they refer to)

What happens to an object reference after it is set to null

I know an object reference or object handle has a size itself and the size is JVM dependent. I am just wondering what will happen after it has been explicitly set to null. Say we have a variable Object o = new Object() and later we set o = null. Will it be garbage collected?
In your example:
Object o = new Object()
o = null;
Assume o is either a field or a local variable/parameter. In the former situation it occupies 4/8 bytes in some other (outer) object. These bytes will be garbage collected when outer object is garbage collected.
If o is a parameter/local variable, no garbage collection is needed, the JVM will "recycle" the stack and simply reuse/erase that space.
References aren't objects and they are not subject to GC, other than in objects that contain them. They live in lexical scopes and they have the same lifetime.
No object will be garbage-collected while any kind of reference to it exists. If all the references that point to an object are set to null or are made to point to other objects, then the object may be garbage-collected, but it will no longer be "the object to which those references refer".
Note that Java has a class called WeakReference, which is designed to hold a reference to an object without preventing it from being garbage-collected. If when the system performs a garbage-collection there exists any object which is the target of a WeakReference, but would otherwise be eligible for garbage-collection, the system will invalidate the WeakReference. At that point, if nobody asked the WeakReference for its target before it was invalidated, there will no longer be any reference to the object, and it will thus be eligible for collection.

regarding garbage collection and references

I have a question regarding references and garbage collector in java.
When calling a method with a parameter, let say an array, it is sent a copy of the reference of the array that is considered the parameter.
Hypothesis: the garbage collector is triggered exactly after calling the method, or when executing operations inside the method to the considered array.
Is now the same reference for the array in the calling method and in the called method, regardless of the operations and moves done by the garbage collector (the garbage collector can move the reference from eden to survivor 1)?
A simpler expression for the question: can you rely on this reference copy in order to use it as a mechanism for parameters sent 'by reference'?
Thank you very much!
Roxana
If you're trying to ask whether you can fake pass by reference like this:
// We'd like to pass x by reference...
String x = "hello";
String[] array = { x };
foo(array);
x = array[0];
...
static void foo(String[] array)
{
array[0] = array[0] + "foo";
}
... then yes, that will always work, and isn't affected by garbage collection.
I'd personally try to avoid it, but yes, it'll work :)
Note that unlike with real pass-by-reference, if the method throws an exception then the assignment after the method call won't occur, so you'll lose the "change".
Garbage collector removes object that cannot be accessed by any reference. In your example there are at least 2 references that can be used to access object. Therefore it will not be removed and you can be use references to access it.
Some garbage collectors work by finding objects with no references and reclaiming the space they occupy.
Others work by finding all objects with references, and moving them to a new object space. When all objects have been moved, the old object space is reclaimed. In that case, all the references are updated.

Does setting Java objects to null do anything anymore?

I was browsing some old books and found a copy of "Practical Java" by Peter Hagger. In the performance section, there is a recommendation to set object references to null when no longer needed.
In Java, does setting object references to null improve performance or garbage collection efficiency? If so, in what cases is this an issue? Container classes? Object composition? Anonymous inner classes?
I see this in code pretty often. Is this now obsolete programming advice or is it still useful?
It depends a bit on when you were thinking of nulling the reference.
If you have an object chain A->B->C, then once A is not reachable, A, B and C will all be eligible for garbage collection (assuming nothing else is referring to either B or C). There's no need, and never has been any need, to explicitly set references A->B or B->C to null, for example.
Apart from that, most of the time the issue doesn't really arise, because in reality you're dealing with objects in collections. You should generally always be thinking of removing objects from lists, maps etc by calling the appropiate remove() method.
The case where there used to be some advice to set references to null was specifically in a long scope where a memory-intensive object ceased to be used partway through the scope. For example:
{
BigObject obj = ...
doSomethingWith(obj);
obj = null; <-- explicitly set to null
doSomethingElse();
}
The rationale here was that because obj is still in scope, then without the explicit nulling of the reference, it does not become garbage collectable until after the doSomethingElse() method completes. And this is the advice that probably no longer holds on modern JVMs: it turns out that the JIT compiler can work out at what point a given local object reference is no longer used.
No, it's not obsolete advice. Dangling references are still a problem, especially if you're, say, implementing an expandable array container (ArrayList or the like) using a pre-allocated array. Elements beyond the "logical" size of the list should be nulled out, or else they won't be freed.
See Effective Java 2nd ed, Item 6: Eliminate Obsolete Object References.
Instance fields, array elements
If there is a reference to an object, it cannot be garbage collected. Especially if that object (and the whole graph behind it) is big, there is only one reference that is stopping garbage collection, and that reference is not really needed anymore, that is an unfortunate situation.
Pathological cases are the object that retains an unnessary instance to the whole XML DOM tree that was used to configure it, the MBean that was not unregistered, or the single reference to an object from an undeployed web application that prevents a whole classloader from being unloaded.
So unless you are sure that the object that holds the reference itself will be garbage collected anyway (or even then), you should null out everything that you no longer need.
Scoped variables:
If you are considering setting a local variable to null before the end of its scope , so that it can be reclaimed by the garbage collector and to mark it as "unusable from now on", you should consider putting it in a more limited scope instead.
{
BigObject obj = ...
doSomethingWith(obj);
obj = null; // <-- explicitly set to null
doSomethingElse();
}
becomes
{
{
BigObject obj = ...
doSomethingWith(obj);
} // <-- obj goes out of scope
doSomethingElse();
}
Long, flat scopes are generally bad for legibility of the code, too. Introducing private methods to break things up just for that purpose is not unheard of, too.
In memory restrictive environments (e.g. cellphones) this can be useful. By setting null, the objetc don't need to wait the variable to get out of scope to be gc'd.
For the everyday programming, however, this shouldn't be the rule, except in special cases like the one Chris Jester-Young cited.
Firstly, It does not mean anything that you are setting a object to null. I explain it below:
List list1 = new ArrayList();
List list2 = list1;
In above code segment we are creating the object reference variable name list1 of ArrayList object that is stored in the memory. So list1 is referring that object and it nothing more than a variable. And in the second line of code we are copying the reference of list1 to list2. So now going back to your question if I do:
list1 = null;
that means list1 is no longer referring any object that is stored in the memory so list2 will also having nothing to refer. So if you check the size of list2:
list2.size(); //it gives you 0
So here the concept of garbage collector arrives which says «you nothing to worry about freeing the memory that is hold by the object, I will do that when I find that it will no longer used in program and JVM will manage me.»
I hope it clear the concept.
One of the reasons to do so is to eliminate obsolete object references.
You can read the text here.

Categories