Here's an idea from this question: Upon object creation, increment a class variable. When object gets collected, decrement it. As you can observe, finalizer is called, and @@no_foo
gets decremented. But when I query it a moment later, decrement is gone. Seems that value is going only up, never down (if I create two objects, it will show 2). Am I missing something obvious?
class Foo
@@no_foo = 0
def initialize
puts 'creating object'
@@no_foo += 1
ObjectSpace.define_finalizer(self, proc { self.delete })
end
def delete
puts 'deleting object'
@@no_foo # => 1
@@no_foo -= 1
@@no_foo # => 0
end
def self.no_foo
@@no_foo # => 0, 1
end
end
Foo.no_foo # => 0
f = Foo.new
f = nil
GC.start
Foo.no_foo # => 1
# >> creating object
# >> deleting object
It can work, but there's circular reference in finalization. Your finalizer depends on the binding of an object that should be collected. See this solution.
Finalization is not happening when you think it should in the code you provided.
For example, if you change that one line to:
Then notice how it does nothing (even if I sit there and wait a while) until I kill irb:
So the first assumption may be that GC was not invoked. But, lets look at it using
GC::Profiler
:So, it looks like the GC is getting invoked when you ask it to, but it is not finalizing the Foo instance until irb exit.