diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 27494e7..8c96031 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -1024,7 +1024,8 @@ function drupal_bootstrap($phase = NULL) {
 
       switch ($current_phase) {
         case DRUPAL_BOOTSTRAP_CONFIGURATION:
-          $kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), 'prod');
+          $classloader = require __DIR__ . '/../vendor/autoload.php';
+          $kernel = DrupalKernel::createFromRequest($request, $classloader, 'prod');
           break;
 
         case DRUPAL_BOOTSTRAP_KERNEL:
@@ -1399,50 +1400,6 @@ function _current_path($path = NULL) {
 }
 
 /**
- * Initializes and returns the class loader.
- *
- * The class loader is responsible for lazy-loading all PSR-0 compatible
- * classes, interfaces, and traits (PHP 5.4 and later). It's only dependency
- * is DRUPAL_ROOT. Otherwise it may be called as early as possible.
- *
- * @param $class_loader
- *   The name of class loader to use. This can be used to change the class
- *   loader class when calling drupal_classloader() from settings.php. It is
- *   ignored otherwise.
- *
- * @return \Composer\Autoload\ClassLoader
- *   A ClassLoader class instance (or extension thereof).
- */
-function drupal_classloader($class_loader = NULL) {
-  // By default, use the ClassLoader which is best for development, as it does
-  // not break when code is moved on the file system. However, as it is slow,
-  // allow to use the APC class loader in production.
-  static $loader;
-
-  if (!isset($loader)) {
-
-    // Retrieve the Composer ClassLoader for loading classes.
-    $loader = include __DIR__ . '/../vendor/autoload.php';
-
-    // Register the class loader.
-    // When configured to use APC, the ApcClassLoader is registered instead.
-    // Note that ApcClassLoader decorates ClassLoader and only provides the
-    // findFile() method, but none of the others. The actual registry is still
-    // in ClassLoader.
-    if (!isset($class_loader)) {
-      $class_loader = Settings::get('class_loader', 'default');
-    }
-    if ($class_loader === 'apc') {
-      require_once __DIR__ . '/../vendor/symfony/class-loader/Symfony/Component/ClassLoader/ApcClassLoader.php';
-      $apc_loader = new ApcClassLoader('drupal.' . Settings::getHashSalt(), $loader);
-      $loader->unregister();
-      $apc_loader->register();
-    }
-  }
-  return $loader;
-}
-
-/**
  * Registers an additional namespace.
  *
  * @param string $name
@@ -1451,7 +1408,7 @@ function drupal_classloader($class_loader = NULL) {
  *   The relative path to the Drupal component in the filesystem.
  */
 function drupal_classloader_register($name, $path) {
-  $loader = drupal_classloader();
+  $loader = \Drupal::service('class_loader');
   $loader->addPsr4('Drupal\\' . $name . '\\', DRUPAL_ROOT . '/' . $path . '/src');
 }
 
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 4cdc529..a1ab30d 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -286,7 +286,8 @@ function install_begin_request(&$install_state) {
   }
 
   $site_path = DrupalKernel::findSitePath($request, FALSE);
-  Settings::initialize($site_path);
+  $class_loader = require __DIR__ . '/../vendor/autoload.php';
+  Settings::initialize($site_path, $class_loader);
 
   // Ensure that procedural dependencies are loaded as early as possible,
   // since the error/exception handlers depend on them.
@@ -358,7 +359,7 @@ function install_begin_request(&$install_state) {
   }
 
   // Only allow dumping the container once the hash salt has been created.
-  $kernel = InstallerKernel::createFromRequest($request, drupal_classloader(), $environment, (bool) Settings::get('hash_salt', FALSE));
+  $kernel = InstallerKernel::createFromRequest($request, $class_loader, $environment, (bool) Settings::get('hash_salt', FALSE));
   $kernel->setSitePath($site_path);
   $kernel->boot();
   $container = $kernel->getContainer();
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index 7b69341..a7539a8 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -182,11 +182,10 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
    * Create a DrupalKernel object from a request.
    *
    * @param \Symfony\Component\HttpFoundation\Request $request
