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.
Related
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)
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.
I know System.gc() is not guaranteed to cause GC, but theoretically, in the following code, will the object obj be eligible for garbage collection?
public class Demo {
public static void main(String[] args) throws Exception {
SomeClass obj = new SomeClass();
ArrayList list = new ArrayList();
list.add(obj);
obj = null;
System.gc();
}
}
class SomeClass {
protected void finalize() {
System.out.println("Called");
}
}
At the point where you call System.gc() the SomeClass instance you created is not eligible for garbage collection because it is still referred to by the list object, i.e. it is still reachable.
However, as soon as this method returns list goes out of scope, so obj will then become eligible for garbage collection (as will list).
Simply setting the reference obj to null does not, by itself, make the object referred to eligible for garbage collection. An object is only eligible if there are no references to it from the graph of visible objects.
will the object obj be eligible for garbage collection?
Only those objects are garbage collected who don't have even one reference to reach them. (except the cyclic connectivity)
In you code, there are two reference that are pointing to new SomeClass();
obj
zeroth index of list
You put obj = null, i.e. it's not pointing to that object anymore. But, still there exists another reference in list which can be used to access that object.
Hence the object will be eligible for GC only when main returns. i.e. you can't see the output of finalize method even if it got called. (not sure if JVM still calls it)
No, because the object actually exists in the list.
You as Java programmer can not force Garbage collection in Java; it will only trigger if JVM thinks it needs a garbage collection based on Java heap size
When a Java program started Java Virtual Machine gets some memory from Operating System. Java Virtual Machine or JVM uses this memory for all its need and part of this memory is call java heap memory.
Heap in Java generally located at bottom of address space and move upwards. whenever we create object using new operator or by any another means object is allocated memory from Heap and When object dies or garbage collected ,memory goes back to Heap space in Java
EDIT :
will the object obj be eligible for garbage collection?
No, because the object is still in the ArrayList.
Agreed, it won't be garbage collected as long as its there in the list.
I have read this article about different types of references in Java (strong, soft, weak, phantom), but I don't really understand it.
What is the difference between these reference types, and when would each type be used?
Java provides two different types/classes of Reference Objects: strong and weak. Weak Reference Objects can be further divided into soft and phantom.
Strong
Weak
soft
phantom
Let's go point by point.
Strong Reference Object
StringBuilder builder = new StringBuilder();
This is the default type/class of Reference Object, if not differently specified: builder is a strong Reference Object. This kind of reference makes the referenced object not eligible for GC. That is, whenever an object is referenced by a chain of strong Reference Objects, it cannot be garbage collected.
Weak Reference Object
WeakReference<StringBuilder> weakBuilder = new WeakReference<StringBuilder>(builder);
Weak Reference Objects are not the default type/class of Reference Object and to be used they should be explicitly specified like in the above example. This kind of reference makes the reference object eligible for GC. That is, in case the only reference reachable for the StringBuilder object in memory is, actually, the weak reference, then the GC is allowed to garbage collect the StringBuilder object. When an object in memory is reachable only by Weak Reference Objects, it becomes automatically eligible for GC.
Levels of Weakness
Two different levels of weakness can be enlisted: soft and phantom.
A soft Reference Object is basically a weak Reference Object that remains in memory a bit more: normally, it resists GC cycle until no memory is available and there is risk of OutOfMemoryError (in that case, it can be removed).
On the other hand, a phantom Reference Object is useful only to know exactly when an object has been effectively removed from memory: normally they are used to fix weird finalize() revival/resurrection behavior, since they actually do not return the object itself but only help in keeping track of their memory presence.
Weak Reference Objects are ideal to implement cache modules. In fact, a sort of automatic eviction can be implemented by allowing the GC to clean up memory areas whenever objects/values are no longer reachable by strong references chain. An example is the WeakHashMap retaining weak keys.
Weak Reference :
A weak reference, simply put, is a reference that isn't strong enough to force an object to remain in memory. Weak references allow you to leverage the garbage collector's ability to determine reachability for you, so you don't have to do it yourself.
Soft Reference :
A soft reference is exactly like a weak reference, except that it is less eager to throw away the object to which it refers. An object which is only weakly reachable (the strongest references to it are WeakReferences) will be discarded at the next garbage collection cycle, but an object which is softly reachable will generally stick around for a while.
Phantom Reference :
A phantom reference is quite different than either SoftReference or WeakReference. Its grip on its object is so tenuous that you can't even retrieve the object -- its get() method always returns null. The only use for such a reference is keeping track of when it gets enqueued into a ReferenceQueue, as at that point you know the object to which it pointed is dead.
This text was extracted from: https://weblogs.java.net/blog/2006/05/04/understanding-weak-references
This article can be super helpful to understand strong, soft, weak and phantom references.
To give you a summary,
If you have a strong reference to an object, then the object can never be collected/reclaimed by GC (Garbage Collector).
If you only have weak references to an object (with no strong references), then the object will be reclaimed by GC in the very next GC cycle.
If you only have soft references to an object (with no strong references), then the object will be reclaimed by GC only when JVM runs out of memory.
We create phantom references to an object to keep track of when the object gets enqueued into the ReferenceQueue. Once you know that you can perform fine-grained finalization. (This would save you from accidentally resurrecting the object as phantom-reference don't give you the referrant). I'd suggest you reading this article to get in-depth detail about this.
So you can say that, strong references have ultimate power (can never be collected by GC)
Soft references are powerful than weak references (as they can escape GC cycle until JVM runs out of memory)
Weak references are even less powerful than soft references (as they cannot escape any GC cycle and will be reclaimed if object have no other strong reference).
Restaurant Analogy
Waiter - GC
You - Object in heap
Restaurant area/space - Heap space
New Customer - New object that wants table in restaurant
Now if you are a strong customer (analogous to strong reference), then even if a new customer comes in the restaurant or what so ever happnes, you will never leave your table (the memory area on heap). The waiter has no right to tell you (or even request you) to leave the restaurant.
If you are a soft customer (analogous to soft reference), then if a new customer comes in the restaurant, the waiter will not ask you to leave the table unless there is no other empty table left to accomodate the new customer. (In other words the waiter will ask you to leave the table only if a new customer steps in and there is no other table left for this new customer)
If you are a weak customer (analogous to weak reference), then waiter, at his will, can (at any point of time) ask you to leave the restaurant :P
The simple difference between SoftReference and WeakReference is provided by Android Developer.
The difference between a SoftReference and a WeakReference is the point of time at which the decision is made to clear and enqueue the reference:
A SoftReference should be cleared and enqueued as late as possible,
that is, in case the VM is in danger of running out of memory.
A WeakReference may be cleared and enqueued as soon as is known to be
weakly-referenced.
The three terms that you have used are mostly related to Object's eligibility to get Garbage collected .
Weak Reference :: Its a reference that is not strong enough to force the object to remain in memory . Its the garbage collector's whims to collect that object for garbage collection.
You can't force that GC not to collect it .
Soft Reference :: Its more or less same like the weak reference . But you can say that it holds the object a bit more strongly than the weak reference from garbage collection.
If the Garbage collectors collect the weak reference in the first life cycle itself, it will collect the soft reference in the next cycle of Garbage collection.
Strong Reference :: Its just opposite to the above two kind of references .
They are less like to get garbage collected (Mostly they are never collected.)
You can refer to the following link for more info :
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/Reference.html
Strong References
These are your regular object references which we code daily:
Employee emp = new Employee();
The variable “emp” holds a strong reference to an Employee object and objects that are reachable through any chain of strong references are not eligible for garbage collection.
Usually, this is what you want but not always. Now suppose we are fetching lots of employees from database in a collection or map, and we need to do a lot of processing on them regularly, So in order keep performance we will keep them in the cache.
As far as this is good but now we need different data and we don’t need those Employee objects and these are not referenced from anywhere except the cache. Which is causing a memory leak because these objects are not in use but still not eligible for the garbage collection and we cannot remove those objects from cache because we don’t have reference to them?
So here either we need to empty the entire cache manually which is tedious or we could use other kind references e.g. Weak References.
Weak References
A weak reference does not pin an object into memory and will be GC’d in next GC cycle if not referenced from other references. We can use WeakReference class which is provided by Java to create above kind of caches, which will not store objects which are not referenced from somewhere else.
WeakReference<Cache> cache = new WeakReference<Cache>(data);
To access data you need to call cache.get(). This call to get may return null if the weak reference was garbage collected: you must check the returned value to avoid NPEs.
Java provides collections that use weak references e.g., the WeakHashMap class stores keys (not values) as weak references. If the key is GC’d then the value will automatically be removed from the map too.
Since weak references are objects too we need a way to clean them up (they’re no longer useful when the object they were referencing has been GC’d). If you pass a ReferenceQueue into the constructor for a weak reference then the garbage collector will append that weak reference to the ReferenceQueue before they’re finalized or GC’d. You can periodically process this queue and deal with dead references.
Soft References
A SoftReference is like a WeakReference but it is less likely to be garbage collected. Soft references are cleared at the discretion of the garbage collector in response to memory demand. The virtual machine guarantees that all soft references to softly reachable objects will have been cleared before it would ever throw an OutOfMemoryError.
Phantom References
Phantom references are the weakest of all reference types, calling get on them will always return null. An object is phantomly referenced after it has been finalized, but before its allocated memory has been reclaimed, As opposed to weak references which are enqueued before they’re finalized or GC’d Phantom references are rarely used.
So how are they useful? When you construct a phantom reference you must always pass in a ReferenceQueue. This indicates that you can use a phantom reference to see when your object is GC’d.
Hey, so if weak references are enqueued when they’re considered finalize but not yet GC’d we could create a new strong reference to the object in the finalizer block and prevent the object being GC’d. Yep, you can but you probably shouldn’t do this. To check for this case the GC cycle will happen at least twice for each object unless that object is reachable only by a phantom reference. This is why you can run out of heap even when your memory contains plenty of garbage. Phantom references can prevent this.
You can read more on my article Types of References in Java(Strong, Soft, Weak, Phantom).
4 degrees of reference - Strong, Weak, Soft, Phantom
Strong - is a kind of reference, which makes the referenced object not
eligible for GC. builder classes. eg - StringBuilder
Weak - is a reference which is eligible for GC.
Soft - is a kind of reference whose object is eligible for GC until memory is avaiable. Best for image cache. It will hold them till the memory is available.
Phantom - is a kind of reference whose object is directly eligible for GC. Used only to know when an object is removed from memory.
uses:
Allows you to identify when an object is exactly removed from memory.
when finalize() method is overloaded, then GC might not happen in timely fashion for GC eligible objects of the two classes. So phantom reference makes them eligible for GC before finalize(), is why you can get OutOfMemoryErrors even when most of the heap is garbage.
Weak references are ideal to implement the cache modules.
public class Singleton {
public void processRequest(final List<a> aList) {
List<b> bList = new AbstractList<b>() {
b get(int i) {
return (b)aList.get(i);
}
int size() {
return aList.size();
}
......
}
}
here an anonymous instance is created with an implicit reference to the enclosing instance. Since the enclosing instance is a singleton that would always exist in JVM, would this prevent the anonymous instance being claimed by GC and cause memory leak?
any help appreciated!
No, there is no memory leak here. Objects that refer to non-garbage objects can be collected; it is only objects referred to by non-garbage objects that cannot become garbage.
As Russell said, there is no memory leak here.
An object is eligible to garbage collection when it is not reachable by any thread.
If an object is not referenced by any other object, it is never reachable.
But if A and B are refering to each others, it doesn't mean they are reachable, because both of them can be unreachable from any thread. This is what we call Island of isolation
Notice that in some cases, an object reachable from a thread can be collected, when you are not using the normal references (default) but when you use soft or weak references.
Reachability
Going from strongest to weakest, the different levels of reachability
reflect the life cycle of an object. They are operationally defined as
follows: An object is strongly reachable if it can be reached by some
thread without traversing any reference objects. A newly-created
object is strongly reachable by the thread that created it. An object
is softly reachable if it is not strongly reachable but can be reached
by traversing a soft reference. An object is weakly reachable if it is
neither strongly nor softly reachable but can be reached by traversing
a weak reference. When the weak references to a weakly-reachable
object are cleared, the object becomes eligible for finalization. An
object is phantom reachable if it is neither strongly, softly, nor
weakly reachable, it has been finalized, and some phantom reference
refers to it. Finally, an object is unreachable, and therefore
eligible for reclamation, when it is not reachable in any of the above
ways.
Reference package of Java API
This answer is coming 2 years after the fact, but it came up under my similar question pane when I asked: Reference to final object in anonymous class constructor a leak?
I give a different answer than both #Russel and #Sebestian because they rely on a narrow definition of memory leak. What leak often means in GC languages, however, is "keeping a reference thus preventing the GC from collecting it." http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html and that to me seems how OP was using the term. I think he's asking am I unintendedly keeping this object alive? Am I preventing the GC from claiming it?
If those are your actual questions, then the answer is yes. aList is an implict field of bList. Holding a reference to bList will prevent aList from being collected, so long as bList is kept alive.