When is an object suitable for garbage collection?

In a C # 5.0 book in a nutshell by Joseph Albahari I found this

enter image description here where it says, as soon as you pass a line of code where the last variable is used, the object to which it refers has the right to garbage collection (that is, if no other variable contains a link to this object).

However, according to this lecture from UC Berkley, as long as a reference to an object exists on the stack, it will not be garbage collected. I understand that until the method returns, the variable remains on the stack. This means that any object it refers to is alive until the method returns.

Is this a bug in the book, or is java and .net garbage collection working differently?

+6
source share
4 answers

However, according to this lecture from UC Berkley, if an object reference exists on the stack, it will not be garbage collection.

You're right. What you are missing is that the link no longer exists on the stack.

For code that creates an object on the stack:

StringBuilder ref1 = new StringBuilder("object1"); 

variable ref1 is stored on the stack in some memory cell:

  0x403730: Stack Pointer -> 0x40372C: pointer to ref1 0x403728: saved value of EBP 0x403724: saved value of return address 0x403720 

Now comes the following line:

 StringBuilder ref2 = new StringBuilder("object2"); 

Where will the pointer to ref2 be stored? On the stack: yes. But where on the stack? In the same memory cell that was used for ref1 , of course !:

  0x403730: Stack Pointer -> 0x40372C: pointer to ref2 0x403728: saved value of EBP 0x403724: saved value of return address 0x403720 

It would be foolish to just push another value onto the stack:

 Stack Pointer -> 0x403730: pointer to ref2 0x40372C: pointer to ref1 0x403728: saved value of EBP 0x403724: saved value of return address 0x403720 

It would be stupid because ref1 no longer needed.

That's why ref1 has the right to garbage collection: there are no more links to it.

+6
source

The book is correct.

In .NET, the garbage collector has information about where the variable is used in the code, and once it is not used, the object has the right to garbage collection.

(However, if you ran the code with an attached debugger, the garbage collector changed the behavior. It saves the object for the entire scope of the variable, not just where the variable is used, so that the object can be examined in the debugger.)

+5
source

I understand that until the method returns, the variable remains on the stack. This means that any object it refers to is alive until the method returns.

JIT can remove an object reference ("variable") at any time after the last use, so this is optional.

as long as the link to the object exists on the stack, it will not be collected with garbage

This is true, but the JIT may change if this variable no longer exists on the stack, in a way that does not necessarily correspond to your code.

In C # 5, this can become really confusing, since async methods can be rewritten in such a way that the variables will stick for longer than you would expect in some scenarios.

However, if you need to ensure that the object is entitled at some point, setting the variable (s) that references the object to null explicitly allows you to control when it becomes available explicitly.

+4
source

this is the CIL code generated from this method:

 .method private hidebysig static void Main(string[] args) cil managed { .entrypoint // Code size 46 (0x2e) .maxstack 2 .locals init ([0] class [mscorlib]System.Text.StringBuilder ref1, [1] class [mscorlib]System.Text.StringBuilder ref2, [2] class [mscorlib]System.Text.StringBuilder ref3) IL_0000: nop IL_0001: ldstr "object1" IL_0006: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor(string) IL_000b: stloc.0 //here ref1 is stored on stack. IL_000c: ldloc.0 //here it is loaded to be displayed by the console.writeline IL_000d: call void [mscorlib]System.Console::WriteLine(object) IL_0012: nop //from here on no more reference to ref1. IL_0013: ldstr "object2" IL_0018: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor(string) IL_001d: stloc.1 IL_001e: ldloc.1 IL_001f: stloc.2 IL_0020: ldloc.2 IL_0021: call void [mscorlib]System.Console::WriteLine(object) IL_0026: nop //and from here on ref2 and ref3 also. IL_0027: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey() IL_002c: pop IL_002d: ret } // end of method Program::Main 
+2
source

Source: https://habr.com/ru/post/948821/


All Articles