I have been going through the following tutorial , and I came across this code :
map.put(new String("Maine"), "Augusta");
just to experiment, I changed it to:
String hold = "Maine";
map.put(hold, "Augusta");
As a result, the loop goes on forever meaning that this object does not get garbage collected as it should, because we are using WeakHashMap. I have no idea why this is. What makes new String() different from String hold in this situation ?
also.. there is one more question - why does this map have to be static or else containKeys will give an error ?
As explained in the link you posted:
allows a key-value pair to be garbagecollected when its key is no
longer referenced outside of the WeakHashMap
So in first example, "Maine" string is not externally referenced by anything, so it will be garbage-collected eventually (when GC runs). In the second example, it is referenced from outside the WeakHashMap (by hold) and thus it is not garbage-collected.
When you declare the String hold, you are making a strong reference, this means that "Maine" should not be garbage collected because some variable outside the weakmap references that String.
On the initial example, the only reference to "Maine" was inside the weakmap so this reference is called "weak". The variable is then garbage collected
Related
I know that with a WeakReference, if I make a WeakReference to something that unless there's a direct reference to it that it will be Garbage Collected with the next GC cycle. My question becomes, what if I make an ArrayList of WeakReferences?
For example:
ArrayList<WeakReference<String>> exArrayList;
exArrayList = new ArrayList<WeakReference<String>>();
exArrayList.add(new WeakReference<String>("Hello"));
I can now access the data with exArrayList.get(0).get().
My question becomes: This is WeakReference data, will the data located at exArrayList.get(0) be GC'd with the next GC cycle? (even IF I don't make another direct reference to it) or will this particular reference stick around until the arraylist is emptied? (eg: exArrayList.clear();).
If this is a duplicate I haven't found it with my keywords in google.
exArrayList.add(new WeakReference<String>("Hello")); is a bad example because String literals are never GC-ed
if it were e.g. exArrayList.add(new WeakReference<Object>(new Object())); then after a GC the object would be GC-ed, but exArrayList.get(0) would still return WeakReference, though exArrayList.get(0).get() would return null
The data at exArrayList.get(0) is the WeakReference. It is not by itself a weak reference, so it will not be collected...
BUT the object referenced by exArrayList.get(0) is weakly referenced, so it might be GCed at any time (of course, that requires that there are no strong references to that object).
So
data.get(0) won't become null, but data.get(0).get() might become.
In other words, the list does not references the weak referenced object but the weak reference itself.
This is a bad idea as the other posters explained above (reference objects not freed). Use a WeakHashMap with the objects as keys and some dummy values ("" or Boolean.TRUE or similar).
I am reading about memory management in JVM and that if an object has no more references to it, it is garbage collected.
lets say, I have a program
public test {
public static void main(String[ ] args) {
String name = "hello";
for (int i =0 ; i < 5; i++) {
System.out.println(i);
}
}
}
As you can see, the String name is not used anywhere, so its reference is kept through out and not garbage collected.
now I have,
String name = "hello"
String name2 = name.substring(1,4)//"ell"
here again, the reference for hello must be present always, and cannot be garbage collected, since name2 uses it.
so when do these String or any objects get garbage collected, which have references but are obsolete, i.e. no longer used in code?
I can see one scenario where trimming down an array causes memory leak and hence setting its reference to null is a good way to garbage collect those obsolete references.
I can see one scenario where trimming down an array causes memory leak
and hence setting its reference to null is a good way to garbage
collect those obsolete references.
Strings are reference types, so all the rules for reference types with respect to garbage collection apply to strings. The JVM may also do some optimizations on String literals but if you're worrying about these, then you're probably thinking too hard.
When does the JVM collect unreferenced objects?
The only answer that matters is: you can't tell and it needn't ever, but if it does you can't know when that will be. You should never write Java code around deterministic garbage collection. It is unnecessary and fraught with ugliness.
Speaking generally, if you confine your reference variables (including arrays or collections of reference types) to the narrowest possible scope, then you'll already have gone a long way toward not having to worry about memory leaks. Long-lived reference types will require some care and feeding.
"Trimming" arrays (unreferencing array elements by assigning null to them) is ONLY necessary in the special case where the array represents your own system for managing memory, eg. if you are making your own cache or queue of objects.
Because the JVM can't know that your array is "managing memory" it can't collect unused objects in it that are still referenced but are expired. In cases where an array represents your own system for managing memory, then you should assign null to array elements whose objects have expired (eg. popped off a queue; J. Bloch, Essential Java, 2nd Ed.).
Technically, the JVM is not required to garbage-collect objects ever. In practice, they usually come behind a little while after the last reference is gone and free up the memory.
First, be aware that constants are always going to be around. Even if you assign a new value to name, the system still has a copy of "hello" stored with the class that it will reuse every time you hit that initializer statement.
However, don't confuse using an object for some sort of calculation with keeping a reference to it forever. In your second example, while "hello" is in fact kept around, that's just because it's living in the constant pool; name2 doesn't have any sort of "hold" on it that keeps it in memory. The call to substring executes and finishes, and there's no eternal hold on name. (The actual implementation in the Oracle JVM shares the underlying char[], but that's implementation-dependent.)
Clearing out arrays is a good practice because it's common for them to be long-lived and reused. If the entire array gets garbage collected, the references it holds get erased (and their objects garbage collected if those were the last ones).
Every variable in Java has a scope: The piece of code during which the variable is defined. The scope of a local variable like name in your example is between the brackets {} it is in. Thus, the name variable will be defined when the thread reaches the String name = "hello"; declaration, and will be kept alive until the main method is finished (because then the brackets the variable was in are closed).
Strings are a different story though than other variables. Strings are cached internally and may not actually be made available for the garbage collector yet.
String samplel = "ToBeGarbageCollected";
String sample2 = samplel.substring(0, 1);
samplel = null;
I know substring internally will keep a reference for original String.
But by explicitly defining samplel as null, will sample1 and sample2 be available for garbage Collection?
I remember seeing somewhere if a parent object is explicitly set to null all child values are available for garbage collection. Will this hold good for the above?
I am just curious if this the parent child relationship scenario? If not, will this cause sample1 or sample2 to be available for garbage collection?
String samplel = "ToBeGarbageCollected";
String sample2 = new String(samplel .substring(0, 1));
samplel = null;
First thing to say is that garbage collection doesn't happen immediately. So assigning null to anything does not / cannot cause garbage collection. What is may do is to cause an object to become unreachable ... and that will make it a potential candidate for garbage collection in a future GC run.
Now to your specific examples.
Important Note: the following only applies to older JVMs; i.e. Java 7 update 5 and earlier. In Java 7 update 6, they changed String.substring() so that the target string and resulting substring DO NOT share the backing array. This eliminates the potential storage leak issue with substring.
The substring method doesn't put a reference to the original String in the new String. What it actually does is save a reference to the original String's backing array; i.e the array that holds the characters.
But having said that, assigning null to samplel is not sufficient to make the state of the entire original string unreachable. The original String's entire backing array will be remain reachable ... and that means it won't be a candidate for garbage collection.
But there is another complication. You set sample1 to a String literal, and the String object that represents a String literal is always reachable (unless the entire class gets unloaded!)
But by explicitly defining samplel as null, will sample1 and sample2 be available for garbage Collection?
The original sample1 object will remain fully reachable, and sample2 will remain be reachable unless that variable goes out of scope.
If sample1 had not been a literal and there were no other references to it, then the answer would be different. The sample1 object would be unreachable, but its backing array would still be reachable via sample2.
In your second example, copying the substring causes a new String to be created. And it is guaranteed that the new String won't share the backing array with the original String and the temporary substring. In that case, assigning null is unnecessary.
Will now both sample1 and sample2 be available for garbage Collection?
The answer is the same as for the above for the case where sample1 is a literal.
If sample1 is not a literal and there are no other references to it, then sample1 and the temporary substring would now be unreachable.
I just want to know where does String constructor be helpful.
In theory it will be.
In practice it depends on whether the references are still reachable when the GC eventually gets around to looking ... and also on whether the Strings in question are large enough and numerous enough to have a significant impact on memory usage.
And in practice, that precondition is usually NOT satisfied and creating a fresh String like that usually does NOT help.
Remember that in Java String is immutable. In this case, sample1 will be discarded, but sample2 never pointed to sample1: it pointed to a separately held immutable string in the JVM that was created at the latest when substring was called.
When you set sample1 to null, the memory it pointed to became available for garbage collection (assuming no other strings held the same value and no other variables were pointed at that location). When you use the new keyword (or implicitly do so through the assignment of a primitive) new memory is allocated on the heap (usually; again, strings are immutable and share the same memory). If no pointers (read: any named variables) point to a given location of memory, it is available for garbage collection.
Remember: in any case where there are no references to an object, it becomes available for garbage collection. Objects are not defined by the variable names assigned to them, but rather are locations in memory, and the variable names act as pointers (references) to those objects. Strings are somewhat different because they are immutable, and the JVM may opt not to garbage collect for reasons independent of references to them.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Does setting Java objects to null do anything anymore?
I am using a same variable again and again in a method & referring it to a new object at many a times.. Is it a good practice from garbage collection aspect to nullify it before making it refer a new object.
Example:
StopWatch watch = new StopWatch();
watch.start();
//some code
watch.stop();
//some code
watch = null;
watch = new StopWatch();
watch.start();
//some code
watch.stop();
//some code
Not sure whether nullifying it make a difference to GC in this case. Please guide.
Thanks!
Assigning null at that point will make no difference, because you are immediately going to assign a new value to that variable.
There is nothing "magical" in Java about assigning null to a variable. It doesn't cause the object to be garbage collected immediately. All it is doing is breaking one of (possibly) many "paths" by which the object in question is reachable. If the path would break / disappear of its own accord before the next GC run, then assigning null achieves nothing.
Normally it is not worth nulling variables or fields in Java, and it is certainly not worth doing for a local variable is about to be overwritten, or is about to go out of scope.
No, nullifying will not make any difference in this case.
It would have made difference had it not been assigned to some other variable immediately. In that case, instead of waiting for the reference to go out of scope, the object would have become eligible for GC.
the GC generally collects those objects which do not have reference. As you are pointing the reference to some other object in memory, the reference to the previous object is anyways lost. Hence there is no difference if you assign null to it or not.
It will be available for garbage collection provider there is no other reference to it
When an object is available for garbage collection JVM assign null value to that object.
Normally it is not worth nulling variables or fields in Java, and it is certainly not worth doing for a local variable is about to be overwritten, or is about to go out of scope.
It will not make any difference as you are immediately assigning a new object after nullifying
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.