Is there any consequences of setting an reference to null in java? - java

If I have a reference pointing to some some java object, and do something like:
myObject=null;
Will the "lost data" of the old object be correctly freed by the JVM Garbage Collector? Something similar in C (with a pointer, would result in trash and a possible memory leak).
I am using null attribution in a java program and would like to now if it is "safe".

If myObject only holds memory ( say large internal array ), then setting this reference to null is enough.
If, on the other hand, it holds some other kind of resource that you've allocated ( Closeable, Thread, ExecutorService, etc ), you must take care to properly shut down these resources.
Even though some of them may have finalize method they may be called too late ( or even never ) for your system to have a desirable effect.
It is a very common mistake for somebody switching from C++ to Java, and I am guilty as charged here. In my first real Java project I would periodically run out of file handle, because I was not calling close after being done with them. Needless to say with a 512MB heap, GC would never feel the need to start finalizing my IO objects before it was too late.

Assuming that there are no other references to the object, this is a good way to free memory up for the GC. (Actually, aside from weak references and the like, it's basically the only way: make the object unreachable from any live variables.) Note that there is no schedule for when an object might get garbage collected once it becomes unreachable.
EDIT: As others have pointed out, setting myObject to null is unnecessary if myObject is going out of scope anyway. When the variable itself is no longer available as a path to reach the object it references, then it doesn't matter to the GC system whether or not it contains a reference or null.

Your assumption is correct, but you don't usually need to specifically do that.
Let's say your "myObject" is used in another object. At some point in the lifetime of your application's execution, this object will stopped being referenced by any other object, and thus will be marked for deletion by the GC. Them myObject will be marked for deletion as well. As soon as all references to a given object disappear, the GC will eventually reclaim the memory.
There are (rare) exceptions, like event handling, where the dependency between two objects cannot be properly automatically ended, and you may end up with a memory leak: when you subscribe to an event on another class, then the subscriber cannot be collected even when there's no "direct" references to it. In that specific case, it might be interesting to clear the link manually.

Yes, that is the purpose of the garbage collector in the JVM. The JVM may at some later time call the finalize method of the object, and then it may discard the associated storage.

Yes, it's sometimes a GOOD idea to set Java object references (pointers) null. This may (if there are no other references to the object) "free" the object sooner than would otherwise occur. This is especially helpful when you have large "networks" of intertwined objects.
At worst case, you're costing one additional memory store.

Yes, The object the reference pointed to is eligible for garbage collection (if there are no other live references to the object) when:
The method returns - if it was initially created with method local scope
Immediately - if it is an instance or class variable

Related

Garbage Created By Object that is Never Referenced

Is any garbage created by an object that is never referenced?
The example I am thinking of is using a static factory method to create an object then having that object perform a function but never creating a reference to it.
For Example:
LoggerFactory.getLogger(Foo.class).info("logging some stuff");
Does this just create an unreferenced object in eden space that will be garbage collected as soon as the next collection happens?
getLogger returns an instance - whether it creates a new one or returns a previously cached one is up to the LoggerFactory's implementation. If this object is no longer referenced from inside the factory in some way, it would be eligible for garbage collection.
Provided that getLogger() doesn't store the created Logger somewhere (which is quite possible), then yes. The garbage collector is very good at disposing short lived objects, so it should get GCd quite quickly.
Of course nobody would write that specific logging line, since it makes no sense.
Java GC works by periodically analyzing which objects are reachable via a chain of references. That does not depend on whether those objects ever were reachable in the first place.
Your question suggests that you think GC may watch for references to be reclaimed to determine which objects to collect. Although GC is not forbidden from doing so, it cannot rely exclusively on such a strategy, and I am unaware of any existing Java GC implementation employing it.
Does this just create an unreferenced object in eden space that will be garbage collected as soon as the next collection happens?
Maybe, maybe not. The Logger instance is referenced as this inside info()
E.g. if info() then creates an anonymous inner class or a this-capturing lambda and puts it on a task queue then the Logger instance may live longer than the line of code in your question.
In most scenarios it is likely still be very short-lived. But you cannot know that for certain from the single line of code.
On the other end of the spectrum the object may never be allocated on the heap in the first place, i.e. not even in eden space, due to Escape Analysis

how to destroy an object in java?

I encountered this question in an interview with following options:
How to destroy an object in java?
a. System.gc();
b. Runtime.getRuntime.gc();
c. object.delete();
d. object.finalize();
e. Java performs gc by itself, no need to do it manually.
The answer should be e?
what if e was not there? then ?
clearly c is not the answer. a and b will do gc for the whole application(question requires for one object).
I think it is d because finalize() is called just prior to gc(but is it necessary that after finalize gc is invoked ?) or I am wrong ? e must be there to answer this question ?
Answer E is correct answer. If E is not there, you will soon run out of memory (or) No correct answer.
Object should be unreachable to be eligible for GC. JVM will do multiple scans and moving objects from one generation to another generation to determine the eligibility of GC and frees the memory when the objects are not reachable.
To clarify why the other answers can not work:
System.gc() (along with Runtime.getRuntime().gc(), which does the exact same thing) hints that you want stuff destroyed. Vaguely. The JVM is free to ignore requests to run a GC cycle, if it doesn't see the need for one. Plus, unless you've nulled out all reachable references to the object, GC won't touch it anyway. So A and B are both disqualified.
Runtime.getRuntime.gc() is bad grammar. getRuntime is a function, not a variable; you need parentheses after it to call it. So B is double-disqualified.
Object has no delete method. So C is disqualified.
While Object does have a finalize method, it doesn't destroy anything. Only the garbage collector can actually delete an object. (And in many cases, they technically don't even bother to do that; they just don't copy it when they do the others, so it gets left behind.) All finalize does is give an object a chance to clean up before the JVM discards it. What's more, you should never ever be calling finalize directly. (As finalize is protected, the JVM won't let you call it on an arbitrary object anyway.) So D is disqualified.
Besides all that, object.doAnythingAtAllEvenCommitSuicide() requires that running code have a reference to object. That alone makes it "alive" and thus ineligible for garbage collection. So C and D are double-disqualified.
Short Answer - E
Answer isE given that the rest are plainly wrong, but ..
Long Answer - It isn't that simple; it depends ...
Simple fact is, the garbage collector may never decide to garbage collection every single object that is a viable candidate for collection, not unless memory pressure is extremely high. And then there is the fact that Java is just as susceptible to memory leaks as any other language, they are just harder to cause, and thus harder to find when you do cause them!
The following article has many good details on how memory management works and doesn't work and what gets take up by what. How generational Garbage Collectors work and Thanks for the Memory ( Understanding How the JVM uses Native Memory on Windows and Linux )
If you read the links, I think you will get the idea that memory management in Java isn't as simple as a multiple choice question.
Set to null. Then there are no references anymore and the object will become eligible for Garbage Collection. GC will automatically remove the object from the heap.
Here is the code:
public static void main(String argso[]) {
int big_array[] = new int[100000];
// Do some computations with big_array and get a result.
int result = compute(big_array);
// We no longer need big_array. It will get garbage collected when there
// are no more references to it. Since big_array is a local variable,
// it refers to the array until this method returns. But this method
// doesn't return. So we've got to explicitly get rid of the reference
// ourselves, so the garbage collector knows it can reclaim the array.
big_array = null;
// Loop forever, handling the user's input
for(;;) handle_input(result);
}
In java there is no explicit way doing garbage collection. The JVM itself runs some threads in the background checking for the objects that are not having any references which means all the ways through which we access the object are lost. On the other hand an object is also eligible for garbage collection if it runs out of scope that is the program in which we created the object is terminated or ended.
Coming to your question the method finalize is same as the destructor in C++. The finalize method is actually called just before the moment of clearing the object memory by the JVM. It is up to you to define the finalize method or not in your program. However if the garbage collection of the object is done after the program is terminated then the JVM will not invoke the finalize method which you defined in your program.
You might ask what is the use of finalize method?
For instance let us consider that you created an object which requires some
stream to external file and you explicitly defined a finalize method to this object which checks wether the stream opened to the file or not and if not it closes the stream. Suppose, after writing several lines of code you lost the reference to the object. Then it is eligible for garbage collection. When the JVM is about to free the space of your object the JVM just checks have you defined the finalize method or not and invokes the method so there is no risk of the opened stream. finalize method make the program risk free and more robust.

Java de-allocate an object from the heap

In Java, to unload an object from the heap, is it sufficient to simply write myObject = null; and the GC will take care of it from there?
EDIT : Ok let me explain my use case, since everyone is assuming that I shouldn't explicitly null objects, I shouldn't worry about it, etc. That's missing the point. I am serializing an object, and am "consuming" a field of this object before I serialize it in order to save disk space. And before you jump down my throat for this, too, I cannot declare this field transient because I am including this field in the object sometimes, but not others.
Does setting an object to null have any effect on the GC?
In some modern VMs, actively setting a reference to null hinders the garbage collector. You should just forget about that.
For knowing when an object is garbage collected, look at the java.lang.ref package - although I can honestly say that in 16 years of Java programming, I've never needed to know when an object is garbage collected.
Can you elaborate on why you think you need this?
No; all references to that object must be lost/nulled. In practice this is something you shouldn't worry about.
Your object will be de-allocated when it is no longer used. Just be aware that any references left to the object will keep the object on the heap and simply assigning null to any single reference will not cause the underlying object to magically go away.
No, and no. myObject = null; will only help if there are no other references to the object, and in most cases it's superfluous because local objects go out of scope at the end of each method.
As for when objects are actually deallocated, that's completely up to the GC. What you can do is add a finalize method that will be called just before the object is deallocated, but this is problematic as well and should not be relied on.

What if a finalizer makes an object reachable?

In Java, finalize is called on an object (that overrides it) when it's about to be garbage collectioned, so when it's unreachable. But what if the finalizer makes the object reachable again, what happens then?
Then the object doesn't get garbage collected, basically. This is called object resurrection. Perform a search for that term, and you should get a bunch of interesting articles. As Jim mentioned, one important point is that the finalizer will only be run once.
The object will not be collected until it gets unreachable again.
According to the JavaDoc, finalize() will not be called again.
If you read the API description carefully, you'll see that the finalizer can make the object reachable again. The object won't be discarded until it is unreachable (again), but finalize() won't be called more than once.
Yeah, this is why you don't use finalizers (Well, one of the many reasons).
There is a reference collection that is made to do this stuff. I'll look it up and post it here in a sec, but I think it's PhantomReference.
Yep, PhantomReference:
Phantom reference objects, which are enqueued after the collector determines that their referents may otherwise be reclaimed. Phantom references are most often used for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.
It actually does another pass to check and make sure there are no more references to the object. Since it will fail that test on its second pass, you'll end up not freeing the memory for the object.
Because finalize is only called a single time for any given object, the next time through when it has no references, it will just free the memory without calling finalize. Some good information here on finalization.

Assigning "null" to objects in every application after their use

Do you always assign null to an object after its scope has been reached?
Or do you rely on the JVM for garbage collection?
Do you do it for all sort of applications regardless of their length?
If so, is it always a good practice?
It's not necessary to explicitly mark objects as null unless you have a very specific reason. Furthermore, I've never seen an application that marks all objects as null when they are no longer needed. The main benefit of garbage collection is the intrinsic memory management.
no, don't do that, except for specific cases such as static fields or when you know a variable/field lives a lot longer than the code referencing it
yes, but with a working knowledge of your VM's limits (and how to cause blocks of memory to be held accidentally)
n/a
I declare almost all of my variables as "final". I also make my methods small and declare most variables local to methods.
Since they are final I cannot assign them null after use... but that is fine since the methods are small the objects are eligible for garbage collection once they return. Since most of the variables are local there is less chance of accidentally holding onto a reference for longer than needed (memory leak).
Assignin null to a variable does not implicitly mean it will be garbage collected right away. In fact it most likely won't be. Whether you practice setting variables to null is usually only cosmetic (with the exception of static variables)
We don't practice this assigning "null". If a variable's scope has reached it's end it should already be ready for GC. There may be some edge cases in which the scope lasts for a while longer due to a long running operation in which case it might make sense to set it to null, but I would imagine they would be rare.
It also goes without saying that if the variable is an object's member variable or a static variable and hence never really goes out of scope then setting it to null to GC is mandatory.
Garbage collection is not as magical as you might expect. As long as an object is referenced from any reachable object it simply can't be collected. So it might be absolutely necessary to null a reference in order to avoid memory leaks. I don't say you should do this always, but always when it's necessary.
As the others have mentioned, it's not usually necessary.
Not only that, but it clutters up your code and increases the data someone needs to read and understand when revisiting your code.
Assigning is not done to objects, it is done to variables, and it means that this variable then holds a reference to some object. Assigning NULL to a variable is not a way to destroy an object, it just clears one reference. If the variable you are clearing will leave its scope afterwards anyway, assigning NULL is just useless noise, because that happens on leaving scope in any case.
The one time I tend to use this practice is if I need to transform a large Collection in some early part of a method.
For example:
public void foo() {
List<? extends Trade> trades = loadTrades();
Map<Date, List<? extends Trade>> tradesByDate = groupTradesByDate(trades);
trades = null; // trades no longer required.
// Apply business logic to tradesByDate map.
}
Obviously I could reduce the need for this by refactoring this into another method: Map<Date, List<? extends Trade>>> loadTradesAndGroupByDate() so it really depends on circumstances / clarity of code.
I only assign a reference to null when:
The code really lies in a memory-critical part.
The reference has a wide scope (and must be reused later). If it is not the case I just declare it in the smallest possible code block. It will be available for collection automatically.
That means that I only use this technique in iterative process where I use the reference to store incoming huge collection of objects. After processing, I do not need the collection any more but I want to reuse the reference for the next collection.
In that case (and only in that case), I then call System.gc() to give a hint to the Garbage Collector. I monitored this technique through heap visualizer and it works very well for big collections (more then 500Mb of data).
When using the .Net I don't think there's a need to set the object to null. Just let the garbage collection happen.
- Do you always assign null to an object after its scope has been reached?
No
- Or do you rely on the JVM for garbage collection?
Yes
- Do you do it for all sort of applications regardless of their length?
Yes
- If so, is it always a good practice?
N/A
I assume you're asking this question because you've seen code with variables being assigned to null at the point where they will never be accessed again.
I dislike this style, but another programmer used it extensively, and said he was taught to do so at a programming course at his university. The reasoning he gave is that it would prevent undetectable bugs if he tried to reuse the variable later on, instead of indeterminate behavior, he'd get a null pointer exception.
So if you're prone to using variables where you shouldn't be using variables, it might make your code more easy to debug.
There was a class of memory leak bugs that happened regardless of whether I set the reference to null - if the library I was using was written in a language like C without memory management, then simply setting the object to null would not necessarily free the memory. We had to call the object's close() method to release the memory (which, of course, we couldn't do after setting it to null.)
It thus seems to me that the de facto method of memory management in java is to rely on the garbage collector unless the object/library you're using has a close() method (or something similar.)

Categories