I'd like to know what is the life cycle of a class (or object), I mean, when it gets into memory and is alive answering messages until finally gets removed from memory.
My assumptions are:
Ok, so an object is alive from its instantiation until garbage collection kills it or you send it a destroy message (or maybe its class)
But, how you instantiate a class to make it alive? you cannot send a NEW message to a kind of metaclass (and if so, what is the metametaclass to instantiate a metaclass?) So, are classes alive by default? Every class in smalltalk library is loaded into memory when you load an image? is really a lot of classes in memory at any time? if so, how can I see classes and objects in memory in certain moment in time?
As Leandro and Bert have described, you can send new
to metaclass. The circular references this creates are somewhat difficult to think about, but they represent a "simplicity" and "elegance" of design and implementation (where beauty is in the eye of the beholder!). I've included a drawing below that shows how this works. Note especially the cycle between Metaclass
and Metaclass class
.
Metaclass allInstances
.Note also that while most Smalltalks have ClassBuilder, not all do so (GemStone does not), and its properties and behavior can be folded into Behavior.
Additional questions:
Every Smalltalk has a ClassBuilder
class, whose instances have the purpose of creating new classes. A ClassBuilder
does this by creating first the Metaclass
for the class about to be built, sending the class message #new
to Metaclass
. Then it is the Metaclass
just created the one that creates its sole instance using the primive 'New'
.
The reason for having a ClassBuilder
is that classes not only are created, they may be modified. For example, a class may change its superclass with another, or keep it but change the shape of its instances or its own shape.
The ClassBuilder
takes care of all the details, and also is responsible for recompiling instance or class methods when the shape changes. Note that a change in one class will impact all its subclasses, if any. So, all the tasks required for the class need also proceed in subclasses.
In addition, new classes need to be installed, in the sense that they must be included in the Smalltalk dictionary so to keep them both accessible and alive.
Note finally that in the case of a change in shape (which can be explicit or the consequence of changing the superclass with another), existing instances of the class must be migrated so to conform to the new shape. All these tasks make the process that runs behind the scenes non-trivial. However, you can follow it from the time you send the class definition message all the way down to the 'New
' primitive and to the migration of existing instances.
Regarding the way classes are garbage collected, well, there is nothing special here. Smalltalk doesn't have any destroy message. Objects that are no longer referenced become ready to be collected. Even objects which may still be referenced could be collected, as it is the case with two objects that reference each other but are not referenced from the "outside", i.e., (possibly indirectly) from any root.
The reason why classes are not (easily) GCed is because they are referenced from the Smalltalk
dictionary, which is one of the roots of the system. Of course, you can manually remove a class, which means that it will be removed from the Smalltalk
dictionary. In those cases the environment will assist the programmer into finding whether there are references to the Association
binding the class name to the class object from other classes. The environment will also assist the programmer in checking whether the class about to be removed has instances or sublasses. Also, since every class knows its subclasses, classes are referenced from there, so the superclass needs to remove the class from its list of subclasses as part of the process of deleting the class.
Addendum (from the comments below)
Q. Who creates the ClassBuilder
class?
A. This is one of the (many) bootstrapping problems that every Smalltalk dialect solves. Any Smalltalk is born from a kernel, i.e., a minimal set of classes and instances with just enough support for creating new classes. Depending on the dialect, ClassBuilder
may belong or not in the kernel. If it doesn't, then you can still create classes by hand, as the only that is needed is to be able to send the #new
message to Metaclass
. Note however that Metaclass
(the class) needs to be in the kernel for any of this to work. Also, when you save the image all the objects (including classes and methods, which are objects too), are saved to disk. Afterwards, when you load the image in memory, the very same objects are there, and any running processes (which are also Smalltalk objects) that were running at saving time, will resume where they were interrupted when the save operation took place. Note also that no object is "instantiated", they are just loaded from disk into memory in a copy (+ possible relocate) primitive operation. So, no #new
is involved when you load the image as the objects are already there.
Q. How ClassBuilder
gets instantiated itself?
A. You may think of it as built by hand and then saved in the image. So, the next time you load the image ClassBuilder
(the class) will be available. Actually, the complexity of ClassBuilder
may require several iterations. The system/runtime programmer may start by creating a very simple version of it, to be handled with care, and then use this incipient class to refine itself in further iterations.
Q. Is there a Metaclass
for every class?
A. Yes.
Q. Is there any book to learn about internals and implementation of Smalltalk?
A. Smalltalk-80 The Language and its Implementation (you can find it online)
All the classes in a live Smalltalk system are objects. Some were created a long time ago when the system was bootstrapped (e.g. some objects in Squeak are more than 20 years old). The memory occupied by the objects is saved to disk as an "image" file and then resumed later when you "start" that image, but the objects aren't created over and over again.
This is unlike in most other programming systems where classes and objects are created from source code every time you run a program. In Smalltalk, the objects are live in memory. The System Browser shows you a textual view of all the class objects in the system. You can "file out" a textual representation of a class but that text is not the original source code. The original source lives in the class objects in memory.
To create a new class, you send a message to its superclass:
Object subclass: #NameOfClass
instanceVariableNames: 'instVarName1 instVarName2'
classVariableNames: 'ClassVarName1 ClassVarName2'
poolDictionaries: ''
category: 'Kernel-Objects'
which you normally do by "accepting" this template in a browser window. This instructs the existing superclass (Object
in this case) to create a new class. Leandro's answer goes into the details of that. But essentially it is sending new
to Metaclass
to create a new metaclass object, and then sending new
to that metaclass to create the actual class object. You can see the result of that by sending the class
message:
'abc' class. "=> String"
'abc' class class. "=> String class"
'abc' class class class. "=> Metaclass"
So in this case, 'abc'
is an instance of String
, which is an instance of String class
, which is an instance of Metaclass
.
The Metaclass
object itself is part of the base system and has been instantiated many many years ago (arguably in the early 1980ies).
The details of this are a little bit more complicated but this is a pretty good approximation of what is happening.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With