Ruby 强制垃圾收集未按预期工作
Ruby forcing garbage collection not working as expected
在下面的代码中:
class ExampleClass
def initialize
ObjectSpace.define_finalizer(self, proc{puts 'dead'})
end
end
ex = ExampleClass.new
ex = nil
GC.start
while true
# the while loop is to prevent the program from terminate
# if the program does terminate, the finalizer gets called in the end like expected
end
此处的终结器从未被调用,也没有输出。我本来希望垃圾收集器收集 ex
因为它已被取消引用。为什么 GC.start
不强制收集 ex
并立即导致 finalizer to be called
?
我相信当你创建一个新的Proc
(proc
just calls Proc.new
, in Kernel
)
Creates a new Proc object, bound to the current context.
意味着它正在保存对 self
对象的引用,因此永远不会被垃圾收集器取消引用以收集它。您应该在 class 方法中创建 proc
,这样上下文就变成 class 而不是您要销毁的实例。
class ExampleClass
def initialize
ObjectSpace.define_finalizer(self, self.class.finalize)
end
def self.finalize
proc { puts "dead" }
end
end
ex = ExampleClass.new
# needed to do something with the object as well, not sure why,
# but it won't work without this line either
puts "object id = #{ex.object_id}"
ex = nil
GC.start
while true
end
这输出
object id = 70223915005060
dead
^Cexample.rb:20:in `<main>': Interrupt
在下面的代码中:
class ExampleClass
def initialize
ObjectSpace.define_finalizer(self, proc{puts 'dead'})
end
end
ex = ExampleClass.new
ex = nil
GC.start
while true
# the while loop is to prevent the program from terminate
# if the program does terminate, the finalizer gets called in the end like expected
end
此处的终结器从未被调用,也没有输出。我本来希望垃圾收集器收集 ex
因为它已被取消引用。为什么 GC.start
不强制收集 ex
并立即导致 finalizer to be called
?
我相信当你创建一个新的Proc
(proc
just calls Proc.new
, in Kernel
)
Creates a new Proc object, bound to the current context.
意味着它正在保存对 self
对象的引用,因此永远不会被垃圾收集器取消引用以收集它。您应该在 class 方法中创建 proc
,这样上下文就变成 class 而不是您要销毁的实例。
class ExampleClass
def initialize
ObjectSpace.define_finalizer(self, self.class.finalize)
end
def self.finalize
proc { puts "dead" }
end
end
ex = ExampleClass.new
# needed to do something with the object as well, not sure why,
# but it won't work without this line either
puts "object id = #{ex.object_id}"
ex = nil
GC.start
while true
end
这输出
object id = 70223915005060
dead
^Cexample.rb:20:in `<main>': Interrupt