Lably
Skip to content

Tracing garbage collection

Form of computer memory management

  • 23 min read
  • 8 chapters

Related on Lably

Through Computer programming, Local variable and Parameter (computer programming)

Reachability of an object

Informally, an object is reachable if it is referenced by at least one variable in the program, either directly or through references from other reachable objects. More precisely, objects can be reachable in only two ways:

  1. A distinguished set of roots: objects that are assumed to be reachable. Typically, these include all the objects referenced from anywhere in the call stack (that is, all local variables and parameters in the functions currently being invoked), and any global variables.
  2. Anything referenced from a reachable object is itself reachable; more formally, reachability is a transitive closure.

The reachability definition of "garbage" is not optimal, insofar as the last time a program uses an object could be long before that object falls out of the environment scope. A distinction is sometimes drawn between syntactic garbage, those objects the program cannot possibly reach, and semantic garbage, those objects the program will in fact never again use. For example:

<span id="mwIw"></span><span class="n" id="mwJA">Object</span><span class="w" id="mwJQ"> </span><span class="n" id="mwJg">x</span><span class="w" id="mwJw"> </span><span class="o" id="mwKA">=</span><span class="w" id="mwKQ"> </span><span class="k" id="mwKg">new</span><span class="w" id="mwKw"> </span><span class="n" id="mwLA">Foo</span><span class="p" id="mwLQ">();</span> <span class="n" id="mwLg">Object</span><span class="w" id="mwLw"> </span><span class="n" id="mwMA">y</span><span class="w" id="mwMQ"> </span><span class="o" id="mwMg">=</span><span class="w" id="mwMw"> </span><span class="k" id="mwNA">new</span><span class="w" id="mwNQ"> </span><span class="n" id="mwNg">Bar</span><span class="p" id="mwNw">();</span> <span class="n" id="mwOA">x</span><span class="w" id="mwOQ"> </span><span class="o" id="mwOg">=</span><span class="w" id="mwOw"> </span><span class="k" id="mwPA">new</span><span class="w" id="mwPQ"> </span><span class="n" id="mwPg">Quux</span><span class="p" id="mwPw">();</span> <span class="cm" id="mwQA">/* At this point, we know that the Foo object </span> <span class="cm" id="mwQQ"> * originally assigned to x will never be</span> <span class="cm" id="mwQg"> * accessed: it is syntactic garbage.</span> <span class="cm" id="mwQw"> */</span> <span class="cm" id="mwRA">/* In the following block, y *could* be semantic garbage;</span> <span class="cm" id="mwRQ"> * but we won't know until x.check_something() returns</span> <span class="cm" id="mwRg"> * some value -- if it returns at all.</span> <span class="cm" id="mwRw"> */</span> <span class="k" id="mwSA">if</span><span class="w" id="mwSQ"> </span><span class="p" id="mwSg">(</span><span class="n" id="mwSw">x</span><span class="p" id="mwTA">.</span><span class="na" id="mwTQ">check_something</span><span class="p" id="mwTg">())</span><span class="w" id="mwTw"> </span><span class="p" id="mwUA">{</span> <span class="w" id="mwUQ"> </span><span class="n" id="mwUg">x</span><span class="p" id="mwUw">.</span><span class="na" id="mwVA">do_something</span><span class="p" id="mwVQ">(</span><span class="n" id="mwVg">y</span><span class="p" id="mwVw">);</span> <span class="p" id="mwWA">}</span> <span class="n" id="mwWQ">System</span><span class="p" id="mwWg">.</span><span class="na" id="mwWw">exit</span><span class="p" id="mwXA">(</span><span class="mi" id="mwXQ">0</span><span class="p" id="mwXg">);</span>

The problem of precisely identifying semantic garbage can easily be shown to be partially decidable: a program that allocates an object X, runs an arbitrary input program P, and uses X if and only if P finishes would require a semantic garbage collector to solve the halting problem. Although conservative heuristic methods for semantic garbage detection remain an active research area, essentially all practical garbage collectors focus on syntactic garbage.

Another complication with this approach is that, in languages with both reference types and unboxed value types, the garbage collector needs to somehow be able to distinguish which variables on the stack or fields in an object are regular values and which are references: in memory, an integer and a reference might look alike. The garbage collector then needs to know whether to treat the element as a reference and follow it, or whether it is a primitive value. One common solution is the use of tagged pointers.

Sign in to keep reading

7 more chapters are free with a Lably account.

More in Computing and communication