Wednesday, December 23, 2009

GC Assertions: Using the Garbage Collector to Check Heap Properties

Assertions are a Good Thing. Sadly, most programming languages support a very limited set of assertions; the most common case is just specifying a boolean expression, based on current variable values, that must evaluate to true in order for the assertion to succeed. Some languages, such as Eiffel, offer a slightly more advanced language for expressing some assertions -- for example, the old keyword can be used in post-conditions to refer to the original value of variables that might have changed during evaluation.

In general, any assertion mechanism that allows programmers to use higher-level concepts, or measure properties that are not readily accessible otherwise, is good progress. Assertions for heap properties are not a new thing, but in GC Assertions: Using the Garbage Collector to Check Heap Properties (PLDI '09), E. A. Aftandilian and S. Z. Guyer suggest both a rich set of heap-related assertions, plus a novel mechanism for performing the tests with minimal runtime overhead (<3% when a significant set of assertion is used).

The authors claim their system to be more precise than static analysis, since it tests the actual, concrete heap, and work well in the presence of (commonly used) mechanisms like reflection and dynamic class loading; more efficient than runtime invariant checks; and more accurate than heuristics.

The set of assertions offered in this system include assert-dead(ref) (zero incoming references), assert-alldead() (for all objects allocated in a marked region), assert-instances(type), num), assert-unshared(ref) (one incoming pointer), and more. Assertion violations provide a dump that shows the path from a memory root (e.g., thread stack or static field) to the violating object.

The system's strength lies in the fact that assertions are tested not when encountered at runtime, but rather on the following GC cycle; but this imposes some limitations on the assertions that can be tested for. What I found missing is (a) a slightly richer set of assertions, with variants such as assert-min-references or assert-max-references; and (b) conditional asserts, as in, "test this assertion only if that condition holds". The conditions can be limited to very trivial ones, e.g., "if ref != null, assert-min-references(ref, 2)" can be used to verify that a given reference to an object is never the only one. (Yes, this specific example can be achieved by means of weak references, but that complicates the program's code, and unlike assertions, it cannot be turned off; I don't want the system to auto-release my reference if it's the last one, I want to assert that it never is.)

All in all, the paper presents a great new take on memory-related assertions. If Design-by-Contract is ever added to the Java language (as it should be), this paper provides a first glimpse into the possibilities of contracts that go beyond the trivial and easily-tested ones, by wisely taking advantage of the managed runtime environment.

0 comments:

Post a Comment