do you need to null objects? - java

duplicate - How to destroy java objects?
My question is very simple. I am new to app development with Java and am not sure whether I need to null objects after i am finished with them. for example i am using libGDX to create a game and I have several objects (Actors) being created. when I am finished with them do I simply call
obj.remove();
or should i -
obj.remove();
obj = null;
do I save memory by nulling objects or is there no advantage to be had?

No you do not need to null or manually delete objects. The java garbage collector will do this for you for any objects that have no pointers referencing them (when an object goes out of scope for example).

Generally, in java, marking the Object references as null is done to make it explicitly eligible for GC. If an object is unreachable, then it becomes eligible for GC, so, yes, you can mark it as null and let the GC do its work.
The Object will become unreachable only when there is no reference pointing to it.
example :
class MyTest {
#Override
protected void finalize() throws Throwable {
System.out.println("object is unreachable..");
}
}
// In some other class
public static void main(String[] args) {
MyTest o1 = new MyTest();
MyTest o2 = new MyTest();
System.gc();
o1 = null;
System.gc();
System.out.println("hello");
}
O/P:
hello
object is unreachable..
Here, you might have several thousand lines of code after "hello". You might want to make the GC's job easier by marking the object's references as null.

Manually nulling Objects in Java is bad, because it is slowing down most garbage collection (GC) algorithims. The GC detects by itself wether an Object is reachable or not and then it gets removed. After nulling an object the space in memory is still used and only after the GC recycles the space it can be used again. So nulling objects does not free up your space immediately. Also starting the GC manually is a bad idea. It is started by the VM if it is needed.

Related

Does not storing a newly declared object cause a memory leak?

