diff --git a/composer.json b/composer.json
index e4f74e0dc807275ab28bfba28f87b39419f4da05..9db48262376a2db549b4a01c52373294a26cbef9 100644
--- a/composer.json
+++ b/composer.json
@@ -21,6 +21,13 @@
     "easyrdf/easyrdf": "0.8.0-beta.1",
     "phpunit/phpunit": "3.7.15"
   },
+  "autoload": {
+    "psr-0": {
+      "Drupal\\Core": "core/lib/",
+      "Drupal\\Component": "core/lib/",
+      "Drupal\\Driver": "drivers/lib/"
+    }
+  },
   "minimum-stability": "dev",
   "config": {
     "vendor-dir": "core/vendor"
diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index e8ccd368a04e05f67d77a1ec4e9709ac07c5354a..c14ab53215995a4bbc13ca2e03044cb1d5bd24db 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -6,8 +6,8 @@
 use Drupal\Core\DrupalKernel;
 use Drupal\Core\Database\Database;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
-use Symfony\Component\ClassLoader\UniversalClassLoader;
-use Symfony\Component\ClassLoader\ApcUniversalClassLoader;
+use Symfony\Component\ClassLoader\ClassLoader;
+use Symfony\Component\ClassLoader\ApcClassLoader;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\DependencyInjection\Container;
 use Symfony\Component\DependencyInjection\Reference;
@@ -3076,78 +3076,41 @@ function ip_address() {
  *   loader class when calling drupal_classloader() from settings.php. It is
  *   ignored otherwise.
  *
- * @return Symfony\Component\ClassLoader\UniversalClassLoader
- *   A UniversalClassLoader class instance (or extension thereof).
+ * @return \Symfony\Component\ClassLoader\ClassLoader
+ *   A ClassLoader class instance (or extension thereof).
  */
 function drupal_classloader($class_loader = NULL) {
-  // By default, use the UniversalClassLoader 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.
+  // 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)) {
 
     // Include the Symfony ClassLoader for loading PSR-0-compatible classes.
-    require_once DRUPAL_ROOT . '/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/UniversalClassLoader.php';
-    if (!isset($class_loader) && class_exists('Drupal\Component\Utility\Settings', FALSE)) {
-      $class_loader = settings()->get('class_loader');
+    require_once DRUPAL_ROOT . '/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/ClassLoader.php';
+    $loader = new ClassLoader();
+
+    // 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');
     }
-
-    switch ($class_loader) {
-      case 'apc':
-        if (function_exists('apc_store')) {
-          require_once DRUPAL_ROOT . '/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php';
-          $loader = new ApcUniversalClassLoader('drupal.' . $GLOBALS['drupal_hash_salt']);
-          break;
-        }
-      // Fall through to the default loader if APC was not loaded, so that the
-      // site does not fail completely.
-      case 'dev':
-      case 'default':
-      default:
-        $loader = new UniversalClassLoader();
-        break;
+    if ($class_loader === 'apc') {
+      require_once DRUPAL_ROOT . '/core/vendor/symfony/class-loader/Symfony/Component/ClassLoader/ApcClassLoader.php';
+      $apc_loader = new ApcClassLoader('drupal.' . $GLOBALS['drupal_hash_salt'], $loader);
+      $apc_loader->register();
+    }
+    else {
+      $loader->register();
     }
 
-    // Register explicit namespaces for Drupal core.
-    // The majority of namespaces that need to be resolved are from Drupal core,
-    // so registering/setting them before vendor libraries saves a few
-    // additional cycles per class lookup.
-    $loader->registerNamespaces(array(
-      'Drupal\Core' => DRUPAL_ROOT . '/core/lib',
-      'Drupal\Component' => DRUPAL_ROOT . '/core/lib',
-      'Drupal\Driver' => DRUPAL_ROOT . '/drivers/lib',
-    ));
-
-    // Register namespaces and PEAR-like prefixes for vendor libraries managed
-    // by Composer. Composer combines libraries that use PHP 5.3 namespaces and
-    // ones that use PEAR-like class prefixes in a single array, but the Symfony
-    // class loader requires them to be registered separately.
+    // Register namespaces for vendor libraries managed by Composer.
     $prefixes_and_namespaces = require DRUPAL_ROOT . '/core/vendor/composer/autoload_namespaces.php';
-    $prefixes = array();
-    $namespaces = array();
-    foreach ($prefixes_and_namespaces as $key => $path) {
-      // If the key:
-      // - Contains a namespace separator, we know it's a namespace.
-      // - Doesn't contain a namespace separator and ends in an "_" (e.g.,
-      //   "Twig_"), it's likely intended as a PEAR-like prefix rather than a
-      //   namespace.
-      // - Doesn't contain a namespace separator or end in an "_" (e.g.,
-      //   "Assetic"), then it could be either a namespace or an incomplete
-      //   PEAR-like prefix, but we assume the former, since the only example of
-      //   that currently in Drupal is Assetic.
-      // @todo Switch to a class loader that doesn't require this guessing:
-      //   http://drupal.org/node/1658720.
-      $is_namespace = (strpos($key, '\\') !== FALSE) && (substr($key, -1) !== '_');
-      if ($is_namespace) {
-        $namespaces[rtrim($key, '\\')] = $path;
-      }
-      else {
-        $prefixes[$key] = $path;
-      }
-    }
-    $loader->registerPrefixes($prefixes);
-    $loader->registerNamespaces($namespaces);
+    $loader->addPrefixes($prefixes_and_namespaces);
 
     // Register the loader with PHP.
     $loader->register();
@@ -3165,7 +3128,7 @@ function drupal_classloader($class_loader = NULL) {
  */
 function drupal_classloader_register($name, $path) {
   $loader = drupal_classloader();
-  $loader->registerNamespace('Drupal\\' . $name, DRUPAL_ROOT . '/' . $path . '/lib');
+  $loader->addPrefix('Drupal\\' . $name, DRUPAL_ROOT . '/' . $path . '/lib');
 }
 
 /**
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index ee14fb37f07a1bb6bf5bce6114c22c8a7e204828..6a26314fde5627eb13a1f500aad1edb1606d7d42 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -11,7 +11,7 @@
 use Drupal\Core\Config\BootstrapConfigStorageFactory;
 use Drupal\Core\CoreBundle;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
-use Symfony\Component\ClassLoader\UniversalClassLoader;
+use Symfony\Component\ClassLoader\ClassLoader;
 use Symfony\Component\Config\Loader\LoaderInterface;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
 use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
@@ -67,7 +67,7 @@ class DrupalKernel extends Kernel implements DrupalKernelInterface {
   /**
    * The classloader object.
    *
-   * @var \Symfony\Component\ClassLoader\UniversalClassLoader
+   * @var \Symfony\Component\ClassLoader\ClassLoader
    */
   protected $classLoader;
 
@@ -110,7 +110,7 @@ class DrupalKernel extends Kernel implements DrupalKernelInterface {
    *   Boolean indicating whether we are in debug mode. Used by
    *   Symfony\Component\HttpKernel\Kernel::__construct(). Drupal does not use
    *   this value currently. Pass TRUE.
-   * @param \Symfony\Component\ClassLoader\UniversalClassLoader $class_loader
+   * @param \Symfony\Component\ClassLoader\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
@@ -119,7 +119,7 @@ class DrupalKernel extends Kernel implements DrupalKernelInterface {
    *   (optional) FALSE to stop the container from being written to or read
    *   from disk. Defaults to TRUE.
    */
-  public function __construct($environment, $debug, UniversalClassLoader $class_loader, $allow_dumping = TRUE) {
+  public function __construct($environment, $debug, ClassLoader $class_loader, $allow_dumping = TRUE) {
     parent::__construct($environment, $debug);
     $this->classLoader = $class_loader;
     $this->allowDumping = $allow_dumping;
@@ -294,7 +294,7 @@ protected function initializeContainer() {
       // All namespaces must be registered before we attempt to use any service
       // from the container.
       $container_modules = $this->container->getParameter('container.modules');
-      $namespaces_before = $this->classLoader->getNamespaces();
+      $namespaces_before = $this->classLoader->getPrefixes();
       $this->registerNamespaces($this->getModuleNamespaces($container_modules));
 
       // If 'container.modules' is wrong, the container must be rebuilt.
@@ -308,9 +308,9 @@ protected function initializeContainer() {
         // registerNamespaces() performs a merge rather than replace, so to
         // effectively remove erroneous registrations, we must replace them with
         // empty arrays.
-        $namespaces_after = $this->classLoader->getNamespaces();
+        $namespaces_after = $this->classLoader->getPrefixes();
         $namespaces_before += array_fill_keys(array_diff(array_keys($namespaces_after), array_keys($namespaces_before)), array());
-        $this->classLoader->registerNamespaces($namespaces_before);
+        $this->registerNamespaces($namespaces_before);
       }
     }
 
@@ -376,7 +376,7 @@ protected function buildContainer() {
     $container->setParameter('container.namespaces', $namespaces);
 
     // Register synthetic services.
-    $container->register('class_loader', 'Symfony\Component\ClassLoader\UniversalClassLoader')->setSynthetic(TRUE);
+    $container->register('class_loader', 'Symfony\Component\ClassLoader\ClassLoader')->setSynthetic(TRUE);
     $container->register('kernel', 'Symfony\Component\HttpKernel\KernelInterface')->setSynthetic(TRUE);
     $container->register('service_container', 'Symfony\Component\DependencyInjection\ContainerInterface')->setSynthetic(TRUE);
     foreach ($this->bundles as $bundle) {
@@ -474,8 +474,6 @@ protected function getModuleNamespaces($moduleFileNames) {
    * Registers a list of namespaces.
    */
   protected function registerNamespaces(array $namespaces = array()) {
-    foreach ($namespaces as $namespace => $dir) {
-      $this->classLoader->registerNamespace($namespace, $dir);
-    }
+    $this->classLoader->addPrefixes($namespaces);
   }
 }
diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module
index b78ff3ccd647dd5dcf05d76dbf9924fc8957c04b..5ad1b393539f186aed4383cde2e03b5b3f18e702 100644
--- a/core/modules/simpletest/simpletest.module
+++ b/core/modules/simpletest/simpletest.module
@@ -526,19 +526,19 @@ function simpletest_classloader_register() {
     $matches = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.' . $info['extension'] . '$/', $info['dir']);
     foreach ($matches as $name => $file) {
       drupal_classloader_register($name, dirname($file->uri));
-      drupal_classloader()->registerNamespace('Drupal\\' . $name . '\\Tests', DRUPAL_ROOT . '/' . dirname($file->uri) . '/tests');
+      drupal_classloader()->addPrefix('Drupal\\' . $name . '\\Tests', DRUPAL_ROOT . '/' . dirname($file->uri) . '/tests');
       // While being there, prime drupal_get_filename().
       drupal_get_filename($type, $name, $file->uri);
     }
   }
 
   // Register the core test directory so we can find Drupal\UnitTestCase.
-  drupal_classloader()->registerNamespace('Drupal\\Tests', DRUPAL_ROOT . '/core/tests');
+  drupal_classloader()->addPrefix('Drupal\\Tests', DRUPAL_ROOT . '/core/tests');
 
   // Manually register phpunit prefixes because they use a classmap instead of a
   // prefix. This can be safely removed if we move to using composer's
   // autoloader with a classmap.
-  drupal_classloader()->registerPrefixes(array(
+  drupal_classloader()->addPrefixes(array(
     'PHPUnit' => DRUPAL_ROOT . '/core/vendor/phpunit/phpunit',
     'File_Iterator' => DRUPAL_ROOT . '/core/vendor/phpunit/php-file-iterator/',
     'PHP_Timer' => DRUPAL_ROOT . '/core/vendor/phpunit/php-timer/',
diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/ClassLoaderTest.php b/core/modules/system/lib/Drupal/system/Tests/Module/ClassLoaderTest.php
index df59ea08d8aae98d7a992c536f9676896deeb85e..2fd8eb93432ac29a1e470f8f2f0befa6edfc05eb 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Module/ClassLoaderTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Module/ClassLoaderTest.php
@@ -13,6 +13,12 @@
  * Tests class loading.
  */
 class ClassLoaderTest extends WebTestBase {
+
+  /**
+   * The expected result from calling the module-provided class' method.
+   */
+  protected $expected = 'Drupal\\module_autoload_test\\SomeClass::testMethod() was invoked.';
+
   public static function getInfo() {
     return array(
       'name' => 'Module class loader',
@@ -23,24 +29,33 @@ public static function getInfo() {
 
   /**
    * Tests that module-provided classes can be loaded when a module is enabled.
+   *
+   * @see \Drupal\module_autoload_test\SomeClass
    */
   function testClassLoading() {
-    $expected = 'Drupal\\module_autoload_test\\SomeClass::testMethod() was invoked.';
-
+    // Enable the module_test and module_autoload_test modules.
     module_enable(array('module_test', 'module_autoload_test'), FALSE);
     $this->resetAll();
     // Check twice to test an unprimed and primed system_list() cache.
     for ($i=0; $i<2; $i++) {
       $this->drupalGet('module-test/class-loading');
-      $this->assertText($expected, 'Autoloader loads classes from an enabled module.');
+      $this->assertText($this->expected, 'Autoloader loads classes from an enabled module.');
     }
+  }
 
+  /**
+   * Tests that module-provided classes can't be loaded from disabled modules.
+   *
+   * @see \Drupal\module_autoload_test\SomeClass
+   */
+  function testClassLoadingDisabledModules() {
+    // Ensure that module_autoload_test is disabled.
     module_disable(array('module_autoload_test'), FALSE);
     $this->resetAll();
     // Check twice to test an unprimed and primed system_list() cache.
     for ($i=0; $i<2; $i++) {
       $this->drupalGet('module-test/class-loading');
-      $this->assertNoText($expected, 'Autoloader does not load classes from a disabled module.');
+      $this->assertNoText($this->expected, 'Autoloader does not load classes from a disabled module.');
     }
   }
 }
diff --git a/core/vendor/composer/autoload_namespaces.php b/core/vendor/composer/autoload_namespaces.php
index 54b2551e7bcff6026d85e2320fe922b17007137f..3d8eaaf67ac989331729dd2fb00da3d356b81b90 100644
--- a/core/vendor/composer/autoload_namespaces.php
+++ b/core/vendor/composer/autoload_namespaces.php
@@ -6,6 +6,9 @@
 $baseDir = dirname($vendorDir);
 
 return array(
+    'Drupal\\Driver' => $baseDir . '/../drivers/lib/',
+    'Drupal\\Core' => $baseDir . '/lib/',
+    'Drupal\\Component' => $baseDir . '/lib/',
     'Twig_' => $vendorDir . '/twig/twig/lib/',
     'Symfony\\Component\\Yaml\\' => $vendorDir . '/symfony/yaml/',
     'Symfony\\Component\\Validator\\' => $vendorDir . '/symfony/validator/',