-1

Please consider the following bit of code :


import java.util.*;
import java.lang.*;
import java.io.*;

/* Name of the class has to be "Main" only if the class is public. */


class Ideone
{
    public static List<String> arraylist=new ArrayList<String>();

    //add hello n times to the list
    public static void add_to_list(int n)
    {
        if(n==0)
        {
            return;
        }
        else
        {
            String b=new String("hello");
            arraylist.add(b);
            add_to_list(n-1);
        }
    }

    public static void main(String args[]) throws IOException
    {
        add_to_list(5);
        for(String s:arraylist)
        {
            System.out.println(s);
        }
    }
}

I have tried running this program multiple times and I get the same output as :

hello
hello
hello
hello
hello

My assumptions :

  1. String b goes out of the scope once the method add_to_list is executed
  2. I am referencing the arraylist reference indexes outside their scope
  3. Arraylist contains the reference of the strings created in the method.

Hence my question is :

  1. Is there a possibility that the references are cleaned up by the java collector before I print the value?
  2. Did I just get lucky and the Java collector did not run before I read those values?
Sourav Kanta
  • 2,727
  • 1
  • 18
  • 29
  • 4
    The garbage collector will only collect objects which have no _strong_ references to them. – Slaw Oct 03 '19 at 15:41
  • @Slaw can you please explain what a strong reference is? – Sourav Kanta Oct 03 '19 at 15:43
  • @GeorgeZ. If String b goes out of scope will it be still kept in memory? – Sourav Kanta Oct 03 '19 at 15:44
  • 4
    The *variable* `b` goes out of scope, but the object still exists and is ineligible for GC since the list holds a reference to it. If the item is removed from the list, it will be eligible for GC. – Michael Oct 03 '19 at 15:44
  • @Michael so as long an object has its reference stored in memory, ite won't be collected by GC even if it goes out of scope? – Sourav Kanta Oct 03 '19 at 15:47
  • 1
    @SouravKanta Correct. The garbage collector is specifically designed so that you should never be able to see it working. – Louis Wasserman Oct 03 '19 at 15:49
  • @SouravKanta Objects don't really go out of scope. Variables, which hold references, go out of scope, removing one reference to the object. When there are no references left, it is eligible to be removed at some point in the future (well, it's a bit more complicated than that, since a circular reference chain which is itself unreachable will still be removed, but anyway). – Michael Oct 03 '19 at 15:49
  • The Strings are being added to an array list. The array list is not out of scope. – moonboy Oct 03 '19 at 15:53
  • @Michael Thanks a lot. i think I get it now. Coming from a C background I was confused, like in C if I initialize char p[]="hello" inside a method, it would be overwritten after its scope. But I guess the "hello" would be stored in read only memory rather than in the heap. Hence it gets overwritten. – Sourav Kanta Oct 03 '19 at 15:55
  • @Michael if you want to you can just convert your comments into the answer and I would be glad to accept the answer :) Thanks a lot. – Sourav Kanta Oct 03 '19 at 15:56
  • An equivalent to `char p[]=...` does not exist in Java. In java every object is allocated on the heap as if it's created with c++'s `new`. – Mark Jeronimus Oct 03 '19 at 15:57
  • 1
    @SouravKanta The difference is that in Java nothing really exists on the stack except primitives and references. All objects are allocated off-stack. To compensate for piling everything onto the heap, there is a memory for pool newly created objects -- "young gen" -- from which objects are culled off aggressively. – Michael Oct 03 '19 at 15:57
  • @Michael Thanks a lot. I kind of get it now. I will read a bit into it so as to understand memory allocation in Java a bit better. – Sourav Kanta Oct 03 '19 at 16:00
  • Here are some links that might help: https://stackoverflow.com/questions/9809074/; https://stackoverflow.com/questions/10587868/; https://www.javarticles.com/2016/09/java-garbage-collector-reachable-and-unreachable-objects.html. Also, I should rephrase my first comment: The garbage collector will only collect objects which are not strongly reachable from a "garbage collector root". – Slaw Oct 03 '19 at 17:31

2 Answers2

3

your variable arraylist is static, so doesn't go out of scope. It therefore maintains references to its element until the end of the program.

They can't be garbage collected, so you're not "just lucky".

Dragonthoughts
  • 2,180
  • 8
  • 25
  • 28
0

When you create a String using new() operator, it always create a new object in heap memory. In your above code, every time add_to_list() is called it creates a new string object in heap memory and its reference is stored in local variable 'b' which resides in stack memory of add_to_list(). On every call to this method, fresh stack memory is allocated and upon finishing its execution for that particular call, its allocated stack memory is cleared.

But you also adding this string object reference i.e. 'b' to a static ArrayList. Static variables are stored as part of Class object associated with the class and resides in PermGen in Heap memory and will live as long as the class is in memory.

Garbage collection is always working to free memory by clearing any objects without any references. These are objects that are no longer being used. But in your above code all string references are stored in static list and thus they will be garbage collected only when class terminates.

rupaj
  • 66
  • 7