Java ArrayList Memory Issue - java

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.

Related

Is this java Object eligible for garbage collection in List

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.

java pass by value and memory and cpu utilization

Coming from a C background I have a very basic question: Does pass by value of a larger datatype like a String array invoke something like a copy constructor in java.
So would this code result in creating duplicate list in memory by copying list in list2.
Thus double memory and cpu utilization.
String[] getList() {
String[] list = new String...
...
return list;
}
String [] list2 = getList();
Is my assumption correct? If yes, is there an alternative like passing pointers in C.
PS: if we let garbage collector do the job of cleaning extra memory wont this be another set of cpu utilization of cycles of cleaning the memory which shouldn't have been created at first place.
No, it won't double memory and CPU usage. In Java, all non-primitive types are stored as references and those references are passed by value.
So in your example, the getList method will construct an array on the heap and return a reference to that array. No array copy involved; just a reference copy.
No, the contents of the array will not be copied. A reference pointing to the array on the heap will be passed instead.
Java does not have pointers, it has references. In Java, references pointing to objects on the heap are passed as arguments and returned by methods. Arrays are objects in Java, so they are treated this way too.

Deleting An Entire Array

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 = [];

Non runtime allocation solution - ArrayList

I'm making a game in Java. I need some solution for my current runtime allocation, caused by my ArrayList. Every single minute or 30 seconds the garbage collector starts to runs because of I am calling for draw and updates-method through this collection.
How should I be able to do a non runtime allocation solution?
Thanks in advance and if needed, my code is posted below from my Manager class which contains the ArrayList of objects.:
Some code:
#Override
public void draw(GL10 gl) {
final int size = objects.size();
for(int x = 0; x < size; x++) {
Object object = objects.get(x);
object.draw(gl);
}
}
public void add(Object parent) {
objects.add(parent);
}
//Get collection, and later we call the draw function from these objects
public ArrayList<Object> getObjects() {
return objects;
}
public int getNumberOfObjects() {
return objects.size();
}
More explanation: The reason I mix with this is because (1) I see that the ArrayList implementation is slow and causing lags and (2) that I want to merge the objects/components together. When firing an update call from my Thread-class, it goes through my collection, send things down the tree/graph using the Manager's update function.
When looking at an Open Source project, Replica Island, I found that he used an alternative class FixedSizeArray that he wrotes on his own. Since I'm not that good at Java, I wanted to make things easier and now I'm looking for another solution. And at last, he explained WHY he made the special class:
FixedSizeArray is an alternative to a standard Java collection like ArrayList. It is designed to provide a contiguous array of fixed length which can be accessed, sorted, and searched without requiring any runtime allocation. This implementation makes a distinction between the "capacity" of an array (the maximum number of objects it can contain) and the "count" of an array (the current number of objects inserted into the array). Operations such as set() and remove() can only operate on objects that have been explicitly add()-ed to the array; that is, indexes larger than getCount() but smaller than getCapacity() can't be used on their own.
I see that the ArrayList implementation is slow and causing lags ...
If you see that, you are misinterpreting the evidence and jumping to unjustifiable conclusions. ArrayList is NOT slow, and it does NOT cause lags ... unless you use the class in a particularly suboptimal way.
The only times that an array list allocates memory are when you create the list, add more elements, copy the list, or call iterator().
When you create the array list, 2 java objects are created; one for the ArrayList and one for its backing array. If you use the initialCapacity argument and give an appropriate value, you can arrange that subsequent updates will not allocate memory.
When you add or insert an element, the array list may allocate one new object. But this only happens when the backing array is too small to hold all of the elements, and when it does happen the new backing array is typically twice the size of the old one. So inserting N elements will result in at most log2(N) allocations. Besides, if you create the array list with an appropriate initialCapacity, you can guarantee that there are zero allocations on add or insert.
When you copy a list to another list or array (using toArray or a copy constructor) you will get 1 or 2 allocations.
The iterator() method creates a new object each time you call it. But you can avoid this by iterating using an explicit index variable, List.size() and List.get(int). (Be aware that for (E e : someList) { ... } implicitly calls List.iterator().)
(External operations like Collections.sort do entail extra allocations, but that is not the fault of the array list. It will happen with any list type.)
In short, the only way you can get lots of allocations using an array list is if you create lots of array lists, or use them unintelligently.
The FixedSizedArray class you have found sounds like a waste of time. It sounds like it is equivalent to creating an ArrayList with an initial capacity ... with the restriction that it will break if you get the initial capacity wrong. Whoever wrote it probably doesn't understand Java collections very well.
It's not quite clear what you are asking, but:
If you know at compile time what objects should be in the collection, make it an array not an ArrayList and set the contents in an initialisation block.
Object[] objects = new Object[]{obj1,obj2,obj3};
What makes you think you know what the GC is reclaiming? Have you profiled your application?
What do you mean by "non-runtime allocation"? I'm really not even sure what you mean by "allocation" in this context... allocation of memory? That's done at runtime, obviously. You clearly aren't referring to any kind of fixed pool of objects that are known at compile time either, since your code allows adding objects to your list several different ways (not that you'd be able to allocate anything for them at compile time even if you were).
Beyond that, nothing in the code you've posted is going to cause garbage collection by itself. Objects can only be garbage collected when nothing in the program has a strong reference to them, and your posted code only allows adding objects to the ArrayList (though they can be removed by calling getObjects() and removing from that, of course). As long as you aren't removing objects from the objects list, you aren't reassigning objects to point to a different list, and the object containing it isn't itself becoming eligible for garbage collection, none of the objects it contains will ever be available for garbage collection either.
So basically, there isn't any specific problem with the code you've posted and your question doesn't make sense as asked. Perhaps there are more details you can provide or there's a better explanation of what exactly your issue is and what you want. If so, please try to add that to your question.
Edit:
From the description of FixedSizeArray and the code I looked at in it, it seems largely equivalent to an ArrayList that is initialized with a specific array capacity (using the constructor that takes an int initialCapcacity) except that it will fail at runtime if something tries to add to it when its array is full, where ArrayList will expand itself to hold more and continue working just fine. To be honest, it seems like a pointless class, possibly written because the author didn't actually understand ArrayList.
Note also that its statement about "not requiring any runtime allocation" is a bit misleading... it does of course have to allocate an array when it is created, but it just refuses to allocate a new array if its initial array fills up. You can achieve the same thing using ArrayList by simply giving it an initialCapacity that is at least large enough to hold the maximum number of objects you will ever add to it. If you do so, and you do in fact ensure you never add more than that number of objects to it, it will never allocate a new array after it is created.
However, none of this relates in any way to your stated issue about garbage collection, and your code still doesn't show anything that would cause huge numbers of objects to be garbage collected. If there is any issue at all, it may relate to the code that is actually calling the add and getObjects methods and what it's doing.

How does object reference and cloning works in java

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.

Categories

Resources