-
Notifications
You must be signed in to change notification settings - Fork 1
Execution and Lifecycle
Ruby is a garbage-collected language. The garbage collector may run on any Ruby thread, either when Ruby chooses to invoke it directly before a memory allocation operation, or when it's explicitly invoked by Ruby code, the core library or an extension library. In the current implementation, the Ruby VM does not create any hidden Ruby threads for the purpose of garbage collection, finalizers or any other purpose.
Ruby allows you to register one or more finalizers to any value which is not an immediate value (i.e. object values only). A finalizer is a block which can be called when the object can be destroyed, and it is called with 1 parameter, which is the object id of the object which is being finalized.
An object id is currently implemented as a representation of a pointer to the object's memory location. As such they are a unique identifier for currently available objects - note that when an object is freed from memory e.g. by the garbage collector, it is possible for another object to be created with the same object ID.
Ruby has 2 mechanisms for invoking finalizers:
- Garbage collection, as part of freeing an object
- VM destruction
The garbage collector frees objects as follows:
- An object is deemed to be dead when it is no longer possible for any code to access the object. This includes finalizer code - if a registered finalizer block can access the object it is intended to finalize, e.g. through its closure on local variables, then the garbage collector will never free it
- The garbage collector may choose to free dead objects when it is invoked
- If the garbage collector chooses to free an object, then the object's finalizers will invoked as follows:
- Any one Ruby thread will be selected to finalize the object, and it will run the object's finalizers in the order in which they were registered
- The object being finalized may already have been freed when its finalizers are invoked
- It is undefined whether the thread invoking the finalizer is holding any Mutex locks - if the finalizer locks Mutexes, it must be careful that the thread it is running in does not already hold the lock
- Some more specific details of the current implementation of the garbage collector:
- Ruby does not currently permit multiple finalizers to be running at once, either on multiple threads or reentrantly (a finalizer run within a finalizer)
- When the garbage collector detects a dead object which has finalizers, the object will be added to a global list of objects with pending finalizers
- During garbage collection, if there are pending finalizers to be run, and no finalizers are currently running, the thread running the garbage collector will be scheduled to execute all pending finalizers at its next interrupt point (as long as at that point no finalizers are running)
- In an explicit invocation of the garbage collector, if no finalizers are currently running, pending finalizers will be run as part of the explicit invocation
- If, after running a list of pending finalizers, there have been more pending finalizers added, these will immediately be run
- Objects with finalizers will be freed from memory before the finalizer runs, either as part of the garbage collection or during the interrupt point
A Ruby Language Reference
Copyright © by Michael Hore, 2016.
Introduction to This Document
Ruby Elements
- Classes and Modules
- Methods
- Blocks, Procs and Lambdas
- Execution Context and Closures
- Variables, Constants and Namespaces
- Types and Literals
- Ruby Expressions
- Operators
Syntax Grammar
Exceptions and Throw
Ruby Sourcefiles and Libraries
Multi Threading
Execution and Lifecycle