-   * @param \Composer\Autoload\ClassLoader $class_loader
-   *   (optional) The classloader is only used if $storage is not given or
-   *   the load from storage fails and a container rebuild is required. In
-   *   this case, the loaded modules will be registered with this loader in
-   *   order to be able to find the module serviceProviders.
+   * @param $class_loader
+   *   The class loader to use. Usually an instance of
+   *   \Composer\Autoload\Classloader or
+   *   \Symfony\Component\ClassLoader\ApcClassLoader.
    * @param string $environment
    *   String indicating the environment, e.g. 'prod' or 'dev'.
    * @param bool $allow_dumping
@@ -194,7 +193,7 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
    *   from disk. Defaults to TRUE.
    * @return static
    */
-  public static function createFromRequest(Request $request, ClassLoader $class_loader, $environment, $allow_dumping = TRUE) {
+  public static function createFromRequest(Request $request, $class_loader, $environment, $allow_dumping = TRUE) {
     // Include our bootstrap file.
     require_once dirname(dirname(dirname(__DIR__))) . '/includes/bootstrap.inc';
 
@@ -204,9 +203,7 @@ public static function createFromRequest(Request $request, ClassLoader $class_lo
     static::bootEnvironment();
 
     // Get our most basic settings setup.
-    $site_path = static::findSitePath($request);
-    $kernel->setSitePath($site_path);
-    Settings::initialize($site_path);
+    $kernel->initializeSettings($request);
 
     // Redirect the user to the installation script if Drupal has not been
     // installed yet (i.e., if no $databases array has been defined in the
@@ -220,20 +217,38 @@ public static function createFromRequest(Request $request, ClassLoader $class_lo
   }
 
   /**
+   * Initializes the kernel's site path and the Settings singleton.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The request that will be used to determine the site path.
+   *
+   * @return $this
+   */
+  public function initializeSettings(Request $request) {
+    // This should not be called multiple times.
+    if (isset($this->sitePath)) {
+      throw new \BadMethodCallException('Do not initialize settings multiple times.');
+    }
+
+    $site_path = static::findSitePath($request);
+    $this->setSitePath($site_path);
+    Settings::initialize($site_path, $this->classLoader);
+  }
+
+  /**
    * Constructs a DrupalKernel object.
    *
    * @param string $environment
    *   String indicating the environment, e.g. 'prod' or 'dev'.
-   * @param \Composer\Autoload\ClassLoader $class_loader
-   *   (optional) The class loader is only used if $storage is not given or
-   *   the load from storage fails and a container rebuild is required. In
-   *   this case, the loaded modules will be registered with this loader in
-   *   order to be able to find the module serviceProviders.
+   * @param $class_loader
+   *   The class loader to use. Usually an instance of
+   *   \Composer\Autoload\Classloader or
+   *   \Symfony\Component\ClassLoader\ApcClassLoader.
    * @param bool $allow_dumping
    *   (optional) FALSE to stop the container from being written to or read
    *   from disk. Defaults to TRUE.
    */
-  public function __construct($environment, ClassLoader $class_loader, $allow_dumping = TRUE) {
+  public function __construct($environment, $class_loader, $allow_dumping = TRUE) {
     $this->environment = $environment;
     $this->classLoader = $class_loader;
     $this->allowDumping = $allow_dumping;
@@ -349,8 +364,6 @@ public function boot() {
     // Start a page timer:
     Timer::start('page');
 
-    drupal_classloader();
-
     // Load legacy and other functional code.
     require_once DRUPAL_ROOT . '/core/includes/common.inc';
     require_once DRUPAL_ROOT . '/core/includes/database.inc';
diff --git a/core/lib/Drupal/Core/Site/Settings.php b/core/lib/Drupal/Core/Site/Settings.php
index e2d57d2..274c0da 100644
--- a/core/lib/Drupal/Core/Site/Settings.php
+++ b/core/lib/Drupal/Core/Site/Settings.php
@@ -87,8 +87,14 @@ public static function getAll() {
    *
    * @param string $site_path
    *   The current site path.
+   * @param \Composer\Autoload\ClassLoader $class_loader
+   *   The class loader that is used for this request. This is passed by
+   *   reference and exposed to the settings.php file to allow for it to be
+   *   wrapped with Symfony's ApcClassLoader, for example.
+   *
+   * @see default.settings.php
    */
-  public static function initialize($site_path) {
+  public static function initialize($site_path, &$class_loader) {
     // Export these settings.php variables to the global namespace.
     global $base_url, $cookie_domain, $config_directories, $config;
     $settings = array();
diff --git a/core/modules/simpletest/src/InstallerTestBase.php b/core/modules/simpletest/src/InstallerTestBase.php
index 34354a5..206db40 100644
--- a/core/modules/simpletest/src/InstallerTestBase.php
+++ b/core/modules/simpletest/src/InstallerTestBase.php
@@ -138,7 +138,8 @@ protected function setUp() {
 
     // Import new settings.php written by the installer.
     $request = Request::createFromGlobals();
-    Settings::initialize(DrupalKernel::findSitePath($request));
+    $class_loader = require __DIR__ . '/../../../vendor/autoload.php';
+    Settings::initialize(DrupalKernel::findSitePath($request), $class_loader);
     foreach ($GLOBALS['config_directories'] as $type => $path) {
       $this->configDirectories[$type] = $path;
     }
@@ -150,7 +151,7 @@ protected function setUp() {
     // WebTestBase::tearDown() will delete the entire test site directory.
     // Not using File API; a potential error must trigger a PHP warning.
     chmod(DRUPAL_ROOT . '/' . $this->siteDirectory, 0777);
-    $this->kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), 'prod', FALSE);
+    $this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', FALSE);
     $this->kernel->prepareLegacyRequest($request);
     $this->container = $this->kernel->getContainer();
     $config = $this->container->get('config.factory');
diff --git a/core/modules/simpletest/src/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php
index afea590..a0c80cb 100644
--- a/core/modules/simpletest/src/KernelTestBase.php
+++ b/core/modules/simpletest/src/KernelTestBase.php
@@ -154,7 +154,8 @@ protected function setUp() {
     // Back up settings from TestBase::prepareEnvironment().
     $settings = Settings::getAll();
     // Bootstrap a new kernel. Don't use createFromRequest so we don't mess with settings.
-    $this->kernel = new DrupalKernel('testing', drupal_classloader(), FALSE);
+    $class_loader = require __DIR__ . '/../../../vendor/autoload.php';
+    $this->kernel = new DrupalKernel('testing', $class_loader, FALSE);
     $request = Request::create('/');
     $this->kernel->setSitePath(DrupalKernel::findSitePath($request));
     $this->kernel->boot();
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php
index a12c310..c9ea46f 100644
--- a/core/modules/simpletest/src/WebTestBase.php
+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -853,14 +853,15 @@ protected function setUp() {
     // Since Drupal is bootstrapped already, install_begin_request() will not
     // bootstrap into DRUPAL_BOOTSTRAP_CONFIGURATION (again). Hence, we have to
     // reload the newly written custom settings.php manually.
-    Settings::initialize($directory);
+    $class_loader = require __DIR__ . '/../../../vendor/autoload.php';
+    Settings::initialize($directory, $class_loader);
 
     // Execute the non-interactive installer.
     require_once DRUPAL_ROOT . '/core/includes/install.core.inc';
     install_drupal($parameters);
 
     // Import new settings.php written by the installer.
-    Settings::initialize($directory);
+    Settings::initialize($directory, $class_loader);
     foreach ($GLOBALS['config_directories'] as $type => $path) {
       $this->configDirectories[$type] = $path;
     }
@@ -874,7 +875,7 @@ protected function setUp() {
     chmod($directory, 0777);
 
     $request = \Drupal::request();
-    $this->kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), 'prod', TRUE);
+    $this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', TRUE);
     $this->kernel->prepareLegacyRequest($request);
     // Force the container to be built from scratch instead of loaded from the
     // disk. This forces us to not accidently load the parent site.
diff --git a/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php b/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
index a36adae..65d41c5 100644
--- a/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
+++ b/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
@@ -9,7 +9,7 @@
 
 use Drupal\Core\DrupalKernel;
 use Drupal\Core\Site\Settings;
-use Drupal\simpletest\DrupalUnitTestBase;
+use Drupal\simpletest\KernelTestBase;
 use Symfony\Component\HttpFoundation\Request;
 
 /**
@@ -17,12 +17,7 @@
  *
  * @group DrupalKernel
  */
-class DrupalKernelTest extends DrupalUnitTestBase {
-
-  /**
-   * @var \Composer\Autoload\ClassLoader
-   */
-  protected $classloader;
+class DrupalKernelTest extends KernelTestBase {
 
   protected function setUp() {
     // DrupalKernel relies on global $config_directories and requires those
@@ -38,8 +33,6 @@ protected function setUp() {
       'directory' => DRUPAL_ROOT . '/' . $this->public_files_directory . '/php',
       'secret' => Settings::getHashSalt(),
     )));
-
-    $this->classloader = drupal_classloader();
   }
 
   /**
@@ -59,7 +52,8 @@ protected function setUp() {
    */
   protected function getTestKernel(Request $request, array $modules_enabled = NULL, $read_only = FALSE) {
     // Manually create kernel to avoid replacing settings.
-    $kernel = DrupalKernel::createFromRequest($request, drupal_classloader(), 'testing');
+    $class_loader = require __DIR__ . '/../../../../../vendor/autoload.php';
+    $kernel = DrupalKernel::createFromRequest($request, $class_loader, 'testing');
     $this->settingsSet('hash_salt', $this->databasePrefix);
     if (isset($modules_enabled)) {
       $kernel->updateModules($modules_enabled);
diff --git a/core/modules/system/src/Tests/System/IgnoreReplicaSubscriberTest.php b/core/modules/system/src/Tests/System/IgnoreReplicaSubscriberTest.php
index 49d11ec..429285a 100644
--- a/core/modules/system/src/Tests/System/IgnoreReplicaSubscriberTest.php
+++ b/core/modules/system/src/Tests/System/IgnoreReplicaSubscriberTest.php
@@ -32,7 +32,8 @@ function testSystemInitIgnoresSecondaries() {
     Database::addConnectionInfo('default', 'replica', $connection_info['default']);
 
     db_ignore_replica();
-    $kernel = new DrupalKernel('testing', drupal_classloader(), FALSE);
+    $class_loader = require __DIR__ . '/../../../../../vendor/autoload.php';
+    $kernel = new DrupalKernel('testing', $class_loader, FALSE);
     $event = new GetResponseEvent($kernel, Request::create('http://example.com'), HttpKernelInterface::MASTER_REQUEST);
     $subscriber = new ReplicaDatabaseIgnoreSubscriber();
     $subscriber->checkReplicaServer($event);
diff --git a/core/rebuild.php b/core/rebuild.php
index f7acbce..c915aff 100644
--- a/core/rebuild.php
+++ b/core/rebuild.php
@@ -25,7 +25,7 @@
 // Manually resemble early bootstrap of DrupalKernel::boot().
 require_once __DIR__ . '/includes/bootstrap.inc';
 DrupalKernel::bootEnvironment();
-Settings::initialize(DrupalKernel::findSitePath($request));
+Settings::initialize(DrupalKernel::findSitePath($request), $autoloader);
 
 if (Settings::get('rebuild_access', FALSE) ||
   ($request->get('token') && $request->get('timestamp') &&
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index 017fe8a..f9b6ab7 100644
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -377,11 +377,26 @@
  * cached class loader solution for better performance, which is
  * recommended for production sites.
  *
- * Examples:
- *   $settings['class_loader'] = 'apc';
- *   $settings['class_loader'] = 'default';
+ * For this reason the $class_loader variable is available when this file is
+ * loaded.
+ *
+ * To use Symfony's APC class loader, for example, uncomment the code below.
+ *
+ * @see \Symfony\Component\ClassLoader\ApcClassLoader
+ */
+/**
+use Symfony\Component\ClassLoader\ApcClassLoader;
+
+// Do not do anything if no hash salt is set.
+if ($settings['hash_salt']) {
+  // Wrap $class_loader with Symfony's APC class loader.
+  $apc_loader = new ApcClassLoader('drupal.' . $settings['hash_salt'], $class_loader);
+  $class_loader->unregister();
+  $apc_loader->register();
+  // Replace the $class_loader variable.
+  $class_loader = $apc_loader;
+}
  */
-# $settings['class_loader'] = 'apc';
 
 /**
  * Authorized file system operations:
