Is it a good practice to remove references to help the GC? - java

I am wondering whether you would consider it a good practice to remove references (setting them to null) to objects in order to help the Java Garbage Collector.
For instance, let's say you have a class with two fields, one of them being very memory-consuming. If you know you only need it for a particular processing, you can null it right after to help the GC.
Assume I really need those two to be fields, and not only internal variables, so heavyObject1 cannot be out of scope at the end of the method.
Would you do this as a general practice?
public class TestClass {
public static Object heavyObject1;
public static Object object2;
private static void action() {
object2 = doSomething(heavyObject1);
heavyObject1 = null; //is this good?
}
}

Usually it isn't needed.
It's a good idea in the following specific circumstance:
The object is large (i.e. large enough for you to care)
You are sure the object won't be needed again
The object won't go out of scope otherwise (e.g. you know the surrounding object won't be garbage collected)
However if you find yourself in this situation I suspect you have a design smell anyway: why does the internal object have such a different scope / lifetime from the enclosing object? This makes me suspicious, because usually when you build up an object graph with composition you expect the composed objects to have similar lifetimes.

In most of the cases, you dont need to set the object to null to be garbage collected.If you decalre the object in proper scope(method level,instance level or class level), the object will be unreachable immediately after its use and will be eligible for garbage collection.

It's certainly not bad practice to assign null to references if you don't want to use that object anymore. However, it is bad practice to count on the GC to collect them at any point soon or at all during your program's execution.

No, it's unnecessary. As soon as heavyObject1 is out of scoped, it'll be marked for GC anyway.

As a general practice, no, because it is not needed.
There are special cases -- I can imagine a long-lived class, for instance, that has a long list of memory consuming objects with which it does something one time and then waits for a period before replacing that list with another list. Might as well null the list while you're waiting, won't hurt anything, and may prevent the program from having to end up with both lists at the same time.
But therein lies the "not needed" principle again. You can't count on the GC to run during particular period, so the program needs to support having both these lists on the heap at the same time, so it doesn't make your program viable if it was not so before.
And let's PLEASE not encourage people to make a 'rule' about it. When I think of all the code I've read where someone puts "final" in front of (nearly) all the variables that (they think) won't change after initialization, making the code less readable and convincing me that the programmer had no understanding of the speed improvement they were supposedly making...

No. It is not generally good practice to null fields or locals.
In most cases the object whose field you are nulling is going to become unreachable before the GC runs. If that happens, the CPU cycles you spent nulling the object's field are going to be wasted.
The only situations where it is necessary / good to null fields / locals are where:
it is likely that the parent object will still be reachable when the GC runs, AND
the child object (graph) is large enough for the amount of memory retained to be significant ... relative to the total heap size.
You might also do it if you are implementing a class that is intended to be used in a wide range of situations ... and some of those situations could fit the criteria above. (For instance, a data structure implementation where the instances could grow large.)

Dereferencing objects is unnecessary unless your class is managing its own memory or your class is caching resources, then obsolete references should be eliminated.

Related

Java - Do object references get destroyed when the creating class is closed?

Say i have a class, which loads a file and then calls another method to do something to that file. For example, counting the words in the file.
Within class CountWords, a number of objects/collections are created in order to get the number of words. The method runs, the number of words is found, and then this is returned to the calling class.
My question is, do all the objects/collection created in the CountWords class get "destroyed" when control is returned to the calling class or do they remain in the memory? If the latter, would i have to set each object to null before exiting the class to mark them for collection?
We don't generally control exactly when a Java object gets destroyed. It will get destroyed some time after it becomes inaccessible - in other words, when there are no further references to it in any scope.
If you create an object, and store a reference to it in a field of another object, then the object you created continues to be accessible for as long as the object that has the reference to it is accessible.
If you have code like this
public void run() {
Foo a = new Foo();
System.out.println("This method is finished");
}
then the Foo that you created will be inaccessible as soon as run finishes, because there are no more variables with references to it. Foo will be destroyed some time afterwards. Unless of course, the constructor of Foo does some magic to register itself in some nasty static data store somewhere.
So in general, you don't need to go round setting references to null to destroy objects. From the point of view of the garbage collector, letting those references go out of scope is just as good as setting them to null.
Java is a programming language that has memory management aka garbage collection. The basic answer is, the garbage collector will take care of reclaiming the memory of unused objects.
But since you have tagged the question with [garbage-collection], you should already know this. So it’s not clear what additional detail you want to know or why you think your scenario is special in any way, to deserve an additional answer beyond “there is a garbage collector”.
You question is full of phrases that are wrong or misguiding.
“do object references get destroyed”—the storage of objects is reclaimed, there is no such thing as “destruction of references”
“when the creating class is closed”—there is no such thing as “closing of classes”
“do all the objects/collection created in the CountWords class get ‘destroyed’ when control is returned to the calling class or do they remain in the memory?”—in this form, not simple to answer
there is no such thing as “destruction”. The whole purpose of garbage collection is to permit the reuse of the memory. This implies recording somewhere that the memory is free. But the memory itself does not need to be touched.
when your method returns, these objects are eligible for garbage collection. The garbage collection itself does not have to run immediately. It may happen when there is need for free memory or when the CPU load is low.
As said, even if the garbage collector ran, the result is that the memory is now considered to be free, not necessarily to “scrub” the memory. So the objects may “remain in the memory” until actually being overwritten by other objects. So that’s simply the wrong question. You actually want to know whether the memory will be reusable.
“If the latter, would i have to set each object to null before exiting the class to mark them for collection?”—“the latter” still implies that the memory is free, semantically. But what do you want to “set to null”? The references do not exist anymore. The objects are unreachable.
The answer is there is nothing you can do and there is nothing you should do. That’s the whole point of garbage collection, no need for you to do anything.
We don't need to set the objects to null after coming out the function . For this Java have garbage Collector , which runs on the Java Virtual Machine which gets rid of objects which are not being used by a Java application anymore. It is a form of automatic memory management.
For example :
for (int i =0 ; i<10 ; i++) {
String s = String.valueOf(i)
}
In the above code, the integer s is being created on each iteration of the for loop. This means that in every iteration, a little bit of memory is being allocated to make a integer object.
Going back to the code, we can see that once a single iteration is executed, in the next iteration, the integer object that was created in the previous iteration is not being used anymore -- that object is now considered "garbage".
Eventually, we'll start getting a lot of garbage, and memory will be used for objects which aren't being used anymore. If this keeps going on, eventually the Java Virtual Machine will run out of space to make new objects.
That's where the garbage collector steps in.
The garbage collector will look for objects which aren't being used anymore, and gets rid of them, freeing up the memory so other new objects can use that piece of memory.
Automatic memory management schemes like garbage collection makes it so the programmer does not have to worry so much about memory management issues, so he or she can focus more on developing the applications they need to develop.

Unset instance when have few memory

