java loitering and garbage collection - java

I have this bit of code for the Stack's pop method and i'm trying to figure out how it avoids loitering while still returning the element that our index is currently pointing to:
public String pop()
{ // Remove item from top of stack.
String item = a[--N];
a[N] = null; // Avoid loitering (see text).
if (N > 0 && N == a.length/4) resize(a.length/2);
return item;
}
From what i can understand we are pointing the reference item of our String object to the indexed element(we start from the last element using it's current size N-1 hence the decrements) of our array a. Then if we are returning the reference why are we setting that indexed element that our reference is pointing to null before doing so? Doesnt that make the item point to nothing and return nothing?

An object can't be garbage collected as long as it is reachable. If you simply change your index with --N but do not nullify a[N], you will keep a reference to that object, preventing its garbage collection even if the client code does not reference that object any longer.
That is one of the only cases where you need to nullify a variable in Java.
You also seem to misunderstand what references are. a[N] contains a value that points to an object in memory. When your write String item = a[N], you copy that value to the variable item. Both variables (item and a[N]) now refer to the same object. When you then write a[N] = null, you remove that reference from the array but item still contains a value that points to the original object.

This copies the reference in the array. It doesn't reference the array member.
String item = a[--N];
Now you have two references to the same object, one in the local variable, and one in the array. This removes the copy in the array:
a[N] = null; // Avoid loitering (see text).
If it were not removed from the array, then an unnecessary reference would continue to exist, preventing garbage collection.

Related

Can I get an element which is deleted from a java collection?

I have a collection and some elements inside it. If I remove one element, then is there any way I can get it back or recover it? Please guide me if it is possible and how.
Check this example:
List<Object> toRemove = new ArrayList<Object>();
for(Object a: list){
if(//delete condition){
toRemove.add(a);
}
}
The element will be cleared from the memory by garbage collection as soon as there's no reference to it. This means that you need to keep at least one reference pointing at the actual element to have it alive in the memory. Otherwise consider it gone.
You need to store a reference to the element before you remove it. If there is no further reference to the item it may be collected by the garbage collector and there is no way to find it again. To store a reference either set a temporary variable equal to the object before you delete it; or certain collections such as ArrayLists allow you to save the object as you delete it if you use the Remove() method that takes an integer (the index of the element).

Java garbage collection cleanup of pointers

I'm writing a function to reverse a linked list and at the end my data structure looks like this:
OriginalPointer -> [Obj 1] <- [Obj 2] <- [Obj 3] <- [Obj 4] <- ReversedList
The OriginalPointer is what I passed into the function, and the ReverseList is the pointer I'm returning. In java, once I've returned my ReverseList pointer, does the OriginalPointer get cleaned up by the garbage collection or is that pointer always going to be there? Just curious.
All objects on java are stored on a heap and those objects are linked together. So when you are reversing your linked lists, all you are doing is changing the reference of the object, one object points to. So lets assume, the heap has 4 objects obj1,obj2, obj3, obj4. All objects contain a nextNode attribute, which tells them the next node. Once you reverse the list, all you are doing is changing this nextNode attribute value for that object. So by default your previous link will be deleted and I don't think anything needs to be up for GC.
GC only collects objects when there are no references to them anywhere in the program. As long as you hold a reference to one of the nodes, either in another node or in a temp, it won't be collected. The 'Original Pointer' you pass in I'm assuming is the list reference variable, and it will still point to the beginning (now end) of your list, unless you change it. Local variables like those are only destroyed when the method they are in is completed and returned from.
Java is always pass by value, which means that when you will call doReverce(List<obj> objList) , you will send a value of your pointer as a parameter.
Any change you make to your objList will have impact to your original list, unless you clone your list.
GC removes any object from the ram once it is not reachable within your code.
By the end of doReverse, it will remove any reference created there. In this case, it will remove the secondary reference inside the method, but since you have a reference from your main, your list object will still be in the ram. Once you have no references in your object, GC will collect (remove) it. The code I am refering is below. Keep in mind that you don't need to return a pointer of your object, since you already have it.
main()
{
List<obj> objList = new objList<>;
doReverse(objList);
}
//By the end of your main GC will collect objList
Here's your example, in Java syntax:
Node yourList = /* [Obj 1] <- [Obj 2] <- [Obj 3] <- [Obj 4] */;
yourList = reverse(yourList);
You start with four objects in the heap (the four nodes of your list), and one variable on the stack, yourList. This variable holds a reference to Obj 1's location in the heap. When reverse() is called it is handed the reference to Obj 1 and iterates through each object, reversing the list. Finally it returns a reference to Obj 4. The yourList variable is then updated to reference Obj 4. Since Obj 4 in turn references the other objects, none of them will be garbage collected.
All that happens to yourList is its value is updated. It previously stored the location (address) of Obj 1, now it stores the location of Obj 4. The previous value isn't garbage collected, it's overwritten. So after reverse() returns we end up with the same four objects on the heap, and the same one variable on the stack.

what is the concept behind memory initialization for Array?

String a[]=null;
if(a[0]!=null)
{
System.err.println("dd-1");
}
if(a!=null)
{
System.err.println("dd-2");
}
}
In first if condtion its throwing null pointer exception, but in second if condition its not throwing null pointer exception? can anyone please explain me the same? is there is any concept behind this on Heap memory allocation.
also i got to know the problem becauese of Missing memory allocation,String a[]=new String.[10]; please expalain the concept?
In the first if condition you are trying to access the first element in the array, even thought there is no allocation done for it.
In second condition you are just testing the reference.
(Think of it as C pointers, char *str = NULL does not allocated any thing except a pointer pointing to NULL)
String a[]=null;
No memory is allocated for the array only reference is created.
String a[] = new String[1]
Memory to hold one String object is created on the Heap and a points to the allocated string object.
if(a[0]!=null)
The first condition is trying to access the first element of the array (and check if it exists). That will not work if the array does not exist (i.e. is null).
if(a!=null)
The second condition is just checking if the array itself is null.
Memory for the array gets allocated (on the heap) when you create the array. At that time you also have to specify its size (and that will determine exactly how much memory gets allocated). The memory is also initialized with null, so you don't get garbage data for a fresh array.
Access to array elements is not just pointer arithmetic as in C, Java actually checks if the array exists and if the index is within its bounds.
Arrays are objects. You have to create new space for them. If you're trying to access a null reference, you'll get a NullPointerException every time.
If you use a[0], you are going to access a object (first object of the array). but a doesn't have any object yet. therefore first one throws a exception. But in second one, you are checking a reference. it is not an object. So a is equals to NULL.
In Java, arrays are not like C, they are objects living in the heap, they do have a special type and syntax to access their elements but they are objects, if you wish to access any subindex you'll need to do something like
String[] a = new String[10];
after that, each element will be initialized in null, 0 or false depending the type of the array.

