Java GarbageCollection and Collections - java

Say I do something like this:
List<Stuff> methodA() {
List<Stuff> all_the_stuff_to_do = new ArrayList<>();
all_the_stuff_to_do.add(new Stuff("important"));
all_the_stuff_to_do.add(new Stuff("not important"));
return all_the_stuff_to_do;
}
List<Stuff> methodB() {
List<Stuff> important_stuff_to_do = new ArrayList<>();
Stuff important = methodA().get(0);
// at this point Stuff("not important") is not reachable anymore
// since I have no reference to the list that contains it left
important_stuff_to_do.add(important);
return important_stuff_to_do;
}
void methodC() {
... do a happydance ...
List<Stuff> stuff_to_do = methodB();
... look sad because now I got important stuff to do ...
}
***** EDIT *****
Better clarification and simplified code
To Clarify:
When exiting methodA() I got a reference of a list with two objects Stuff("important") and Stuff("not important")
I add the reference to Stuff("important") to a list in methodB().
At this point the Object Stuff("not important") is not reachable anymore.
Also the List in methodA() is not reachable anymore.
But the List still contains a reference to an Object that is indeed reachable, namely Stuff("important").
When will the all_the_stuff_to_do List be cleared and when the Stuff("not important") Object?
Will it be directly after the Call to MethodA? Or will it be at the end of MethodB? Or never since it contains a reference to the Stuff("important") Object that is still active till the end of the program?

Will (all_the_stuff_to_do be garbage collected) directly after the Call to MethodA?
Or will it be at the end of MethodB? Or never since it contains a reference to the Stuff("important") Object that is still active till the end of the program?
Garbage collection is generally done on a low priority thread. If nothing else is being done, the garbage collector may run.
If the VM is low on, or out of, memory, the garbage collector may run immediately as the highest priority thread, since it needs to recover memory for the program's immediate need.
So, will it be collected directly after the call to MethodA? No. Will it get collected after the call to get(0)? Possible, but unlikely. At the end of MethodB? Possible, but unlikely. Still active at the end of the program? Possible, but only likely if the program never ran out of memory and never became idle.
The fact that the list contains a copy of "Stuff("important") Object" is irrelevant to whether the list gets collected. If no accessible objects reference the list, the list is eligible for garbage collection.
Will the list get #clear()'d during collection? No, there is no need. If it was a user defined collection, the clear method could do anything, including add another reference to the list, which would mess up the garbage collection. Instead, it is just collected, and objects the list refer to are referenced one less time. That include "Stuff("important") Object" ... It's reference count will get decremented, but since a reference still exists, it won't be cleared.

The collection contains references to the objects that you have added. Until that is no longer reachable or you remove the objects from the collection, they will be reachable. Can you think of a way programs could work reliably if it were otherwise?

In your scenario new Stuff("important") here new keyword is responsible to making an object and reference of this Stuff Object hold by the collection List <Stuff> important_stuff_to_do. Now this collection will hold the reference of the two object that you made .
As per Collection definition all we know that Collection is a group of multiple Object of same type of Objects as a single Entity.
So, No Garbage Collection will be perform because here these two objects are still reachable.
new Stuff("important")
new Stuff("not important")
Note:- Garbage Collection performs only objects which is completely unreachable (One kind of Orphan). Here No Object is getting orphan because Collection never makes the copy / cloing of the objects which is added .
Conclusion :- No Garbage will be performed in this scenario. Thank you

Related

WeakReference of a Collection in java