I have a method that create some heavy objects as cache. This objects are rarely accessed, but expensive and slow to process, and are initialized only on demand. Then on use my application, for instance, I could request about three heavy object like that, and reuse them, but too is possible that I run it once and it only occupy memory while I never use it anymore during a session.
My question is: is possible I define that an object is "garbage collectable", then in case of application requires more memory it unset this unused data?
I think that it should works something like that (pseudo-code):
private static MyInstance instance = null;
public static getInstance() {
if (instance == null) {
instance = calculate();
GC.put(instance);
}
return instance;
}
I think that I can do it with some kind of Timer, then check from time to time, but I guess that Java should have something like that, to call only if memory is heavy used.
Yes, Java offers three types of indirect references which are sensitive to memory usage.
A cache can use a SoftReference that will be cleared before the process raises an OutOfMemoryError. As long as there is plenty of memory, however, the SoftReference will prevent its referent from being garbage collected.
Java does not have a way to manually de-allocate memory (see Memory Management in Java. However, it does have automatic garbage collection. This means that any object that has no references left in the program will be automatically removed. In your case, for example, if an Instance is no longer used (the function that used it returns, and no other references exist, or you overwrite the sole variable that stored a reference to the Instance with something else), that Instance will be garbage-collected.
There is not, however, any method of making the Instance disappear any faster than getting rid of references to it, and letting the garbage collector deal with it.
What I would suggest instead, for your application, is something like an LRU cache (see How would you implement an LRU cache in Java?), which would restrict your memory usage to a set number of instances, which (depending on what exactly Instance is) would limit you to a set amount of memory used by Instances.
If you wanted instead to allow any amount of memory to be used, but not used for very long, you could create a wrapper class for Instance, which implements your cache idea (only creates an Instance when called, if its current copy is null), but keeps a timer and sets its Instance to null after a given amount of time has expired without it being used.
What you need is a proper cache implementation. There are tons of them in Java, e.g., Guava Cache, which is highly configurable.
Your calculate method is just CacheLoader#load.
You don't need to care about the GC. Just size your cache properly so that not too much memory gets used. Evicted cache entries get collected automaticaly (when not referenced elsewhere).
I think that I can do it with some kind of Timer, then check from time to time, but I guess that Java should have something like that, to call only if memory is heavy used.
You can use time based eviction with e.g. CacheBuilder#expireAfterWrite. There's no caching in Java itself, but there's SoftReference. Anyway, I don't recommend using it directly, but consider using it with CacheBuilder#softKeys.

When to create variables (memory management)

You create a variable to store a value that you can refer to that variable in the future. I've heard that you must set a variable to 'null' once you're done using it so the garbage collector can get to it (if it's a field var).
If I were to have a variable that I won't be referring to agaon, would removing the reference/value vars I'm using (and just using the numbers when needed) save memory? For example:
int number = 5;
public void method() {
System.out.println(number);
}
Would that take more space than just plugging '5' into the println method?
I have a few integers that I don't refer to in my code ever again (game loop), but I've seen others use reference vars on things that really didn't need them. Been looking into memory management, so please let me know, along with any other advice you have to offer about managing memory
I've heard that you must set a variable to 'null' once you're done using it so the garbage collector can get to it (if it's a field var).
This is very rarely a good idea. You only need to do this if the variable is a reference to an object which is going to live much longer than the object it refers to.
Say you have an instance of Class A and it has a reference to an instance of Class B. Class B is very large and you don't need it for very long (a pretty rare situation) You might null out the reference to class B to allow it to be collected.
A better way to handle objects which don't live very long is to hold them in local variables. These are naturally cleaned up when they drop out of scope.
If I were to have a variable that I won't be referring to agaon, would removing the reference vars I'm using (and just using the numbers when needed) save memory?
You don't free the memory for a primitive until the object which contains it is cleaned up by the GC.
Would that take more space than just plugging '5' into the println method?
The JIT is smart enough to turn fields which don't change into constants.
Been looking into memory management, so please let me know, along with any other advice you have to offer about managing memory
Use a memory profiler instead of chasing down 4 bytes of memory. Something like 4 million bytes might be worth chasing if you have a smart phone. If you have a PC, I wouldn't both with 4 million bytes.
In your example number is a primitive, so will be stored as a value.
If you want to use a reference then you should use one of the wrapper types (e.g. Integer)
So notice variables are on the stack, the values they refer to are on the heap. So having variables is not too bad but yes they do create references to other entities. However in the simple case you describe it's not really any consequence. If it is never read again and within a contained scope, the compiler will probably strip it out before runtime. Even if it didn't the garbage collector will be able to safely remove it after the stack squashes. If you are running into issues where you have too many stack variables, it's usually because you have really deep stacks. The amount of stack space needed per thread is a better place to adjust than to make your code unreadable. The setting to null is also no longer needed
It's really a matter of opinion. In your example, System.out.println(5) would be slightly more efficient, as you only refer to the number once and never change it. As was said in a comment, int is a primitive type and not a reference - thus it doesn't take up much space. However, you might want to set actual reference variables to null only if they are used in a very complicated method. All local reference variables are garbage collected when the method they are declared in returns.
Well, the JVM memory model works something like this: values are stored on one pile of memory stack and objects are stored on another pile of memory called the heap. The garbage collector looks for garbage by looking at a list of objects you've made and seeing which ones aren't pointed at by anything. This is where setting an object to null comes in; all nonprimitive (think of classes) variables are really references that point to the object on the stack, so by setting the reference you have to null the garbage collector can see that there's nothing else pointing at the object and it can decide to garbage collect it. All Java objects are stored on the heap so they can be seen and collected by the garbage collector.
Nonprimitive (ints, chars, doubles, those sort of things) values, however, aren't stored on the heap. They're created and stored temporarily as they're needed and there's not much you can do there, but thankfully the compilers nowadays are really efficient and will avoid needed to store them on the JVM stack unless they absolutely need to.
On a bytecode level, that's basically how it works. The JVM is based on a stack-based machine, with a couple instructions to create allocate objects on the heap as well, and a ton of instructions to manipulate, push and pop values, off the stack. Local variables are stored on the stack, allocated variables on the heap.* These are the heap and the stack I'm referring to above. Here's a pretty good starting point if you want to get into the nitty gritty details.
In the resulting compiled code, there's a bit of leeway in terms of implementing the heap and stack. Allocation's implemented as allocation, there's really not a way around doing so. Thus the virtual machine heap becomes an actual heap, and allocations in the bytecode are allocations in actual memory. But you can get around using a stack to some extent, since instead of storing the values on a stack (and accessing a ton of memory), you can stored them on registers on the CPU which can be up to a hundred times (maybe even a thousand) faster than storing it on memory. But there's cases where this isn't possible (look up register spilling for one example of when this may happen), and using a stack to implement a stack kind of makes a lot of sense.
And quite frankly in your case a few integers probably won't matter. The compiler will probably optimize them out by itself in this case anyways. Optimization should always happen after you get it running and notice it's a tad slower than you'd prefer it to be. Worry about making simple, elegant, working code first then later make it fast (and hopefully) simple, elegant, working code.
Java's actually very nicely made so that you shouldn't have to worry about nulling variables very often. Whenever you stop needing to use something, it will usually incidentally be disappearing from the scope of your program (and thus becoming eligible for garbage collection). So I guess the real lesson here is to use local variables as often as you can.
*There's also a constant pool, a local variable pool, and a couple other things in memory but you have close to no control over the size of those things and I want to keep this fairly simple.

Resource Handling Practice

It's assured that Garbage Collector destroys all the unwanted and unused objects,
what if we manually nullify the objects eg. List<String> = null ,
does this action makes any negative or positive performance effect?
I am on Java.
Thanks.
Not an expert on details of memory handling but I can share what I know. GC will collect whatever is not used. Thus when you eliminate the last reference to an object (by explicitly nullifying) you'll be marking it for garbage collection. This does not guarantee that it'll be collected immediately.
You can explicitly try and invoke GC but you'll see lots of people advising against it. My understanding is that the call to GC is unreliable at best. The whole point with GC and Java is that you as a programmer should not need to worry much about the memory allocation. As for performance, unless you have tight limitations for heap space, you shouldn't notice GC activity.
Garbage collection is a way in which Java recollects the space occupied by loitering objects. By doing so, it [Java] ensures that your application never runs out of memory (though we cannot be assured that the program will ever run out of memory).
It is suggested to leave it on JVM.
Read related : Does setting Java objects to null do anything anymore?
Explicit nulling makes little or no difference. Usually the GC can reliably detect when an object can no longer be reached, and can thus be GCd.
Particularly, nulling stack (i.e. inside methods) variables helps absolutely nothing. It's trivial to for the runtime to automatically detect when they will be needed and when not. nulling heap (i.e. inside classes) variables could in some rare instances help, but that's a rare exception, and probably does more harm (in code legibility/maintainability) than good.
Also note that nulling doesn't guarantee if, or when, an object will be GCd.

can any unused object escape from Garbage Collector?

Is there any possibility that a object which is not referenced anywhere and still existing on heap. I mean is there a possibility that a unused object getting escaped from garbage collector and be there on the heap until the end of the application.
Wanted to know because if it is there, then while coding i can be more cautious.
If an object is no longer referenced, it does still exist on the heap, but it is also free to be garbage-collected (unless we are talking Class objects, which live in PermGen space and never get garbage-collected - but this is generally not something you need to worry about).
There is no guarantee on how soon that will be, but your application will not run out of memory before memory from those objects is reclaimed.
However, garbage collection does involve overhead, so if you are creating more objects than you need to and can easily create less, then by all means do so.
Edit: in response to your comment, if an object is truly not referenced by anything, it will be reclaimed during garbage collection (assuming you are using the latest JVM from Sun; I can't speak toward other implementations). The reason why is as follows: all objects are allocated contiguously on the heap. When GC is to happen, the JVM follows all references to "mark" objects that it knows are reachable - these objects are then moved into another, clean area. The old area is then considered to be free memory. Anything that cannot be found via a reference cannot be moved. The point is that the GC does not need to "find" the unreferenced objects. If anything, I would be more worried about objects that are still referenced when they are not intended to be, which will cause memory leaks.
You should know that, before a JVM throws an out-of-memory exception, it will have garbage collected everything possible.
If an instance is no longer referenced, it is a possible candidate for garbage collection. This means, that sooner or later it can be removed but there are no guaranties. If you do not run out of of memory, the garbage collector might not even run, thus the instance my be there until the program ends.
The CG system is very good at finding not referenced objects. There is a tiny, tiny chance that you end up keeping a weird mix of references where the garbage collector can not decide for sure if the object is no longer referenced or not. But this would be a bug in the CG system and nothing you should worry about while coding.
It depends on when and how often the object is used. If you allocate something then deallocate (i.e., remove all references to it) it immediately after, it will stay in "new" part of the heap and will probably be knocked out on the next garbage collection run.
If you allocate an object at the beginning of your program and keep it around for a while (if it survives through several garbage collections), it will get promoted to "old" status. Objects in that part of the heap are less likely to be collected later.
If you want to know all the nitty-gitty details, check out some of Sun's gc documentation.
Yes; imagine something like this:
Foo foo = new Foo();
// do some work here
while(1) {};
foo.someOp(); // if this is the only reference to foo,
// it's theoreticaly impossible to reach here, so it
// should be GC-ed, but all GC systems I know of will
// not Gc it
I am using definition of: garbage = object that can never be reached in any execution of the code.
Garbage collection intentionally makes few guarantees about WHEN the objects are collected. If memory never gets too tight, it's entirely possible that an unreferenced object won't be collected by the time the program ends.
The garbage collector will eventually reclaim all unreachable objects. Note the "eventually": this may take some time. You can somewhat force the issue with System.gc() but this is rarely a good idea (if used without discretion, then performance may decrease).
What can happen is that an object is "unused" (as in: the application will not use it anymore) while still being "reachable" (the GC can find a path of references from one of its roots -- static fields, local variables -- to the object). If you are not too messy with your objects and structures then you will not encounter such situations. A rule of thumb would be: if the application seems to take too much RAM, run a profiler on it; if thousands of instances of the same class have accumulated without any apparent reason, then there may be some fishy code somewhere. Correction often involves explicitly setting a field to null to avoid referencing an object for too long.
This is theoretically possible (there is no guarantee the GC will always find all objects), but should not worry you for any real application - it usually does not happen and certainly does not affect a significant chunk of memory.
In theory, the garbage collector will find all unused objects. There could, of course, be bugs in the garbage collector…
That said, "In theory there is no difference between theory and practice, in practice, there is." Under some, mostly older, garbage collectors, if an object definition manages to reach the permanent generation, then it will no longer be garbage collected under any circumstances. This only applied to Class definitions that were loaded, not to regular objects that were granted tenured status.
Correspondingly, if you have a static reference to an object, that takes up space in the "regular" object heap, this could conceivably cause problems, since you only need to hold a reference to the class definition from your class definition, and that static data cannot be garbage collected, even if you don't actually refer to any instances of the class itself.
In practice though, this is a very unlikely event, and you shouldn't need to worry about it. If you are super concerned about performance, then creating lots of "long-lived" objects, that is, those that escape "escape-analysis", will create extra work for the garbage collector. For 99.99% of coders this is a total non-issue though.
My advice - Don't worry about it.
Reason - It is possible for a non-referenced object to stay on the heap for some time, but it is very unlikely to adversely affect you because it is guaranteed to be reclaimed before you get an out of memory error.
In general, all objects to which there are no live hard references, will be garbage-collected. This is what you should assume and code for. However, the exact moment this happens is not predictable.
Just for completeness, two tricky situations [which you are unlikely to run into] come into my mind:
Bugs in JVM or garbage collector code
So called invisible references - they rarely matter but I did have to take them into account one or two times during the last 5 years in a performance-sensitive application I work on

Categories

Resources