Where and how are an Objective-C class's methods stored?

methods, objective-c, objective-c-runtime

Solution

In a "standard" Objective-C runtime, every object contains, before any other instance variables, a pointer to the class it is a member of, as if the base Object class had an instance variable called:

Class isa;

Each object of a given class shares the same `isa` pointer.

The class contains a number of elements, including a pointer to the parent class, as well as an array of method lists. These methods are the ones implemented on this class specifically.

struct objc_class {
    Class super_class;
    ...
    struct objc_method_list **methodLists;
    ...
};

These method lists each contain an array of methods:

struct objc_method_list {
    int method_count;
    struct objc_method method_list[];
};

struct objc_method {
    SEL method_name;
    char *method_types;
    IMP method_imp;
};

The `IMP` type here is a function pointer. It points to the (single) location in memory where the implementation of the method is stored, just like any other code.

A note: What I'm describing here is, in effect, the ObjC 1.0 runtime. The current version doesn't store classes and objects quite like this; it does a number of complicated, clever things to make method calls even faster. But what I'm describing still is still the spirit of how it works, if not the exact way it does.

I've also left out a few fields in some of these structures which just confused the situation (e.g, backwards compatibility and/or padding). Read the real headers if you want to see all the gory details.

Problem

I know that when an object is instantiated on the heap, at the least enough memory is allocated to hold the object's ivars. My question is about how methods are stored by the compiler. Is there only one instance of method code in memory? Or is the code generated an intrinsic part of the object in memory, stored contiguously with the ivars and executed? It seems like if the latter were the case, even trivial objects such as `NSString`s would require a (relatively) large amount of memory (`NSString` inherits methods from `NSObject`, also). Or is the method stored once in memory and passed a pointer to the object which owns it?

Original source