I have some custom object like:
public class House
{
private Roof r;
private Wall w;
private Floor f;
public House()
{
this.r = new Roof();
this.w = new Wall();
this.f = new Floor();
}
}
Then I create a new instance of House object:
public static void main()
{
House h = new House();
}
So, now I have four objects:
House h
Roof r
Wall w
Floor f
Roof r, Wall w and Floor f absolutely depends on House.
So if I will delete House h, I want them to be removed as well.
What is the correct way to do it?
What if I will add this method to House class:
public void remove()
{
this.r = null;
this.w = null;
this.f = null;
}
And when I will need to remove a House h with all its components write:
public static void main()
{
h.remove();
h = null;
}
I think this should work, but not sure.
Also, maybe there is a better way?
And yes, there is nothing about public houses, inns etc. :)
You can never depend on garbage collection occurring at all. Even if you call System.gc(), you have no guarantee that it will do anything. When the system decides to run a garbage collection, unreachable references may be collected, but if you run a small application, the collector may never run.
If you need to be notified when an object is disposed, you should use a java.lang.ref.PhantomReference and a java.lang.ref.ReferenceQueue. Do not depend on Object.finalize(). But that does not seem to be your issue; you simply want to clean up after yourself. You should care only if your application's performance requires it.
You dont need to null out all instance variables in House since they are automatically garbage collected when there is no reference to the instance of House.
What if they are referenced from somewhere else? But I want them to be removed with the removal of "parent" object.
For this you should use weak references each time you reference the objects from somewhere outside of the House class. This way the objects will get garbage collected when there no longer is a reference to House, since the only strong references pointing to them are inside of House.
The solution you have given is almost correct. Once you have marked an object reference as null, then that object will be destroyed and removed from memory by the JVM garbage collector whenever that garbage collector will start running .
You can also manually instruct garbage collector to collect garbage after setting reference variables as NULL .
Related
I want to delete an object I created, (a oval which follows you), but how would I do this?
delete follower1;
didn't work.
EDIT:
Okay, I'll give some more context. I'm making a small game with a oval you can control, and a oval which follows you. Now I've got files named: DrawPanel.class, this class draws everything on the screen, and handles collisions, sounds, etc. I got an enemy.class, which is the oval following the player. I got an entity.class, which is the player you can control. And if the player intersects with the follower, I want my player object to get deleted. The way I'm doing it:
public void checkCollisions(){
if(player.getBounds().intersects(follower1.getBounds())){
Follower1Alive = false;
player.health = player.health - 10;
}
}
You should remove the references to it by assigning null or leaving the block where it was declared. After that, it will be automatically deleted by the garbage collector (not immediately, but eventually).
Example 1:
Object a = new Object();
a = null; // after this, if there is no reference to the object,
// it will be deleted by the garbage collector
Example 2:
if (something) {
Object o = new Object();
} // as you leave the block, the reference is deleted.
// Later on, the garbage collector will delete the object itself.
Not something that you are currently looking for, but FYI: you can invoke the garbage collector with the call System.gc()
Your C++ is showing.
There is no delete in java, and all objects are created on the heap. The JVM has a garbage collector that relies on reference counts.
Once there are no more references to an object, it becomes available for collection by the garbage collector.
myObject = null may not do it; for example:
Foo myObject = new Foo(); // 1 reference
Foo myOtherObject = myObject; // 2 references
myObject = null; // 1 reference
All this does is set the reference myObject to null, it does not affect the object myObject once pointed to except to simply decrement the reference count by 1. Since myOtherObject still refers to that object, it is not yet available to be collected.
If you want help an object go away, set its reference to null.
String x = "sadfasdfasd";
// do stuff
x = null;
Setting reference to null will make it more likely that the object will be garbage collected, as long as there are no other references to the object.
You don't need to delete objects in java. When there is no reference to an object, it will be collected by the garbage collector automatically.
You can remove the reference using null.
Let's say You have class A:
A a = new A();
a=null;
last statement will remove the reference of the object a and that object will be "garbage collected" by JVM.
It is one of the easiest ways to do this.
Java has a Garbage Collector, it will delete the object for you if no reference is held to it anymore.
//Just use a List
//create the list
public final List<Object> myObjects;
//instantiate the list
myObjects = new ArrayList<Object>();
//add objects to the list
Object object = myObject;
myObjects.add(object);
//remove the object calling this method if you have more than 1 objects still works with 1
//object too.
private void removeObject(){
int len = myObjects.size();
for(int i = 0;i<len; i++){
Objects object = myObjects.get(i);
myObjects.remove(object);
}
}
I'm reading section 12.6.1 of Java SE specs and it said:
Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. For example, a Java compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner.
Another example of this occurs if the values in an object's fields are stored in registers. The program may then access the registers instead of the object, and never access the object again. This would imply that the object is garbage. Note that this sort of optimization is only allowed if references are on the stack, not stored in the heap.
The relevant code is:
class Foo {
private final Object finalizerGuardian = new Object() {
protected void finalize() throws Throwable {
/* finalize outer Foo object */
}
}
}
My question is what kind of JVM would ever store finalizerGuardian in the stack not the heap and why?
The code example is for illustrating the last sentence of your cited text, “Note that this sort of optimization is only allowed if references are on the stack, not stored in the heap” and it is a bit odd that you ripped it off the explaining text:
For example, consider the Finalizer Guardian pattern:
class Foo {
private final Object finalizerGuardian = new Object() {
protected void finalize() throws Throwable {
/* finalize outer Foo object */
}
}
}
The finalizer guardian forces super.finalize to be called if a subclass overrides finalize and does not explicitly call super.finalize.
If these optimizations are allowed for references that are stored on the heap, then a Java compiler can detect that the finalizerGuardian field is never read, null it out, collect the object immediately, and call the finalizer early. This runs counter to the intent: the programmer probably wanted to call the Foo finalizer when the Foo instance became unreachable. This sort of transformation is therefore not legal: the inner class object should be reachable for as long as the outer class object is reachable.
So the code example illustrates a restriction. The “optimizing transformations” mentioned by the specification includes Object Scalarization applied after Escape Analysis has proven that an object is purely local, in other words, the code under optimization spans the entire lifetime of the object.
But it doesn’t need such local objects. As the specification already mentioned, optimized code may keep an object’s fields in CPU registers without the need to re-read them, thus, does not need to keep the object reference anymore. Likewise, a reference variable still in scope may be unused. If that reference was the only reference to an object, removing it from the optimized code allows earlier garbage collection.
Both scenarios would still allow a Foo instance to get eliminated or collected earlier. This in turn would allow the earlier collection of the object (not anymore) referenced by finalizerGuardian. But that doesn’t counteract the intention of this restriction. The specification restricts the optimization to not allow the inner object to get collected earlier than the outer object, but there is no problem in collecting both together, including earlier than naively expected.
Generally, arbitrarily large object graphs may get collected in a single garbage collection cycle, perhaps earlier than naively expected, or even get optimized away completely.
a classic example for such kind of optimization (escape analysis) is a calculation with Point class:
class Point {
double x;
double y;
public Point(final double x, final double y) {
this.x = x;
this.y = y;
}
double length() {
return Math.sqrt(x * x + y * y);
}
static double calc() {
double result = 0;
for (int i = 0; i < 100; i++) {
// this allocation will be optimized
Point point = new Point(i, i);
result += point.length();
}
return result;
}
}
after inlining this new will be not needed because we can extract all fields to local variables like
Point point = new Point(i, i);
double x = point.x;
double y = point.y;
result += Math.sqrt(x * x + y * y);
->
Point point = new Point(i, i);
double x = i;
double y = i;
result += Math.sqrt(x * x + y * y);
now it's obvious that new Point(i, i) is useless and JIT just remove this line.
Note that the allocation was on stack i.e. in a local variable. If it was in a field we'd not be able do that optimization because it's stored in the heap.
That how it works.
about your code snipped: the finalizerGuardian will always in the field (stored in the heap) and JVM can do nothing with this allocation. Furemore if the class Point from the example above contains such field, i think escape analys is not able to remove the allocation because it might change the original behaviour.
I want to delete an object I created, (a oval which follows you), but how would I do this?
delete follower1;
didn't work.
EDIT:
Okay, I'll give some more context. I'm making a small game with a oval you can control, and a oval which follows you. Now I've got files named: DrawPanel.class, this class draws everything on the screen, and handles collisions, sounds, etc. I got an enemy.class, which is the oval following the player. I got an entity.class, which is the player you can control. And if the player intersects with the follower, I want my player object to get deleted. The way I'm doing it:
public void checkCollisions(){
if(player.getBounds().intersects(follower1.getBounds())){
Follower1Alive = false;
player.health = player.health - 10;
}
}
You should remove the references to it by assigning null or leaving the block where it was declared. After that, it will be automatically deleted by the garbage collector (not immediately, but eventually).
Example 1:
Object a = new Object();
a = null; // after this, if there is no reference to the object,
// it will be deleted by the garbage collector
Example 2:
if (something) {
Object o = new Object();
} // as you leave the block, the reference is deleted.
// Later on, the garbage collector will delete the object itself.
Not something that you are currently looking for, but FYI: you can invoke the garbage collector with the call System.gc()
Your C++ is showing.
There is no delete in java, and all objects are created on the heap. The JVM has a garbage collector that relies on reference counts.
Once there are no more references to an object, it becomes available for collection by the garbage collector.
myObject = null may not do it; for example:
Foo myObject = new Foo(); // 1 reference
Foo myOtherObject = myObject; // 2 references
myObject = null; // 1 reference
All this does is set the reference myObject to null, it does not affect the object myObject once pointed to except to simply decrement the reference count by 1. Since myOtherObject still refers to that object, it is not yet available to be collected.
If you want help an object go away, set its reference to null.
String x = "sadfasdfasd";
// do stuff
x = null;
Setting reference to null will make it more likely that the object will be garbage collected, as long as there are no other references to the object.
You don't need to delete objects in java. When there is no reference to an object, it will be collected by the garbage collector automatically.
You can remove the reference using null.
Let's say You have class A:
A a = new A();
a=null;
last statement will remove the reference of the object a and that object will be "garbage collected" by JVM.
It is one of the easiest ways to do this.
Java has a Garbage Collector, it will delete the object for you if no reference is held to it anymore.
//Just use a List
//create the list
public final List<Object> myObjects;
//instantiate the list
myObjects = new ArrayList<Object>();
//add objects to the list
Object object = myObject;
myObjects.add(object);
//remove the object calling this method if you have more than 1 objects still works with 1
//object too.
private void removeObject(){
int len = myObjects.size();
for(int i = 0;i<len; i++){
Objects object = myObjects.get(i);
myObjects.remove(object);
}
}
In Java, having a nested static class Human, I'm wondering if after cleanup of the map variable can make it available for garbage collected. At the moment just before doSomeCode() I called System.gc() and added Thread.sleep(60000) to wait for garbage collector to pick up unreferenced map contents, but no way - it seems map lives in a program unless it is going to finish. My problem is that I need to free up memory because otherwise will get OutOfMemoryError.
What do you think prevents map property of Human class from being recycled? Is it because the Human class is static and thus all its members can not be garbage collected?
import java.util.List;
import java.util.ArrayList;
import com.carrotsearch.hppc.IntObjectMap;
import com.carrotsearch.hppc.IntObjectOpenHashMap;
public class TestNestedStaticClass {
public static class Human {
String name = null;
List<Human> children = null;
// some data about family members
IntObjectMap<int[]> map = null;
public Human(String name) { this.name = name; }
}
public static void main(String[] args) {
final List<Human> family = new ArrayList<Human>();
for (int i = 0; i < 1000; i++) {
// create and get the family member
family.add(new Human("givenName"));
Human h = family.get(i);
// create map and add some data
h.map = new IntObjectOpenHashMap<int[]>();
for (int j = 0; j < 100; j++) {
int[] array = new int[1500];
h.map.put(j, array);
}
}
// ...
// at some point we want to free the memory occupied by
// family.get(i).map for all i from 0 to 1000, so we do:
for (int i = 0; i < 1000; i++) {
// get the family member
Human h = family.get(i);
// explicitly remove references from the map
for (int j = 0; j < 100; j++) {
h.map.remove(j);
}
// cleanup
h.map.clear();
h.map = null;
}
// ...
doSomeCode();
}
}
From the point where you write: h.map = null;, the map becomes eligible for GC (the removes and clear are technically not necessary).
The reason why you don't see it being GC'ed is possibly due to the fact that you run all that code within the same method, and the GC does not have to collect local variables until the method exits.
If you try to split it in several method it will help the GC (which will get rid of the local variables once the methods exit).
See also this post.
ps: I assumed that you don't have any references to the content of the map or the map itself anywhere else!
The fact that the Human class is static means nothing - and even if the map variable was static, setting it to null frees up the object content for garbage collection.
If you are running into OutOfMemoryErrors, and you are certain the map contents are the cause, then there must be lingering references to the data somewhere. For example, if I do this:
human.map.put(0, new int[10000]);
something.thing = map.get(0);
human.map.remove(0);
human.map = null;
Note that a reference to the int[10000] still remains in memory, #something.thing. Cleaning up the map is only part of the work needed to free up the array for garbage collection.
Note that inner static classes are indeed top classes but just inside a class, so the GC rules to collect their instances are the same rules that GC applies on a common class instance.
There is no need to sleep after System.gc() - the gc method doesn't return until the garbage collector is finished.
An instance of a static inner class is treated the same as an instance of any other class for purposes of garbage collection. You are correctly freeing the map elements of your Human classes (although it's overkill to call map.remove() and map.clear() and map = null - only map = null is needed)
It looks like you are using all primitive data types. This might be a problem, this is just a theory, and I haven't tested it, but it might be worth a try.
Instead of using an array of int's ( int[] ), try using an ArrayList. This should create objects which can be garbage collected, primitive data types are created on the stack not on the heap of objects, therefore they aren't subject to garbage collection?
NOTE: I put a question mark, because I am not positive, someone can confirm or reject my theory.
THEORY REJECTED :( , LEAVING AROUND FOR OTHERS TO READ
1) Been a while since I programmed in Java but my guess is the static objects/variables live on in a special place during whole execution of the program.
2) Calling GC explicitly doesn't ensure the objects will be deleted. You simply call the GC and it decides itself (and you cannot really affect this behavior).
I have the following code:
class Test {
public static void main(String[] args) {
String a,b,c;
a = new String(args[0]);
b = a;
a = null;
b = null;
}
}
Can someone tell me when a will be eligible for garbage collection. I think it's after b is made null because don't a and b reference the same object ?
Pitching my answer too. As the other answers say, the String/ object is available for Garbage Collection once it is no longer accessible (you no longer have a handle to it).
So if you had a one-direction linked list... [1] -> [2] -> [3] and you had a handle to [1] (which has a handle to [2] and onwards). If you set your handle to [1] to null, you would put the entire list available to the Garbage collector. As this answer says, you are able to call System.gc() to request the Garbage Collector run, but it is not guaranteed that it will.
I believe the main focus to this answer is that objects are available to the garbage collector when they are inaccessible and that does not necessarily mean that there are no references to it. In my above example, even though [1] had a handle to [2], [2] was available for the garbage collector because there was no handle to [1].
The object you've created, new String(args[0]);, will be eligible for collection once there are no longer any references to it. So let's step through the code:
a = new String(args[0]);
a points to your String, it is not eligible for collection.
b = a;
a and b point to your String, not eligible.
a = null;
b points to your String, not eligible.
b = null;
No references to your String, Garbage Colelctor is happy!
What do you mean by a? a is a reference, and only objects are garbage collected.
The string referenced by a, and then b, is eligible for garbage collection when nothing references it anymore. In this case, this is after both references to the string (a and b) have been changed to reference something else; in this case, null.
You must reason in terms of allocated objects: the String you allocated is not referenced by anyone as soon as you nullify both a and b. From thereon the garbage collector is entitled to do its job.
class Test {
public static void main(String[] args) {
String a,b,c; // you dont have objects yet
a = new String(args[0]); // here u make a new object
b = a; // b references to the same object as a
a = null; // a points to null, reference is removed.
b = null; // b point to null, reference is removed
}
}
in your program the object that was created and assigned to a and b will be garbage collected after references are removed.
Garbage collector will clean up the object that has no roots and not being referenced by anything.