Below is the code
ArrayList arList = someMethod();// returning ArrayList with customDO objects
Now somewhere in different class I am getting data from this arList
CustomDo custDO= (CustomDO)arList.get(0);
Will the arList be alive as long as custDO is alive ? If yes, will below piece of code help
CustomDO custDO = ((CustomDO)arList.get(0)).cloneMe();
// where cloneMe has defintion as return ((CustomDO)super.clone());
// CustomDo implements Cloneable
Is there a better way to keep a copy of only the first element of arList and discard the list so that it can be collected by garbage collector ?
Is there a better to keep a copy of only the first element of arList and discard the list so that it can be collected by garbage collector ?
You don't have to make a copy of the list element. As long as you have another reference to it, it will not be garbage-collected, even if the list you got it from is. And the list will be garbage-collected as soon as you remove all references to it.
There is no need in Java to clone anything just to make sure that the object does not disappear. In Java a reference to an object is always valid. It cannot happen that the data for a live reference gets invalid.
You only want to make a copy (clone) if you are afraid that other people who reference the same object might change its contents (calling some setter on it) in ways that would cause trouble for you (or you want to have a private copy to change it without affecting others).
// reference to first object
CustomDO custDO = ((CustomDO)arList.get(0));
// let arList be garbage collected
arList = null;
Another thing you should know is that Collections clone() methods do a shallow (flat) copy. Sometimes you need to have deep copies (to allow modifing them independedly)
As long as you have access to CustomDO custDO object, it will not be garbage collected. The list can be garbage collected if there is no reference to it.
The ArrayList is an ordinary Object, and only references to this object will keep the list alive. Of course, as long as the list is alive, all its elements are also alive, but the converse does not hold.
Related
I have a weakly-referenced array of weak references to further objects like so:
public class Foo{
WeakReference<WeakReference<Bar>[]> cache;
}
public class Bar{
private final WeakReference<Bar>[] ownerCache;
}
The array itself is weakly referred for reasons I will not go into right now. I want to make sure it is not garbage collected before ANY of the Bar objects reachable from it. In other words, it must exist in memory as long as any Bar object exists that can be reached from it. Then, if no Bar objects exist any more, I am better off if the array is also garbage collected. (Bar objects may or may not be strongly reachable from elsewhere.) I did this by referring to the cache array in a field inside all Bar objects. If the field is sufficient in making the array strongly reachable, it is not garbage collected. However, my code never actually uses that field and I can not make it public. (I get the "unused" warning on it.) I am afraid that the existence of such field is terminated either during compile time or run time, or it could get special treatment from the garbage collector that I am unaware of.
Is this the right solution? Does this solution achieve what I want regardless of the garbage collector or JVM implementation? If not, what would be a better method?
Here are a couple of ideas.
If you control the Bar class, and each instance is referenced by no more than one array, you could add a reference from a Bar instance to the array. Reachable Bar instances will prevent the array from being collected.
Alternatively, you could:
Construct a reference queue for weak references to Bar instances.
ReferenceQueue<Bar> m_refQueue = new ReferenceQueue<>();
Construct each WeakReference with a reference to that queue.
new WeakReference<Bar>( myBar, m_refQueue );
Periodically poll that queue for available collectable instances, and remove them from your collection.
You could make the collection itself a resizable data structure, avoiding the need to collect it.
public class Foo {
final #Nonnull List<WeakReference<Bar>> cache = new ArrayList<>();
// Or you could use an IdentityHashSet from a third-party library.
}
EDIT
As suggested by #Holger below, if an ordered list of references is not needed, your collection of WeakReference can be a java.util.WeakHashMap, used as a set. The keys are weak references; the values can be null. The map is a resizable data structure, so you can simply hold an ordinary reference to the map.
public class Foo {
final #Nonnull WeakHashMap<WeakReference<Bar>,Object> cache
= new WeakHashMap<>();
What I am asking might be a stupid question so please pardon me for that.
So it goes like this :
List<Boss> bossList = new ArrayList<Boss>();
Boss b = null;
for(Employee e : List<Employee> myList){
b = new Boss();
b.setEmployee(e);
bossList.add(b);
b = null;
}
So in above scenario, I am creating lot of Boss objects and then de-referencing them(I know I don't need to write "b = null", but i did it for clarity of my question). In normal scenario, I would have marked them to garbage collection, by doeing this, but because in this scenario, I am adding those Boss objects in List collection, are they marked for GC or not? If not then why? And how does List collection work internally to hold references for each Object added, so as to avoid garbage collection?
[EDIT]
The scope of question is only limited to the individual Boss objects created in for loop, considering that this method returns the reference of the List to the outside world.
The Boss objects will not be collected by the GarbageCollector because they are still referenced in the code block that you are posted. bossList is an ArrayList which has an internal array of Object thus holding references to those objects which are added to it.
I such a situation not only the references by you are considered but all referneces in all objects involved.
EDIT: Since you are returning the List in your code the objects will not be marked for garbage collection until the list is no longer referenced in your program.
ArrayList has Object[] elementData internally. When you added b to bossList ArrayList assigned elementData[0] = b. So when you assigned null to b the instance of Boss is still referenced from elementData[0] and cannot be GCed. But since ArrayList instance is referenced only from method's variable after the method returns both ArrayList and Boss instances will be eligible for GC.
Here's what really happens with your code :
Since java is pass by reference, whenever you add b to bossList, bossList starts referencing the memory location which b is pointing to. So when b nullified only link from b to the reference is broken. Thus keeping the object accessible through bossList.
I have written a program for sorting an integer type array which involves the creation another array of the same size. After sorting, there is no use of the new array, so I want to completely get rid of it. So far, I've only found questions relating to the deletion of specific types of elements. Some help?
Information (if needed):
Original Array: A[n]
New Array: B[n]
B[n] has to be completely deleted.
The temp array will be "deleted" (or more correctly, the occupied memory will be eligible for garbage collection) automatically whenever you leave the method performing the sorting (assuming of course that the temp array is created inside the method).
There is almost never any need for explicit memory deallocation in Java.
Array is a reference type in Java. You can make an array reference null if you no longer wish to use it:
arr = null;
Set B to null.
B = null;
This way the garbage collector will clean it up whenever it runs. While you can't control when garbage collection happens since each JVM might have it's own garbage collection algorithm, you may suggest to the system that it should run the garbage collector to free up some memory.
You can do this by using
System.gc();
Note: As mentioned above, System.gc(); will only suggest that garbage collection be carried out but does not assure it.
Normally the gc() frees the memory which has no references. But you can also free the memory with array = null.
If the array is locally defined in your sorting method then it will be scheduled for garbage collection when your method ends as there will be no existing reference to it.
If it is a class or instance variable then set all references to it to null.
In Java you dont have to worry about memory deallocation. There is no such stuff like C's stdlib free(void*) or C++'s delete[] operator. Thee is only the garbage collector.
set B to an empty array
B = [];
I have the following code:
result = binding.downloadData(sourceURLString.replace("{CAT_ID}", catId), Data.class);
ArrayList<Data> mAllProducts = result.getProducts();
cloneList(mAllProducts);
System.gc();
And here is the deep copy of the mAllProducts ArrayList
static List<Data> clone;
public static void cloneList(ArrayList<Data> list) {
clone = new ArrayList<Data>();
for(Data item: list){
clone.add(new Data(item));
}
}
Data Constructor:
public Data(Data item2) {
this.imageUrl = item2.imageUrl;
*
*
}
My questions are:
Will the mAllProducts arraylist collected by the garbage collector?
Is the clone list a passed by value ArrayList?
If the answer at the 2nd question is yes, that means that the clone arraylist doesn't have a reference to the memory?
And finally, if the answer at the second question is yes, that means that will stay at the memory only for the time is being used by the system and then will be garbage collected?
1) No way to know, your gc call is merely a suggestion that the JVM try to perform a collection.
2) Everything in Java is pass by value.
3) I don't know what you mean. But your clone, assuming it creates new items for the list, and the items don't share references to any objects, is completely separate from the original list. Primitive values like ints are immutable, it's only object instances you have to worry about. It seems you are using a copy constructor, so be extra careful you copy any objects each item contains, as well as any items those children might contain; your copy needs to be deep.
4) I don't know what you mean. If you don't have any references to the original it will be eligible for collection the next time the GC runs.
Will the mAllProducts arraylist collected by the garbage collector?
Only when 1) The garbage collector decides to do so and 2) When it falls out of scope
Is the clone list a passed by value ArrayList?
Yes
If the answer at the 2nd question is yes, that means that the clone arraylist doesn't have a reference to the memory?
Definitely needs a reference to some point in memory, else it can't exist in a logical system i.e. a computer.
And finally, if the answer at the second question is yes, that means that will stay at the memory only for the time is being used by the system and then will be garbage collected?
Again the garbage collector will collect it when it is deemed fit to do so.
When an array of objects is not referenced anymore, does the objects in that array are garbage collected too? (assuming no variables are referencing the elements)
In this page, http://java.sys-con.com/node/37613
it says -
"The biggest danger is placing an object into a collection and forgetting to remove it. The memory used by that object will never be reclaimed."
If you make sure to nullify the references, why will that memory be unclaimed?
Thanks
When an array of objects is not referenced anymore, does the objects
in that array are garbage collected too? (assuming no variables are
referencing the elements)
Yes.
"The biggest danger is placing an object into a collection and
forgetting to remove it. The memory used by that object will never be
reclaimed."
This is when you are holding a reference to the collection. For example, if you have a Map in which you put a key-value and then forget to remove then it stays there for ever. Think http sessions, if you use something in ServerContext or some such at start of request using session id as key but fail to remove it at end of the request processing..
For the first question, the answer is yes, absolutely: the objects inside non-referenced array and no other references do get garbage collected.
As for the second question, the document talks about placing forgetting an object inside a referenced collection, for example a cache of some sort, a static field, a thread-local store, etc.
It won't be unclaimed if nothing references it. The article says that if you nullify a reference, but the object is still in a referenced collection (hence referenced), it won't be collected.
Generally speaking, anything that's not referenced is garbage collected. So, yes, those objects would be garbage collected.
Also, note that:
An array is not a collection.
I think that what the person that wrote that meant was make sure you
remember all of the places you're referencing an object, so that if
you intend to remove it, it gets removed (and there are no lingering
references to it).