DestructorはないけどFinalizerはあった件

http://d.hatena.ne.jp/komamitsu/20090422/1240413644

コードの違いからするとガベコレのタイミングでTCP close()しているようにも思えるけど、Rubyではデストラクタがないからなぁ… どうやってるんだろう?

って書いたのだけど、そこ「ガベコレのタイミング」だったら対応するのは「Finalizer」だYO!!! > 自分

ということでRubyにはObjectSpace.define_finalizerがあるのでした。

こんなコードを書いて…

class Demo
  def self.cleanup
    lambda {puts "finalized!"}
  end

  def initialize
    @a = "abcdefg" * 1024 * 1024 * 2
    ObjectSpace.define_finalizer(self, self.class.cleanup)
  end
end

1.upto 8 do |i|
  puts Time.now
  Demo.new
  sleep 1
end

はしらせてみると

komamitsu@potato:~/lab/ruby$ ruby fin.rb 
Sun Apr 26 22:04:49 +0900 2009
Sun Apr 26 22:04:50 +0900 2009
Sun Apr 26 22:04:51 +0900 2009
finalized!
finalized!
Sun Apr 26 22:04:52 +0900 2009
Sun Apr 26 22:04:53 +0900 2009
Sun Apr 26 22:04:54 +0900 2009
Sun Apr 26 22:04:55 +0900 2009
Sun Apr 26 22:04:56 +0900 2009
finalized!
finalized!
finalized!
finalized!
finalized!
finalized!

となる。

注意すべき点としては、ObjectSpace.define_finalizerで渡しているProcインスタンスからDemoインスタンスへの参照が残らないように気をつけること。あと、私の環境だとDemoの@aのサイズが小さいとガベージコレクションで回収されないみたいだったので無駄に大きくしています。