How Chromium on Android Dynamically Loads Feature Modules

This article provides an overview of how the Chromium browser on Android minimizes its initial download size by utilizing Dynamic Feature Modules (DFMs). By leveraging Android App Bundles and the Google Play Core library, Chromium strips non-essential features—such as Augmented Reality (AR), Virtual Reality (VR), and specific enterprise tools—out of the base installation. When a user triggers one of these features, the browser dynamically downloads, links, and executes the required Java code, native C++ libraries, and UI resources on the fly without requiring an application restart.

The Architecture of Split APKs

To keep the initial download small, Chromium compiles its codebase into an Android App Bundle (AAB) rather than a single monolithic APK. This bundle is divided into a "base" module, which contains the core web rendering engine and essential browser UI, and multiple "feature splits." Each split is an independent APK that packages the compiled Java bytecode (DEX files), native C++ libraries (.so files), and Android resources required for a specific, less-commonly used feature.

Requesting Modules on Demand

In the Chromium codebase, features packaged as DFMs are gated behind an internal module installer API that communicates with the Google Play Core library.

  1. Detection: A user navigates to a website or clicks a UI element that requires a specific capability, such as WebXR.
  2. Verification: Chromium checks with the Android Package Manager to see if the required split APK is already installed on the device.
  3. Download: If the module is missing, Chromium initiates an asynchronous network request to the Google Play Store. The Play Store downloads and installs the specific split APK in the background while the user continues browsing.

Isolated Splits and Java ClassLoading

Once the Play Store installs the module, Chromium must load the new Java code into the currently running application process. On modern Android versions, Chromium relies on an Android manifest configuration called Isolated Splits.

Instead of merging the new code into the base application's ClassLoader—which would require restarting the app or triggering expensive runtime verification—Android creates a separate, dedicated ClassLoader just for the downloaded feature module.

These classloaders are arranged in a tree hierarchy. The feature module's ClassLoader delegates to the base module's ClassLoader, allowing the feature to directly reference core browser classes. Because the base module cannot directly see the feature module's classes at compile time, Chromium uses Java reflection to instantiate a single entry-point class in the feature module, which then hooks into pre-defined Java interfaces in the base module.

Dynamic Linking of Native C++ Code

Because the majority of Chromium is written in C++, loading Java code is only half the process. Feature modules often contain their own compiled C++ code.

To save disk space on the user's device, Chromium stores the feature's native .so libraries uncompressed and page-aligned inside the split APK. When the module is triggered, Chromium uses the Android system linker (dlopen) to map the .so file directly from the APK zip archive into the device's memory, completely bypassing the need to extract the file to the device's storage.

Once the native library is mapped into memory, it resolves its dependencies against the base module's core C++ library. Finally, Chromium executes a dynamic JNI (Java Native Interface) registration step, which binds the newly loaded Java methods in the isolated ClassLoader to their corresponding C++ memory addresses.

Merging UI Resources

Features frequently require their own UI layouts, localized strings, and graphics. During the Chromium build process, each feature module is assigned a unique resource package ID to prevent its resource identifiers from colliding with those in the base APK.

When a DFM is loaded at runtime, Chromium creates a new Context for the feature, which automatically updates the underlying AssetManager to include the file path to the newly downloaded split APK. Once the AssetManager is updated, the feature module can seamlessly inflate XML layouts and read strings just as if they had been installed with the original browser download.