Home > Enterprise >  why object Destructor is not called when I come out of the method
why object Destructor is not called when I come out of the method

Time:01-29

class Raja
  def initialize
    ObjectSpace.define_finalizer(self, self.class.finalize(self))
  end

  def self.finalize(id)
    proc do
      puts "Object #{id.class} got destroyed"
    end
  end
  def hello
    puts 'Raja'
  end
end

def hi
  obj=Raja.new
  obj.hello
end


hi

puts 'Raja'

Consider the preceding program. Because object obj is created inside the hi method and when method call is over, object must have been destroyed, so 'Object #id.class got destroyed' must have been printed, but it's printing after program ends. Why so? Where did my understanding go wrong?

CodePudding user response:

The finalizer gets run when the Garbage Collector collects the object. The Garbage Collector runs when you run out of memory.

Your program only allocates a couple of bytes of memory, so you will never run out of memory and thus the Garbage Collector will never run.

More precisely, the runtime decides when to run the Garbage Collector (and even whether to run the Garbage Collector at all) based on a number of criteria in order to optimize system performance. For example, running the Garbage Collector uses CPU time. So, the runtime tries to find a balance between your program using more memory than strictly necessary (by keeping unreachable objects in memory) and your program using more CPU time than strictly necessary (by running the Garbage Collector even though there is still memory available).

CodePudding user response:

Passing the object itself to the finalize methods and using it inside the finalizer proc interferes with the garbage collection. As noted in the docs:

Note that if your finalizer references the object to be finalized it will never be run on GC, although it will still be run at exit.

Let's fix that by just passing the object's class instead of the object itself: (you could pass the object itself, but you have to take extra care not to expose it to the proc – passing just the class is easier)

class Raja
  def initialize
    ObjectSpace.define_finalizer(self, self.class.finalize(self.class))
  end

  def self.finalize(obj_class)
    proc do
      puts "Object #{obj_class} got destroyed"
    end
  end

  def hello
    puts 'Raja'
  end
end

If you now create a Raja instance, get rid of all references to the object and run garbage collection manually via GC.start:

obj = Raja.new
obj.hello
obj = nil # destroy reference to Raja instance

GC.start

puts 'Done'

... its output should be as expected:

Raja
Object Raja got destroyed
Done

Note that the garbage collection is implementation specific. It might behave differently for the various Ruby implementations and versions.

  •  Tags:  
  • ruby
  • Related