这是来自this question的想法:在创建对象时,增加一个类变量。收集对象后,减少它。如您所见,调用终结器,@@no_foo
递减。但是当我稍后查询它时,减量就消失了。似乎价值只会上升,永不下降(如果我创建两个对象,它将显示2)。我错过了一些明显的东西吗?
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
答案 0 :(得分:6)
它可以工作,但在最终确定中有循环引用。你的终结器取决于应该收集的对象的绑定。请参阅this solution。
class Foo
@@no_foo = 0
def initialize
@@no_foo += 1
ObjectSpace.define_finalizer(self, Foo.method(:delete))
end
def self.delete id # also this argument seems to be necessary
@@no_foo -= 1
end
def self.no_foo
@@no_foo
end
end
Foo.no_foo # => 0
1000.times{Foo.new}
Foo.no_foo # => 1000
GC.start
Foo.no_foo # => 0
答案 1 :(得分:3)
当您认为应该在您提供的代码中时,不会发生最终确定。
例如,如果您将该行更改为:
ObjectSpace.define_finalizer(self, proc do; puts "self is type #{self.class.name} and equals #{self.inspect}"; self.delete; end)
然后注意它是怎么做的(即使我坐在那里等待一段时间)直到我杀了irb:
... (entered class definition from above with that define_finalizer)
1.9.3-p392 :021 > Foo.no_foo # => 0
=> 0
1.9.3-p392 :022 > f = Foo.new
creating object
=> #<Foo:0x007fb5730f3e00>
1.9.3-p392 :023 > f = nil
=> nil
1.9.3-p392 :024 >
1.9.3-p392 :025 > GC.start
=> nil
1.9.3-p392 :026 > Foo.no_foo # => 1
=> 1
1.9.3-p392 :027 > ^D
self is type Foo and equals #<Foo:0x007fb5730f3e00>
deleting object
所以第一个假设可能是没有调用GC。但是,让我们使用GC::Profiler
:
1.9.3p392 :001 > GC::Profiler.enable
... (entered class definition from above)
1.9.3p392 :022 > puts GC::Profiler.result
GC 17 invokes.
Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms)
=> nil
1.9.3p392 :023 > Foo.no_foo # => 0
=> 0
1.9.3p392 :024 > f = Foo.new
creating object
=> #<Foo:0x007fe2fc806808>
1.9.3p392 :025 > puts GC::Profiler.result
GC 17 invokes.
Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms)
=> nil
1.9.3p392 :026 > f = nil
=> nil
1.9.3p392 :027 > puts GC::Profiler.result
GC 17 invokes.
Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms)
=> nil
1.9.3p392 :028 > GC.start
=> nil
1.9.3p392 :029 > puts GC::Profiler.result
GC 18 invokes.
Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms)
1 0.161 997280 2257680 56442 3.96199999999999352696
=> nil
1.9.3p392 :030 > Foo.no_foo # => 1
=> 1
1.9.3p392 :031 > ^D
deleting object
因此,当你提出要求时,看起来GC会被调用,但是在irb退出之前它还没有完成Foo实例。