Reference of two arrayList to same objects

I have this code. But I don't know how to explain the result:
ArrayList<String> first = new ArrayList<String>();
first.add("1");
first.add("2");
first.add("3");
ArrayList<String> second = new ArrayList<String>();
second = first;
System.out.println("before modified:"+second.size());
second.clear();
System.out.println("after modified:");
System.out.println(" First:"+first.size());
System.out.println(" Second:"+second.size());
The result will be: 3 / 0 /0
The problem I don't know is: when you assign first = second; so, both first and second array will point to same object (1,2 and 3). after you clear all elements on second array, so all reference between second array and these objects will loose (no problem here).
The thing I don't know is: but these objects (1,2 and 3) still hold reference to first array. Why first array's size is 0.
Please explain for me.
Thanks :)
By assigning second = first, there is only one arraylist with two references. The references are the same. So, when call clear using one of the two references (first or second), clear will be performed on the referenced arraylist.
This is something else than you first thought. It's not so that assigning the second = first all the references of the strings you added to the first one, will be copied into a new ArrayList object, that would be magic (in Java).
When you do first = second your ArrayList items will point to the same memory locations. Doing a .clear will remove the elements to which the ArrayList is pointing to. This will have repercussions on the other ArrayList.
If you just want to copy the elements of ArrayList1 to ArrayList2, you could do something like so: ArrayList<String> second = new ArrayList<String>(first);
but these objects (1,2 and 3) still hold reference to first array.
Why first array's size is 0.
ArrayList<String> second = new ArrayList<String>();
second = first;
is the same as writing
ArrayList<String> second = first;
You have made second reference point to the first arraylist,it is not using a new arraylist. So when you call clear it clears the "first" arraylist created - you have two references pointing to one arraylist.
When you assign one ArrayList to two variable and modify any one of them, this will reflect in both.So operation performed in any of one variable also reflect in second one. (Single object referenced by two variable).
In Java a variable (except primitives) is always a reference (which has the start address of object) to an object only, Reference is never an object in itself.
For example
second = first;
is assigning a reference, so that first and second now refering to the same object. Objects are not copied, neither in assignments, nor in argument passing (what is copied/assigned is the reference).

Passing by reference ruining everything :(

Hey people i have this structure for the search tree
class State
{
//CLASS STATE
int value;
char[][] state; //the game Grid
State child[]; // children of current state, maximum is 8
State(char[][] src)
{
state=src;
child=new State[8];
}
this is the root node definition
State rootNode = new State(currentGrid);
rootNode.value=-1;
int v =maxValue(rootNode,depth);
after the end of recursion in the max value function the array in rootNode should not be edited since its the the first state but when i Display it i get an array filled with stuff which means that the rootNode.state passed by reference to the max value function :(
//i am trying to implement MiniMax Algorithm.
If you don't want objects that are passed as parameters to be changed, pass in a copy (or make a copy of the parameter inside the method).
Note that char[][] means you have an array of char arrays, i.e. you are working with objects and if you copy the first level you still might have a reference to the second.
Thus you might have to loop through the first level/dimension and copy all the arrays in there, like this:
char target[][] = new char[state.length][0];
for( int i = 0; i < state.length; ++i ) {
target[i] = Arrays.copyOf(state[i], state[i].length);
}
If you need, you can easily create a copy of the array through Arrays.copyOf
You can also create a deep copy. How to do this has been answered here: How to deep copy an irregular 2D array
Yes, Java passes references to arrays and not the array as a value. So if you give a reference to your internal state away, the receiver can change it and the change is "visible" in the source (in fact: it's only one array that has been changed and all reference holders will see the change).
Quick fix/solution: clone your state array and pass a reference to this clone instead of the original. This will keep your internal root state unmodified.

Categories