What I mean to say through the post title is - doing this:
public static void makeNewObjectAndDoTask() {
new SomeClass().doYourTask();
}
I have myself written such code in languages such Java and JavaScript - declaring a new object without storing it in a variable, JUST to call one of its methods. Does this cause memory leaks? ..or does the object get cleared at the end of the method-stack / gets freed by the Java Garbage Collector?
Should I just be doing this instead - for safety?:
public static void makeNewObjectAndDoTask() {
SomeClass obj = new SomeClass().doYourTask();
obj = null;
//System.gc(); // Perhaps also call the collector manually?
}
As the commentors already answered, there is no memory leak in code like
public static void makeNewObjectAndDoTask() {
new SomeClass().doYourTask();
}
at least in itself, assuming that the SomeClass() constructor and the doYourTask() methods don't create memory leaks.
Definitely, the garbage collector will clean up the SomeClass instance at some time in the future.
How does it work?
Instances that are no longer accessible from program code will be garbage collected. Accessibility means being referenced in a variable, field, array element, method argument and so on.
As soon as the new SomeClass().doYourTask(); statement has finished, there is no way to access this individual SomeClass instance any more. So, it fulfills the garbage collection criteria.
The next time the garbage collector runs, it can reclaim the memory occupied by the instance (and its fields, recursively, as long as they aren't referenced elsewhere).
The alternative code
public static void makeNewObjectAndDoTask() {
SomeClass obj = new SomeClass().doYourTask();
obj = null;
}
only delays the garbage collection opportunity, as it stores a reference in obj, thus making the instance accessible for at least a tiny additional period of time, until you assign obj = null;.
Manually calling the garbage collector as in System.gc(); rarely is a good idea. It forces the GC to run (and to spend execution time on cleaning up memory), instead of relying on the JVM's highly optimized GC scheduling strategies. Don't do it unless you have a thorough understanding of the garbage collector, which led you to the conclusion that the GC strategy fails in your case.
We don't want OutOfMemoryErrors, and we don't want excessive time wasted for garbage collection, and the standard GC system does a very good job in both aspects.

Weakly referenced object won't get garbage collected

My concern is about an instance of an object that was once strongly referenced, but after an explicit null assignment to its strong reference and after an explicit System.gc() call, the instance is still reachable via the weak reference. If I understand correctly, when a referred object has only weak references left, the referent is guaranteed to be cleared in the next GC session. What am I missing?
Reference code:
public class References {
public static void main(String[] args) {
Example strongReferenceWrappedInWeak = new Example(42);
strongReferenceWrappedInWeak.printA();
WeakReference<Example> exampleWeakReference = new WeakReference<>(strongReferenceWrappedInWeak);
System.gc();
Example retrievedExample = exampleWeakReference.get();
retrievedExample.printA(); //this works, because a strong reference is present to the instance, hence it's not cleared
strongReferenceWrappedInWeak = null; //eligible for garbage collection
System.gc();
Example retrievedExampleTwo = exampleWeakReference.get(); //should be null
retrievedExampleTwo.printA(); //should throw NPE
}
}
class Example {
private int a;
Example(int a) {
this.a = a;
}
void printA() {
System.out.println(this.a);
}
}
strongReferenceWrappedInWeak = null does not make the Example object instance eligible for garbage collection, because retrievedExample still maintains a strong reference to it.
To fix, add retrievedExample = null;
Example strongReferenceWrappedInWeak = new Example(42);
strongReferenceWrappedInWeak.printA();
WeakReference<Example> exampleWeakReference = new WeakReference<>(strongReferenceWrappedInWeak);
System.gc();
Example retrievedExample = exampleWeakReference.get();
retrievedExample.printA(); //this works, because a strong reference is present to the instance, hence it's not cleared
retrievedExample = null;
strongReferenceWrappedInWeak = null; //now eligible for garbage collection
System.gc();
Example retrievedExampleTwo = exampleWeakReference.get(); //will be null
retrievedExampleTwo.printA(); //will throw NPE
Alternatively, don't create a strong reference with a local variable, just call the method directly off the weak reference. That way you don't accidentally leave a strong reference behind, as you did. *(During the printA() call, the this reference is a strong reference, so object cannot be GC'd during the call)*
Example strongReferenceWrappedInWeak = new Example(42);
strongReferenceWrappedInWeak.printA();
WeakReference<Example> exampleWeakReference = new WeakReference<>(strongReferenceWrappedInWeak);
System.gc(); //does not collect object, since strong reference still exists
exampleWeakReference.get().printA(); //works
strongReferenceWrappedInWeak = null; //eligible for garbage collection
System.gc(); //collects object, since it is now weakly referenced only
exampleWeakReference.get().printA(); //throws NPE
Output (from both)
42
42
Exception in thread "main" java.lang.NullPointerException
at Test.main(Test.java:**)
Tested on Java 13
Garbage Collection works in mysterious ways.
There have been several implementations of garbage collectors in the Java ecosystem, with very different behaviors.
When garbage collection runs varies by the implementation of the garbage collector, and also may depend on the current condition of the JVM. One collector might run almost continuously, while another might wait until low on memory. (I’m greatly oversimplifying here, to make the point clear.)
Whether all garbage is collected, or just some of it, may also vary by collector implementation and by the state of the JVM.
The call to System.gc is merely a suggestion, not a command. A garbage collector is free to ignore it.
In Java, you should not be making any great effort at managing memory. The modern JVM implementations are far better at that than any single programmer is likely to be. Just be sure to release all references to your objects when done using them. Or use WeakReference/SoftReference. Then trust the JVM and garbage collector to do its job.
In extreme cases (very large memory, or extreme volumes of object churn) you might want to study the behaviors of various garbage collector implementations. And maybe consider alternatives such as Zing from Azul Systems or GraalVM from Oracle. But for most projects, the usual OpenJDK-based JVMs work quite well.

Garbage collection when application ends

As far as I know objects are available to be garbage collected when assigning a null value to the variable :
Object a = new Object;
a = null; //it is now available for garbage collection
or when the object is out of scope due to the method's execution is done:
public void gc(){
Object a = new Object;
} //once gc method is done the object where a is referring to will be available for garbage collection
given with the out of scope isn't also the same when the application just ended?
class Ink{}
public class Main {
Ink k = new Ink();
public void getSomething(){
//method codes here
}
public static void main(String[] args) {
Main n = new Main();
}
}
where I expect 2 objects (Ink object and Main object) should be garbage collected when the application ends.
When the Java application terminates, the JVM typically also terminates in the scope of the OS, so GC at that point is moot. All resources have returned to the OS after as orderly a shutdown of the JVM as the app defined.
You are confusing the event of an object becoming eligible for garbage collection with the actual process of collecting garbage or, more precisely, reclaiming memory.
The garbage collector doesn’t run just because a reference became null or an object went out of scope, that would be a waste of resources. It usually runs because either, memory is low or CPU resources are unused.
Also, the term “garbage collection” is misleading. The actual task for the JVM is to mark all objects being still alive (also known as reachable objects). Everything else is considered reclaimable, aka garbage. Since at the termination of the JVM, the entire memory is reclaimed per se, there is no need to search for reachable references.
That said, it’s helpful to understand, that most thinking about the memory management is useless. E.g. in your code:
public void gc(){
Object a = new Object;
// even here the object might get garbage collected as it is unused in subsequent code
}
the optimizer might remove the entire creation of the object, as it has no observable effect. Then, there will no garbage collection, as the object hasn’t been created in the first place.
See also here.
JVM monitors the GC roots - if an object is not available from a GC root, then it is a candidate for garbage collections. GC root can be
local variables
active java threads
static variables
jni references

How to Clean up This Java Example Memory

I was reading about garbage collection and finalization in Java and when I tried an example. I click button 1, and memory jumps up. But when I click button 2, the memory didn't free up used space!
What did I do wrong and how do I free memory from unused objects?
As far as I know (I may be wrong):
When the same variable is re-instantiated again and again, the old object shall be destroyed.
When I set a variable to null the the old object shall be destroyed.
Array cells are null values. They shall be destroyed when parent array object has no variable to reference it.
How do I free up collections? How do array rules apply?
Code:
public class Memory extends javax.swing.JFrame {
Object[] object;
private void Button1ActionPerformed(java.awt.event.ActionEvent evt) {
object = new Object[10240000];
}
private void Button2ActionPerformed(java.awt.event.ActionEvent evt) {
object = null;
System.gc();
System.runFinalization();
//OR
System.runFinalization();
System.gc();
}
}
The System.gc() is only a suggestion for the JVM to clean up the memory. It may or may not take this suggestion. You are not doing anything wrong. Relax.
Java will clean unused objects out eventually, that's what garbage collector is for. You don't have to worry about it or write any code for it.
GC in Java periodically and it is not instantaneous, System.gc() only suggests that GC should run, which might not happen.
If you want to see java GC in action you should try a program with longer run-time to see what's going on with memory and GC in action.
When same variable is re-initanciated more and more the old object shall be destroyed.
When set a variable to null the the old object shall be destroyed
Array cells are null values they shall be destroyed when parent array object has no variable to reference it
How to free up collections or Array rules apply?
Answer to all four points is: Garbage collector will take care of that.
Also the reason why memory is high even though the garbage collector probably did run is that JVM takes more memory than just the objects.

Is object eligible for garbage collection after "obj = null"?

I know System.gc() is not guaranteed to cause GC, but theoretically, in the following code, will the object obj be eligible for garbage collection?
public class Demo {
public static void main(String[] args) throws Exception {
SomeClass obj = new SomeClass();
ArrayList list = new ArrayList();
list.add(obj);
obj = null;
System.gc();
}
}
class SomeClass {
protected void finalize() {
System.out.println("Called");
}
}
At the point where you call System.gc() the SomeClass instance you created is not eligible for garbage collection because it is still referred to by the list object, i.e. it is still reachable.
However, as soon as this method returns list goes out of scope, so obj will then become eligible for garbage collection (as will list).
Simply setting the reference obj to null does not, by itself, make the object referred to eligible for garbage collection. An object is only eligible if there are no references to it from the graph of visible objects.
will the object obj be eligible for garbage collection?
Only those objects are garbage collected who don't have even one reference to reach them. (except the cyclic connectivity)
In you code, there are two reference that are pointing to new SomeClass();
obj
zeroth index of list
You put obj = null, i.e. it's not pointing to that object anymore. But, still there exists another reference in list which can be used to access that object.
Hence the object will be eligible for GC only when main returns. i.e. you can't see the output of finalize method even if it got called. (not sure if JVM still calls it)
No, because the object actually exists in the list.
You as Java programmer can not force Garbage collection in Java; it will only trigger if JVM thinks it needs a garbage collection based on Java heap size
When a Java program started Java Virtual Machine gets some memory from Operating System. Java Virtual Machine or JVM uses this memory for all its need and part of this memory is call java heap memory.
Heap in Java generally located at bottom of address space and move upwards. whenever we create object using new operator or by any another means object is allocated memory from Heap and When object dies or garbage collected ,memory goes back to Heap space in Java
EDIT :
will the object obj be eligible for garbage collection?
No, because the object is still in the ArrayList.
Agreed, it won't be garbage collected as long as its there in the list.

Categories