diff --git a/core/includes/utility.inc b/core/includes/utility.inc
index 290821ca7cfebf0d6d46802824d7f805e8ae9741..ff65dc8cf3fb1a93f6673b8f1b9c66bd14f01e06 100644
--- a/core/includes/utility.inc
+++ b/core/includes/utility.inc
@@ -15,14 +15,14 @@
 /**
  * Rebuilds all caches even when Drupal itself does not work.
  *
- * @param \Composer\Autoload\ClassLoader $classloader
- *   The classloader.
+ * @param \Composer\Autoload\ClassLoader $class_loader
+ *   The class loader.
  * @param \Symfony\Component\HttpFoundation\Request $request
  *   The current request.
  *
  * @see rebuild.php
  */
-function drupal_rebuild(ClassLoader $classloader, Request $request) {
+function drupal_rebuild(ClassLoader $class_loader, Request $request) {
   // Remove Drupal's error and exception handlers; they rely on a working
   // service container and other subsystems and will only cause a fatal error
   // that hides the actual error.
@@ -34,7 +34,7 @@ function drupal_rebuild(ClassLoader $classloader, Request $request) {
   PhpStorageFactory::get('twig')->deleteAll();
 
   // Bootstrap up to where caches exist and clear them.
-  $kernel = new DrupalKernel('prod', $classloader);
+  $kernel = new DrupalKernel('prod', $class_loader);
   $kernel->setSitePath(DrupalKernel::findSitePath($request));
   $kernel->prepareLegacyRequest($request);
 
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index be9821d9cacf7da838edd9b7fee91ded2c8dbf75..859240280e833b015df4bf736602dce921d64c96 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -108,7 +108,7 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
   protected $storage;
 
   /**
-   * The classloader object.
+   * The class loader object.
    *
    * @var \Composer\Autoload\ClassLoader
    */
@@ -217,6 +217,7 @@ public static function createFromRequest(Request $request, $class_loader, $envir
     // Include our bootstrap file.
     $core_root = dirname(dirname(dirname(__DIR__)));
     require_once $core_root . '/includes/bootstrap.inc';
+    $class_loader_class = get_class($class_loader);
 
     $kernel = new static($environment, $class_loader, $allow_dumping);
 
@@ -245,6 +246,19 @@ public static function createFromRequest(Request $request, $class_loader, $envir
       $response->prepare($request)->send();
     }
 
+    // If the class loader is still the same, possibly upgrade to the APC class
+    // loader.
+    if ($class_loader_class == get_class($class_loader)
+        && Settings::get('class_loader_auto_detect', TRUE)
+        && Settings::get('hash_salt', FALSE)
+        && function_exists('apc_fetch')) {
+      $prefix = 'drupal.' . hash('sha256', 'drupal.' . Settings::getHashSalt());
+      $apc_loader = new \Symfony\Component\ClassLoader\ApcClassLoader($prefix, $class_loader);
+      $class_loader->unregister();
+      $apc_loader->register();
+      $class_loader = $apc_loader;
+    }
+
     return $kernel;
   }
 
diff --git a/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php b/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
index 03e56fcdf5d7c1faf54e002ee37780f8e3f7e01c..070e9901b80937f1277d7182d3297b699c94656e 100644
--- a/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
+++ b/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
@@ -122,9 +122,9 @@ public function testCompileDIC() {
     $this->assertEqual(array_values($modules_enabled), $module_list);
 
     // Test that our synthetic services are there.
-    $classloader = $container->get('class_loader');
-    $refClass = new \ReflectionClass($classloader);
-    $this->assertTrue($refClass->hasMethod('loadClass'), 'Container has a classloader');
+    $class_loader = $container->get('class_loader');
+    $refClass = new \ReflectionClass($class_loader);
+    $this->assertTrue($refClass->hasMethod('loadClass'), 'Container has a class loader');
 
     // We make this assertion here purely to show that the new container below
     // is functioning correctly, i.e. we get a brand new ContainerBuilder
@@ -150,9 +150,9 @@ public function testCompileDIC() {
     $this->assertTrue($container->has('service_provider_test_class'), 'Container has test service');
 
     // Test that our synthetic services are there.
-    $classloader = $container->get('class_loader');
-    $refClass = new \ReflectionClass($classloader);
-    $this->assertTrue($refClass->hasMethod('loadClass'), 'Container has a classloader');
+    $class_loader = $container->get('class_loader');
+    $refClass = new \ReflectionClass($class_loader);
+    $this->assertTrue($refClass->hasMethod('loadClass'), 'Container has a class loader');
 
     // Check that the location of the new module is registered.
     $modules = $container->getParameter('container.modules');
diff --git a/core/rebuild.php b/core/rebuild.php
index 24474d05b4610a31c90c2a8fd61572366466ab4e..598a4081d4a74b360d4288cae8df7b537ae57800 100644
--- a/core/rebuild.php
+++ b/core/rebuild.php
@@ -20,7 +20,12 @@
 // Change the directory to the Drupal root.
 chdir('..');
 
-$autoloader = require_once 'autoload.php';
+// Clear the APC cache to ensure APC class loader is reset.
+if (function_exists('apc_fetch')) {
+  apc_clear_cache('user');
+}
+
+$autoloader = require_once __DIR__ . '/vendor/autoload.php';
 require_once __DIR__ . '/includes/utility.inc';
 
 $request = Request::createFromGlobals();
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index d4bb0de40051017dda14d0a147d948e1116146eb..3783d0ab7fc6c28daffefb9ff5ec994b5e7dbe37 100644
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -383,18 +383,29 @@
 /**
  * Class Loader.
  *
- * By default, Composer's ClassLoader is used, which is best for development, as
- * it does not break when code is moved in the file system. You can decorate the
- * class loader with a cached solution for better performance, which is
- * recommended for production sites.
- *
- * To do so, you may decorate and replace the local $class_loader variable.
- *
- * For example, to use Symfony's APC class loader, uncomment the code below.
+ * If the APC extension is detected, the Symfony APC class loader is used for
+ * performance reasons. Detection can be prevented by setting
+ * class_loader_auto_detect to false, as in the example below.
+ */
+# $settings['class_loader_auto_detect'] = FALSE;
+
+/*
+ * If the APC extension is not detected, either because APC is missing or
+ * because auto-detection has been disabled, auto-loading falls back to
+ * Composer's ClassLoader, which is good for development as it does not break
+ * when code is moved in the file system. You can also decorate the base class
+ * loader with another cached solution than the Symfony APC class loader, as
+ * all production sites should have a cached class loader of some sort enabled.
+ *
+ * To do so, you may decorate and replace the local $class_loader variable. For
+ * example, to use Symfony's APC class loader without automatic detection,
+ * uncomment the code below.
  */
 /*
 if ($settings['hash_salt']) {
-  $apc_loader = new \Symfony\Component\ClassLoader\ApcClassLoader('drupal.' . $settings['hash_salt'], $class_loader);
+  $prefix = 'drupal.' . hash('sha256', 'drupal.' . $settings['hash_salt']);
+  $apc_loader = new \Symfony\Component\ClassLoader\ApcClassLoader($prefix, $class_loader);
+  unset($prefix);
   $class_loader->unregister();
   $apc_loader->register();
   $class_loader = $apc_loader;