Ruby ファイナライザーをいじっていて、私にとって非常に奇妙な動作に気付きました。トリガー コードを次のように減らすことができます。
require "weakref"
class Foo
def initialize
ObjectSpace.define_finalizer(self, self.class.finalize)
end
def self.finalize
proc {
puts "finalizing"
}
end
end
Foo.new # does not work
#WeakRef.new(foo) # Using this instead, everything works as expected
sleep 1
ObjectSpace.garbage_collect
puts "... this did not finalize the object"
Foo.new
ObjectSpace.garbage_collect
puts "but this did?"
プログラムが示すように、Foo.new への 2 回目の呼び出しの前にファイナライザーは実行されません。ガベージ コレクターへの最初の呼び出しの前にさらに遅延を追加しようとしましたが (ただし、私が理解しているように、まったく必要ないはずです)、何もしません。
奇妙なことに、コメントアウトされた行 i を使用すると、期待どおりに最初のファイナライザーが呼び出されます。2番目のものは、プログラムが終了する前にまだ呼び出されていません。
なぜこれが起こっているのか誰でも説明できますか?Ruby 1.9.3p194 (2012-04-20 リビジョン 35410) [x86_64-linux] で Ubuntu 12.10 を実行しています。私はweakrefコードを読んでみましたが、私が知る限り、オブジェクトobject_idを保存して後で取得するだけです。
編集:このような状況でガベージコレクターを手動で呼び出すことは意味がないことを理解しています。この背後にあるメカニズムを理解しようとしているだけです。