Backstory
In a library that I maintain we have an internal map keeping track of our cache.
Users of the library are interested in having list access to this map, however we can only provide this by copying its contents (thread-safety reasons).
The idea is to cache this list when it is first accessed without having much memory overhead on a second access.
To illustrate:
List<Bob> list = cache.asList();
List<Bob> otherList = cache.asList(); // use from cache, if still available
The problem is, we don't want to keep this list forever if its not needed anymore. Since java uses GC we thought it would be appropriate to use a WeakReference for this, to allow using it if its not collected.
Question
If I have a WeakReference<List<Bob>> stored inside my class, what happens if one of the elements becomes weakly reachable (which implies the list is weakly reachable)? Is it possible that the GC decides to just collect the element inside the list or would it look for all other weakly reachable objects referencing it and also collect them, in this case the list?
The problem would be, if the GC collected an element of the list and we then try to access the list again (if thats even possible) what would happen?
Clarifications
I'm not interested in the reachability of the list, I know that the list is inside the WeakReference and that the elements are irrelevant to its reachability. I care about a specific state, in which both the list and an element of the list are weakly reachable and whether it is possible that the GC only collects the element but not the list itself. What exactly does the GC do in this specific scenario?
As long as the List itself is not weakly reachable its elements will not be either. (Assuming the list implementation itself does not use weak references or similar)
So there is no problem with having the list cached with a weak reference because it would either be garbage collected completely or not at all.
In provided case (WeakReference<List<Something>>) you have only such possible scenario:
public class Test {
private WeakReference<List<String>> listWeakReference;
public Test(final WeakReference<List<String>> listWeakReference) {
this.listWeakReference = listWeakReference;
}
public static void main(String[] args) {
List<String> testList = Arrays.asList("a", "b", "c");
Test test = new Test(new WeakReference<>(testList));
// Initial check
System.out.println(test.listWeakReference.get());
// Call gc and check
System.gc();
System.out.println(test.listWeakReference.get());
// Remove reference and call gc
testList = null;
System.gc();
System.out.println(test.listWeakReference.get());
}
}
Firstly SoftReference is better for caches, and even that isn't very good.
WeakReference may be released immediately the reference becomes weakly reachable. However, it might not do that until sometime into execution - i.e. it doesn't happen during extensive testing, but it does in production. Fun times. NetBeans used to do this in its caching of files. Of course the rest of the code was expecting the caching so grabbed and released references with incredible frequency. After sometime using the application it would suddenly hammer file I/O and become unusable.
For best performance you need to explicitly estimate how much memory the process is using and release as necessary. Not easy.
Back to the question. Collection of contents of WeakReference (and SoftReference is a two phase operation. The first phase just clears the Reference (and queues if you are using that). The associated memory is not collected. The memory may be resurrected through a finaliser. The WeakReference is forever cleared and queued, it does not reset. Only when an object is completely unreachable can the associated memory be collected as a separate phase.
Fear not, Java is memory-safe (bugs excepted).

Java - JDBC Memory Use After Closing Result/Statement/Connection [duplicate]

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.

At what line can this object be considered to be garbage collected. Java

So my understanding is at line 1, a new object is created and it is referenced by obj. At line 2, obj is referencing to another new object. so the object which we created at line 1 is eligible for garbage collection because it is not referenced by any instance. But the answer from test question is at line 3. Reason? Is the answer correct?
Object obj = new Object(); //line 1
obj = new Object(); //line 2
obj = null; //3
Edit: it is asking when the object created at line 1 can be eligible for garbage collection.
In the real world this question (as posed by the title) has no clear answer.
aggressive dead code elimination could eliminate the first object allocation since it never becomes visible
a modified Object Class (e.g. via bytecode instrumentation or bootstrap classloaders) could resurrect itself on finalization or hold onto additional references indefinitely
garbage collection is asynchronous and happens at an indefinite point in the future, so while an object may be inaccessible from java code it cannot be "considered" garbage collected until it actually has been garbage collected.It might show up in a heap dump after all, which can be relevant if it contained security-sensitive data
I know it's supposed to be an academic question with a simple answer, but there are so many assumptions to make that I could rule-lawyer you any answer you want into existence.
Even if we don't pull any rabbits out of our hat the answer would still depend on whether "at line X" means before or after the execution of that
The garbage collector is checking for live objects and discarding anything that is not. When you create obj, you define it's type because that allows the compiler to know how much space to allot for that address, because something of Type Object will exist there. When the second line executes, new is creating an entirely new instance of the object and you are assigning its address to obj. So after reassigning obj to reference a new object, the old one still exists, but is no longer referenced. It would potentially be marked for collection as it occupies space in the heap, but is no longer active. The same happens with line 3, except, as mentioned previously, you are assigning it an address of null, and no new object is being created. So what used to be referenced by obj are now dead objects and the garbage man takes them away.

Garbage Collection and InComplete Constructed Object

This may be a very naive Question?
Suppose i have Class Something like this
class SlowConstructor {
private final int a;
private final String unReachableString;
public SlowConstructor(String random) {
unReachableString = "I am not reachable will GC will collect me " + random;
Thread.sleep(1000*3600); // ignoring Exception check for readbility
a = 100;
Thread.sleep(1000*3600);
}
}
So my question is if i create Many Objects of SlowConstructor (let say 50 in diff threads) and as you can see each Constructor will take two hours to complete. The String reference in SlowConstructor unReachableString is not reachable from any code for around two hours. If GC runs during this two hours will it not collect unReachableString ref ?. I assume it will not be Garbage Collected but then why? From where unReachableString is reachable ?
The String reference in SlowConstructor unReachableString is not reachable from any code for around two hours.
Incorrect. The SlowConstructor object is immediately reachable from the thread that is in the process of constructing it. So, therefore, is the string.
So that means that the String object won't be garbage collected before the constructor completes.
(And in fact, the string object corresponds to a String literal, and is therefore also reachable from the code (any code!) that assigns or applies a method to the literal.)
The concept of reachability includes any mechanism by which any current or future execution could use the object in question. That includes cases where the object hasn't been assigned to a named variable or array element ... yet.
As other have said GC is not going to affect a half-constructed object. But why? GC necessarily proceeds from a maximal set of root pointers. Anything that can be reached from these roots is "protected" from GC. This is either my marking as in mark-and-sweep collectors or by copying to a new active generation (arena) in a copying collector. Roots consist of the runtime stack, machine (virtual or physical) registers, and global pointers. When the constructor starts running, a pointer to the newly allocated record will be created. Either it will be a root or accessible from a root. So the GC will not collect it. Since the class instance under construction is accessible from a root, so is the string you're referring to. Therefore it can't be collected either.
So long as the threads weren't interrupted, your object will (eventually) instantiate, and (eventually) contain a value for unReachableString.
Strings are interned, and would be subject to garbage collection only if nothing referred to it - kind of like how garbage collection works now. The half-constructed object does refer to the interned string, so it would not be yet eligible for garbage collection.
I'm willing to bet that having fifty or so instances of this type floating around* wouldn't make a difference either - you then have fifty or so references to this string literal, and it wouldn't be yet eligible for garbage collection until these instances were eligible for garbage collection themselves.
*: OH GOD NO PLEASE DON'T DO THIS IN ACTUAL CODE PLEASE
It will not and should not be garbage collected. Sleeping thread is still a live thread.
Reachable in GC context means the following: if we go through the Stack will we find a reference pointing to this object (memory space) on the Heap.
In you case the answer is yes.
your logic is not correct, if thread is still alive it is in scope of method SlowConstructor. So JVM thinks that unReachableString string can be used so Garbacge Collection does not touch that reference.
According to the code you can assume that unReachableString is not used so it has to be Garbage Collected but JVM does not have intelligent logic to know the next. It just look at the scope of method and object reference.

Garbage collector in java - set an object null

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)

Categories

Resources