# How MulleObjC Universe Configuration Is Initialized: Runtime Startup Explained

> Discover how MulleObjC initializes its runtime startup for configurations. Learn about dynamic loader symbols and the MulleObjCBang process for setting up the execution environment.

- Repository: [mulle-objc/mulleobjc-startup](https://github.com/mulle-objc/mulleobjc-startup)
- Tags: internals
- Published: 2026-03-07

---

**MulleObjC initializes its runtime by exporting a dynamic loader symbol that copies the default global configuration into a local structure and passes it to `MulleObjCBang`, which allocates and configures the isolated execution environment before any Objective-C code runs.**

The `mulle-objc/mulleobjc-startup` repository provides the minimal bootstrap sequence required to bring up the Mulle Objective-C runtime. Understanding how MulleObjC universe configuration initialization works is essential when you need to customize memory allocation strategies, exception handlers, or thread-local storage defaults before the runtime begins executing.

## Exporting the Registration Symbol

The initialization sequence begins in `src/MulleObjC-startup.m`, where the codebase defines a macro to export the entry point visible to the dynamic loader. At lines 38-41, the `MULLE_OBJC_DEFINE__register_mulle_objc_universe` macro emits the symbol `register_mulle_objc_universe` with the proper `dllexport` attribute. This symbol serves as the hook that the operating system loader invokes when the library is loaded into memory.

The actual implementation is provided by including the private header at line 50:

```c
#include <MulleObjC/mulle-objc-startup-private.inc>

```

This include file contains the `bang` function (lines 62-73) that orchestrates the actual universe creation sequence.

## Retrieving the Default Configuration

Inside the startup sequence, the runtime first obtains the system defaults by calling `mulle_objc_global_get_default_universeconfiguration()`. This function, defined in the core MulleObjC library, returns a pointer to a static, read-only `struct _mulle_objc_universeconfiguration` that contains sensible defaults for memory allocators, exception handling, and foundation integration.

The startup code then copies these defaults into a mutable local structure at lines 66-70:

```c
struct _mulle_objc_universeconfiguration config;
memcpy(&config,
       mulle_objc_global_get_default_universeconfiguration(),
       sizeof(config));

```

This copying step allows the startup sequence to use the library defaults as a template while remaining open to modifications before the universe is created.

## Universe Creation via MulleObjCBang

The core instantiation happens through `MulleObjCBang`, invoked at line 72 within the `bang` helper function. This routine performs the heavy lifting of universe construction:

```c
MulleObjCBang(universe, allocator, &config);

```

According to the implementation in `<MulleObjC/mulle-objc-startup-private.inc>`, `MulleObjCBang` executes three critical operations:

- **Allocation**: It allocates the `_mulle_objc_universe` structure using the supplied `allocator` parameter.
- **Configuration Installation**: It copies the `config` structure into the new universe's `configuration` field, establishing the runtime parameters for class tables, selector tables, and foundation info.
- **Global Registration**: It registers the newly created universe as the default for the current process, ensuring subsequent Objective-C calls resolve to this isolated environment.

After `MulleObjCBang` returns, the exported symbol `register_mulle_objc_universe` completes its execution, leaving a fully initialized universe ready for Objective-C code.

## Customizing the Universe Configuration

You can replace the default configuration before the loader triggers the startup sequence by installing your own configuration globally. This allows you to inject custom memory allocators or exception handlers without modifying the startup source code:

```c
/* Define a custom configuration structure */
static struct _mulle_objc_universeconfiguration myConfig = {
    .allocator = &myCustomAllocator,
    .exception_handler = myExceptionHandler,
    /* additional custom fields */
};

int main(void)
{
    /* Install your configuration before the loader runs */
    mulle_objc_global_set_default_universeconfiguration(&myConfig);
    
    /* The dynamic loader will now invoke register_mulle_objc_universe,
       which calls bang → MulleObjCBang using your custom config */
    return 0;
}

```

If you do not provide a custom configuration, the runtime automatically uses the memcpy sequence shown above to clone the library defaults, ensuring the runtime always starts with a valid configuration structure.

## Summary

- **Entry Point**: The `MULLE_OBJC_DEFINE__register_mulle_objc_universe` macro in `src/MulleObjC-startup.m` exports the `register_mulle_objc_universe` symbol that the dynamic loader calls.
- **Default Copy**: The startup code copies the global default configuration using `mulle_objc_global_get_default_universeconfiguration()` before passing it to the creation routine.
- **Core Function**: `MulleObjCBang` allocates the `_mulle_objc_universe` structure, installs the configuration, and registers the universe as the process default.
- **Customization**: You can override defaults by calling `mulle_objc_global_set_default_universeconfiguration()` before library load, or rely on the automatic memcpy of system defaults.

## Frequently Asked Questions

### What is the MulleObjC universe?

The **MulleObjC universe** is an isolated execution environment that contains all runtime state for Objective-C, including class tables, selector tables, method caches, and configuration settings. It functions as a self-contained sandbox that allows multiple Objective-C runtimes to exist within the same process without interfering with each other.

### Where does the default universe configuration come from?

The default configuration originates from `mulle_objc_global_get_default_universeconfiguration()`, which returns a static structure defined in the core MulleObjC library (outside the startup repository). This structure provides standard defaults for memory allocation, exception handling, and thread-local storage that the startup code copies before universe creation.

### How can I customize the universe configuration before startup?

You can install a custom configuration by defining a `struct _mulle_objc_universeconfiguration` with your preferred settings and calling `mulle_objc_global_set_default_universeconfiguration()` before the dynamic loader invokes the startup sequence. When `register_mulle_objc_universe` executes, it will copy your configuration instead of the library defaults.

### What is the purpose of the `bang` function?

The `bang` function acts as an internal helper within `<MulleObjC/mulle-objc-startup-private.inc>` that bridges the exported registration symbol and the actual universe creation. It handles the memcpy operation to clone the default configuration and then invokes `MulleObjCBang` to perform the allocation and initialization of the runtime universe.