I sometimes assume that if oldObject != newObject then the object has changed - which seems a fair assumption in most cases but is it truly a bad assumption?
In short, under what situation could the following code print "Same!"?
static WeakReference<Object> oldO = null;
...
Object o = new Object();
oldO = new WeakReference(o);
// Do some stuff with o - could take hours or even days to complete.
...
// Discard o (or let it go out of scope).
o = null;
// More stuff - could be hours or days later.
...
o = new Object();
// Later still.
if ( o == oldO.get() ) {
System.out.println("Same!");
}
I realise that this is indeed remotely possible because an object reference is essentially the memory address of the object (or could be in some JVM). But how likely is it? Are we talking decades of run-time before it actually happens?
Added
My apologies - please assume that oldO is some form of weak reference that does not stop it from being collected. Perhaps it is Weak as the code (now) suggests or the reference is store in a database or a file somewhere.
(I'm answering what I think what you really wanted to know, rather than the particular snippet you have)
It's implementation dependant. The contract of object reference is that as long as the object is still alive, no other object will compare == with it. This implies that after the object is garbage collected, the VM is free to reuse the same object reference.
Implementation of Java may choose to use an increasing integer for object reference, in which case you can only get the same object reference when the reference counter overflows back to 0. Other implementation may use memory location, which makes it more likely for the same reference to be reused. In any case, you should define your own object identity if that matters.
never will it be the same. oldO will always reference the initial object so it will never be discarded and new object can't have same address.
UPDATE: seems like answer was updated to specify that oldO is a weak reference. In this case, when the object goes away, oldO's reference will become null. This means it will never match another object in the JVM.
It is not possible for them to be equal. You still have a reference to the old object (oldO), so it will never be discarded.
o == oldO means ois the same memory address as oldO. So, that cannot happen unless, at some time, you are doing either o = oldO or oldO = o. By transitivity, doing foo = o; oldO = foo or anything equivalent will achieve the same result, of course.
Firstly, memory address is irrelevant. Java ain't C. Object identity is a JVM implemention - it may, or may not, rely on memory address, but more likely does not, since the JVM is free to move the object around in memory but must maintain its identity.
But regardless. because you hold a reference to the original object, the second one can not be the "same" object.
It will never happen.
Your first object (oldO) is stored at a specific memory location.
Your second object will systematically be referenced at another memery location, as long as oldO is referenced.
So oldO == o will compare both memory addresses, which will always be different.
If you dereference oldO, it will be garbage collected, and you'll eventuelly be able to create a new object at this same address. But you won't be able to compare it with oldO, because it has been dereferenced.
By having a reference to your old object, you prevent it being garbage collected, so you prevent that bit of memory being available for a new object, so they could never be equal.
I wondered if you used a SoftReference you could keep a reference to the old object, while allowing it to be garbage-collected BUT:
1) I assume once the old object is collected, the SoftReference is set to null and
2) this is artificially trying to force the situation, so doesn't really prove anything :-)
According to the documentation, weak references will be cleared when the object is garbage collected. It does not specify what it means to be "cleared", but presumably it is set to null. If it is in fact set to null, null will never be declared == to any object reference, regardless of its memory location.
Related
I have a very basic question regarding weak reference and strong reference in Java.
In general Java programming we generally do not create weak reference of object, we create normal strong reference but when we are done with that object we assign null to that object with the conception that, that object will be collected by GC next time.
Is that my understanding is wrong?
After reading some of the articles, it looks like, object is collected by GC If it is null or not referred anywhere if only it has weak reference. I am confused.
In other word what is the difference between these two code snippets, in respect to Java GC?
Snippet 1
Counter counter = new Counter(); // strong reference - line 1
WeakReference<Counter> weakCounter = new WeakReference<Counter> (counter); //weak reference
counter = null;
Snippet 2
Counter counter = new Counter(); // strong reference - line 1
counter = null;
In both cases, counter will be eligible for garbage collection. Even if you use SoftReference, it will be eligible for GC, but it will only be collected reluctantly. (That is, a SoftReference encourages the GC to leave the object in memory, but still allows it to be collected.)
Only hard references force the GC to leave objects alone.
Normally you only need to assign null to a reference if the reference has longer life than you want for the object. Once a hard-reference variable goes out of scope, it is no longer reachable from live code so its hard reference will not prevent the GC from collecting the object.
Note also that there's no guarantee as to when objects eligible for collection will actually be collected by the GC. It may be on the next GC cycle or maybe not. It depends heavily on the implementation of the GC. The only thing you can say for sure is that all eligible objects will be collected before the VM throws an OutOfMemoryError.
The difference is that if I remeber correctly,
The First code snippit assigns the value null to the object counter after it has been assigned to weakCounter. So therfor weakCounter still has the reference to the old counter without the reference to counter being updated. But the counter is still collected by the compiler, even though the weakCounter is assigned to an object reference of Counter
In the second code example, the counter goes from being assigned to a object to a null value letting java know "hey you can collect me in the garbage!"
Hope this made sense and it helped your understanding if some of my facts are wrong please feel free to tell me where I am mistaken :)
The two are essentially equivalent, save for the fact that you might be able to reference the object through the WeakReference if you do so before GC collects it.
The purpose of the WeakReference is so you can have it stashed somewhere (eg, some sort of search index) and not worry about having to clear it if you are done with the object and wish to null any "strong" references (so that the object may be collected and the space reused). If you used an ordinary strong reference you'd have to be sure to clear it or the object would hang around forever.
(SoftReferences, as mentioned by Ted Hopp, are similar in mechanics, except that GC will only collect the referenced objects if storage is tight. This makes them suitable for things like cached internet pages.)
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.
You have one big object in java. it has got 4 or five references. you don't know all those references. At time on deletion you know only one reference and you want to delete that object completely. How to achieve that? and also if you want to know other references then to what is the best way to do that.
It is not in our hand.. You can just nullify it from your end..
Object a = new Object();
a = null; // after that, if there is no live thread which is accessing members,it will be deleted by garbage collector
You could try Finalize() or System.runFinalization() but frankly, if there are references still pointing to the object, then I think the GC will ignore your request.
It is not possible in Java.
If you have strong reference referring your object, you cannot force JVM to GC that object. It simply cannot guarantee the program will work.
If codes of all other references are in your control, consider changing them to use WeakReference or SoftReference
There are some things that are not in our hands and its better to leave it to the JRE to handle it. All we can do that we make sure that the we make them null explicitly after using them.
{
// Some block
HugeObject obj = HugeObject.getInstance();
// Use it
obj = null;
}
// end of block
Java memory handling is just built to prevent that. An object is guaranteed to live as long as a reference to this object exists. As far as I know there is no (official) way to get to know the other references to an object (and there should be no need for that).
In Java GC(Garbage collector) handles heap cleanup. If an Object has no live references to it then it will automatically be cleaned up. So you need to make sure there are no live references to the Object.
Making it null is one of the way. But it will not guarantee it's cleanup if there is some other Object pointing to the same reference. That is why writing good code involves closing all the resources after use which includes making it to null.
If you are running low on heap you can try increasing heap size or calling System.gc() but again calling gc manually does not guarantee gc will actually be performed. it depends on lot of parameters which are JVM dependent.
What kind of references are these to the object? Are these references created by you and at runtime you don't keep track of of those references. If this is the case, you can wrap your references to the object in soft/ weak reference and then explicitly run the GC request. Otherwise, on runtime, if any live thread has access to the object. GC shall not delete that object.
It is hard to answer no knowing your use case, but if there is one location that you want to be able to remove it from then you can store every other reference to it as a WeakReference. Java normally uses strong refrences when referencing objects and the GC will only clear something when it has no more strong references. However, if you use WeakRefrences and your strong refrence ever goes out of scope there is no guarantee that your data will remain even if it is still needed.
I could be mistaken about this though, as I haven't used this class in a year or two.
On WeakReferences:
http://docs.oracle.com/javase/7/docs/api/java/lang/ref/WeakReference.html
You can declare your objects as WeakReference and add them in ReferenceQueue. In this way , whenever your object will not be further referenced , it will be liable for GC.
/**
Initialize the reference queue , even if you don't do it , no problem . Default reference queue will be taken.
**/
ReferenceQueue<? super Object> testReferenceQueue = new ReferenceQueue<Object>();
Map<String,String> demoHashMap = new HashMap<String,String>();
demoHashMap.put("SomeValue","testValue");
// Declare the object as weak object and put it in reference queue
WeakReference<?> weakObject = new WeakReference<Object>(demoHashMap,testReferenceQueue );
demoHashMap.clear();
demoHashMap = null; // This object is not referenced from anywhere
if(weakObject!=null){
System.out.println("Object is not GCd yet");
}else{
System.out.println("It is already garbage collected");
}
I have following code:
void method() {
Object o1 = new Object();
{
Object o2 = new Object();
System.out.println(o2);
}
// any long operation
}
will o2 object be eligible for garbage collection during execution of long operation?
The JLS definition of reachability is:
"A reachable object is any object that can be accessed in any potential continuing
computation from any live thread."
In this case, the reference ceases to be theoretically accessible to ongoing combutations before the println call returns. (I'm assuming that println(o2) doesn't save its the reference somewhere.)
However, in practice no JVMs in existence can tell that the Object becomes unreachable during the call, and most JVMs will only notice this when ... or after ... o2 goes out of scope. And even then, a GC run is not guaranteed to remove the object.
Note: that doesn't contradict the JLS, because the "reachable object" test is really telling you when the object won't be garbage collected, not when it will be. The JLS is careful to specify that an object may be finalized and garbage collected at some point after it becomes unreachable, but that it also may never be finalized and garbage collected.
yes however this will depend on whether the JVM/JIT won't optimize this to avoid superfluous stack operations
which would make it
Object o1 = new Object();
Object o2 = new Object();
System.out.println(o2);
// any long operation
many compilers will group all local variable needed and figure out the maximum needed space to keep them all (and some will be eliminated and just kept in registers) and grow the stack accordingly and only shrink it after the function can return
this would mean that o2 will remain in "accessible" memory according to GC unless it was overwritten with another variable in another scope
You need to understand that your variable o2 and the OBJECT DESIGNATED BY o2 are different.
The variable o2 is actually a pointer (though Java prefers to call them "references") and occupies 4 or 8 bytes in the automatic stack frame. This storage is not garbage collected and only goes away when you return from the procedure (or possibly when you exit the {} brackets depending on compiler implementation).
The object "designated by" (pointed to by) o2 is essentially available for possible garbage collection as soon as the new Object() operation ends, and the existence of a pointer to it in o2 is all that prevents this. Once the variable o2 either no longer exists in a stack frame or has a different pointer value stored into it then the object is eligible to be collected.
So in your particular case the answer is "maybe". It depends on how the compiler and JIT handle the {}, along with a few "luck" issues as to whether, having exited the {} block (but not the method as a whole), the storage location for o2 is reused for something else.
No. Even though the object referenced by o2 is not reachable, it will not be garbage-collected. It is in a state between reachable and unreachable called "invisible" because the reference variable o2 is still on the stack.
To make the object garbage-collectible, assign o2 = null or put that block in another function.
source: A 2001 book on Java performance
Can someone explain the difference between the three Reference classes (or post a link to a nice explanation)? SoftReference > WeakReference > PhantomReference, but when would I use each one? Why is there a WeakHashMap but no SoftHashMap or PhantomHashMap?
And if I use the following code...
WeakReference<String> ref = new WeakReference<String>("Hello!");
if (ref != null) { // ref can get collected at any time...
System.gc(); // Let's assume ref gets collected here.
System.out.println(ref.get()); // Now what?!
}
...what happens? Do I have to check if ref is null before every statement (this is wrong, but what should I do)? Sorry for the rapid-fire questions, but I'm having trouble understanding these Reference classes... Thanks!
The Java library documentation for the java.lang.ref package characterizes the decreasing strength of the three explicit reference types.
You use a SoftReference when you want the referenced object to stay alive until the host process is running low on memory. The object will not be eligible for collection until the collector needs to free memory. Loosely stated, binding a SoftReference means, "Pin the object until you can't anymore."
By contrast, use a WeakReference when you don't want to influence the referenced object's lifetime; you merely want to make a separate assertion about the referenced object, so long as it remains alive. The object's eligibility for collection is not influenced by the presence of bound WeakReferences. Something like an external mapping from object instance to related property, where the property need only be recorded so long as the related object is alive, is a good use for WeakReferences and WeakHashMap.
The last one—PhantomReference—is harder to characterize. Like WeakReference, such a bound PhantomReference exerts no influence on the referenced object's lifetime. But unlike the other reference types, one can't even dereference a PhantomReference. In a sense, it doesn't point to the thing it points to, as far as callers can tell. It merely allows one to associate some related data with the referenced object—data that can later be inspected and acted upon when the PhantomReference gets queued in its related ReferenceQueue. Normally one derives a type from PhantomReference and includes some additional data in that derived type. Unfortunately, there's some downcasting involved to make use of such a derived type.
In your example code, it's not the ref reference (or, if you prefer, "variable") that can be null. Rather, it's the value obtained by calling Reference#get() that may be null. If it is found to be null, you're too late; the referenced object is already on its way to being collected:
final String val = ref.get();
if (null != val)
{
// "val" is now pinned strongly.
}
else
{
// "val" is already ready to be collected.
}
A link: https://community.oracle.com/blogs/enicholas/2006/05/04/understanding-weak-references
PhantomHashMap wouldn't work very well as get always returns null for phantom references.
Caches are difficult, so SoftHashMap might not work as well as you might think. However, I believe Google's collection library contains a general reference map implementation.
You should always check that get returns non-null. (Note, that not checking that the Reference reference itself is not-null.) In the case of interned strings it always will, but (as ever) don't try to be "clever" about it.
It should also be mentioned, as stated on the comment by Truong Xuan Tinh, here: http://blog.yohanliyanage.com/2010/10/ktjs-3-soft-weak-phantom-references/
That JRockit JVM implements weak/soft/phantom references differently than Sun JVM.
String str = new String("hello, world");
WeakReference<String> ref = new WeakReference<String>(str);
str = null;
if (ref != null) {
System.gc();
System.out.println(ref.get());
}
In this case, it will output null. The call to System.gc() is important here.