diff --git a/core/includes/common.inc b/core/includes/common.inc
index 11f8a9d..c21db61 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -2728,7 +2728,7 @@ function drupal_flush_all_caches() {
       $files[$name] = $extension;
     }
   }
-  \Drupal::service('kernel')->updateModules($module_handler->getModuleList(), $files);
+  \Drupal::service('kernel')->updateModules(\Drupal::config('core.extension')->get('module'), $files);
   // New container, new module handler.
   $module_handler = \Drupal::moduleHandler();
 
diff --git a/core/lib/Drupal/Core/CoreServiceProvider.php b/core/lib/Drupal/Core/CoreServiceProvider.php
index ff821b9..ff17cf1 100644
--- a/core/lib/Drupal/Core/CoreServiceProvider.php
+++ b/core/lib/Drupal/Core/CoreServiceProvider.php
@@ -16,7 +16,7 @@
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\DependencyInjection\Compiler\ModifyServiceDefinitionsPass;
 use Drupal\Core\DependencyInjection\Compiler\TaggedHandlersPass;
-use Drupal\Core\DependencyInjection\Compiler\RegisterKernelListenersPass;
+use Drupal\Core\DependencyInjection\Compiler\RegisterEventListenersPass;
 use Drupal\Core\DependencyInjection\Compiler\RegisterAccessChecksPass;
 use Drupal\Core\DependencyInjection\Compiler\RegisterServicesForDestructionPass;
 use Drupal\Core\Plugin\PluginManagerPass;
@@ -67,7 +67,7 @@ public function register(ContainerBuilder $container) {
     $container->addCompilerPass(new RegisterStreamWrappersPass());
 
     // Add a compiler pass for registering event subscribers.
-    $container->addCompilerPass(new RegisterKernelListenersPass(), PassConfig::TYPE_AFTER_REMOVING);
+    $container->addCompilerPass(new RegisterEventListenersPass(), PassConfig::TYPE_AFTER_REMOVING);
 
     $container->addCompilerPass(new RegisterAccessChecksPass());
 
diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterKernelListenersPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterEventListenersPass.php
similarity index 54%
rename from core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterKernelListenersPass.php
rename to core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterEventListenersPass.php
index 33b2683..21a3650 100644
--- a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterKernelListenersPass.php
+++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterEventListenersPass.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\Core\DependencyInjection\Compiler\RegisterKernelListenersPass.
+ * Contains \Drupal\Core\DependencyInjection\Compiler\RegisterEventListenersPass.
  */
 
 namespace Drupal\Core\DependencyInjection\Compiler;
@@ -10,7 +10,10 @@
 use Symfony\Component\DependencyInjection\ContainerBuilder;
 use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
 
-class RegisterKernelListenersPass implements CompilerPassInterface {
+/**
+ * Registers listeners for all services tagged with 'event_subscriber'.
+ */
+class RegisterEventListenersPass implements CompilerPassInterface {
   public function process(ContainerBuilder $container) {
     if (!$container->hasDefinition('event_dispatcher')) {
       return;
@@ -19,8 +22,44 @@ public function process(ContainerBuilder $container) {
     $definition = $container->getDefinition('event_dispatcher');
 
     $event_subscriber_info = [];
-    foreach ($container->findTaggedServiceIds('event_subscriber') as $id => $attributes) {
 
+    $module_parameter = $container->hasParameter('container.modules') ? $container->getParameter('container.modules') : [];
+
+    // First collect all tagged services in order to sort them by module weight
+    // and class name.
+
+    $weights = [];
+    // First figure out all module weights.
+    $ids = array_keys($container->findTaggedServiceIds('event_subscriber'));
+    $id_class_map = [];
+    foreach ($ids as $id) {
+      $class = $container->getDefinition($id)->getClass();
+      $id_class_map[$id] = $class;
+
+      list($drupal, $provider, $rest) = explode('\\', $class, 3);
+
+      // If set in the module configuration, we use the module weight.
+      if ($drupal == 'Drupal' && isset($module_parameter[$provider]['weight'])) {
+        $weight = $module_parameter[$provider]['weight'];
+      }
+      else {
+        $weight = 0;
+      }
+      $weights[$id] = $weight;
+    }
+
+    // Sort the IDs first by module weight, then by full class name. Using the
+    // full class name takes into account the module name automatically.
+    usort($ids, function($a, $b) use ($weights, $id_class_map) {
+      if ($weights[$a] !== $weights[$b]) {
+        return $weights[$a] < $weights[$b] ? -1 : 1;
+      }
+      else {
+        return $id_class_map[$a] < $id_class_map[$b] ? -1 : 1;
+      }
+    });
+
+    foreach ($ids as $id) {
       // We must assume that the class value has been correctly filled, even if the service is created by a factory
       $class = $container->getDefinition($id)->getClass();
 
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index d5e6059..dbde707 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -78,13 +78,13 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface {
    * Holds the list of enabled modules.
    *
    * @var array
-   *   An associative array whose keys are module names and whose values are
-   *   ignored.
+   *   An associative array whose keys are module names and whose values is the
+   *   module weight.
    */
   protected $moduleList;
 
   /**
-   * List of available modules and installation profiles.
+   * List of available module and profile extension objects keyed by name.
    *
    * @var \Drupal\Core\Extension\Extension[]
    */
@@ -638,10 +638,7 @@ protected function moduleData($module) {
   }
 
   /**
-   * Implements Drupal\Core\DrupalKernelInterface::updateModules().
-   *
-   * @todo Remove obsolete $module_list parameter. Only $module_filenames is
-   *   needed.
+   * {@inheritdoc}
    */
   public function updateModules(array $module_list, array $module_filenames = array()) {
     $this->moduleList = $module_list;
@@ -1204,12 +1201,14 @@ protected function getConfigStorage() {
    */
   protected function getModulesParameter() {
     $extensions = array();
-    foreach ($this->moduleList as $name => $weight) {
+
+    foreach ($this->ensureModuleList() as $name => $weight) {
       if ($data = $this->moduleData($name)) {
         $extensions[$name] = array(
           'type' => $data->getType(),
           'pathname' => $data->getPathname(),
           'filename' => $data->getExtensionFilename(),
+          'weight' => $weight,
         );
       }
     }
@@ -1313,4 +1312,17 @@ public static function validateHostname(Request $request) {
     return TRUE;
   }
 
+  /**
+   * Determines the module list.
+   *
+   * @return array|bool
+   */
+  protected function ensureModuleList() {
+    if (isset($this->moduleList)) {
+      return $this->moduleList;
+    }
+    $extensions = $this->getConfigStorage()->read('core.extension');
+    return isset($extensions['module']) ? $extensions['module'] : [];
+  }
+
 }
diff --git a/core/lib/Drupal/Core/DrupalKernelInterface.php b/core/lib/Drupal/Core/DrupalKernelInterface.php
index e7c468f..1ec8fa1 100644
--- a/core/lib/Drupal/Core/DrupalKernelInterface.php
+++ b/core/lib/Drupal/Core/DrupalKernelInterface.php
@@ -87,7 +87,7 @@ public function getAppRoot();
    * list.
    *
    * @param array $module_list
-   *   The new list of modules.
+   *   The list of module weights, keyed by module name.
    * @param array $module_filenames
    *   List of module filenames, keyed by module name.
    */
diff --git a/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php
index 80f7796..abc156b 100644
--- a/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php
@@ -70,7 +70,7 @@ public function onException(GetResponseForExceptionEvent $event) {
    * Cookie provider to send all relevant session data to the user.
    */
   public static function getSubscribedEvents() {
-    $events[KernelEvents::RESPONSE][] = ['onRespond', 0];
+    $events[KernelEvents::RESPONSE][] = ['onRespond', -10];
     $events[KernelEvents::EXCEPTION][] = ['onException', 75];
     return $events;
   }
diff --git a/core/lib/Drupal/Core/EventSubscriber/PathRootsSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/PathRootsSubscriber.php
index 8d96767..d7d4b5c 100644
--- a/core/lib/Drupal/Core/EventSubscriber/PathRootsSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/PathRootsSubscriber.php
@@ -26,7 +26,7 @@ class PathRootsSubscriber implements EventSubscriberInterface {
    *
    * @var array
    */
-  protected $pathRoots;
+  protected $pathRoots = [];
 
   /**
    * The state key value store.
diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
index 73278d3..cc70fb7 100644
--- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php
+++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
@@ -195,7 +195,7 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
         drupal_static_reset('system_rebuild_module_data');
 
         // Update the kernel to include it.
-        $this->updateKernel($module_filenames);
+        $this->updateKernel($extension_config->get('module'), $module_filenames);
 
         // Refresh the schema to include it.
         drupal_get_schema(NULL, TRUE);
@@ -410,7 +410,7 @@ public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
       \Drupal::service('router.builder_indicator')->setRebuildNeeded();
 
       // Update the kernel to exclude the uninstalled modules.
-      $this->updateKernel($module_filenames);
+      $this->updateKernel($extension_config->get('module'), $module_filenames);
 
       // Update the theme registry to remove the newly uninstalled module.
       drupal_theme_rebuild();
@@ -487,12 +487,12 @@ protected function removeCacheBins($module) {
    * @param string $module_filenames
    *   The list of installed modules.
    */
-  protected function updateKernel($module_filenames) {
+  protected function updateKernel($module_list, $module_filenames) {
     // This reboots the kernel to register the module's bundle and its services
     // in the service container. The $module_filenames argument is taken over as
     // %container.modules% parameter, which is passed to a fresh ModuleHandler
     // instance upon first retrieval.
-    $this->kernel->updateModules($module_filenames, $module_filenames);
+    $this->kernel->updateModules($module_list, $module_filenames);
     // After rebuilding the container we need to update the injected
     // dependencies.
     $container = $this->kernel->getContainer();
diff --git a/core/lib/Drupal/Core/Routing/Enhancer/ParamConversionEnhancer.php b/core/lib/Drupal/Core/Routing/Enhancer/ParamConversionEnhancer.php
index a8c1159..0a9217a 100644
--- a/core/lib/Drupal/Core/Routing/Enhancer/ParamConversionEnhancer.php
+++ b/core/lib/Drupal/Core/Routing/Enhancer/ParamConversionEnhancer.php
@@ -86,7 +86,7 @@ public function onException(GetResponseForExceptionEvent $event) {
    * {@inheritdoc}
    */
   public static function getSubscribedEvents() {
-    $events[KernelEvents::EXCEPTION][] = array('onException', 75);
+    $events[KernelEvents::EXCEPTION][] = array('onException', 80);
     return $events;
   }
 
diff --git a/core/modules/simpletest/src/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php
index 6991181..888a643 100644
--- a/core/modules/simpletest/src/KernelTestBase.php
+++ b/core/modules/simpletest/src/KernelTestBase.php
@@ -453,7 +453,7 @@ protected function enableModules(array $modules) {
 
     // Update the kernel to make their services available.
     $module_filenames = $module_handler->getModuleList();
-    $this->kernel->updateModules($module_filenames, $module_filenames);
+    $this->kernel->updateModules($extensions['module'], $module_filenames);
 
     // Ensure isLoaded() is TRUE in order to make _theme() work.
     // Note that the kernel has rebuilt the container; this $module_handler is
@@ -486,7 +486,7 @@ protected function disableModules(array $modules) {
     $module_handler->setModuleList($module_filenames);
     $module_handler->resetImplementations();
     // Update the kernel to remove their services.
-    $this->kernel->updateModules($module_filenames, $module_filenames);
+    $this->kernel->updateModules($extension_config->get('module'), $module_filenames);
 
     // Ensure isLoaded() is TRUE in order to make _theme() work.
     // Note that the kernel has rebuilt the container; this $module_handler is
diff --git a/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php b/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
index 3c43f18..9724cf9 100644
--- a/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
+++ b/core/modules/system/src/Tests/DrupalKernel/DrupalKernelTest.php
@@ -74,8 +74,8 @@ protected function getTestKernel(Request $request, array $modules_enabled = NULL
   public function testCompileDIC() {
     // @todo: write a memory based storage backend for testing.
     $modules_enabled = array(
-      'system' => 'system',
-      'user' => 'user',
+      'system' => 0,
+      'user' => 0,
     );
 
     $request = Request::createFromGlobals();
@@ -150,6 +150,7 @@ public function testCompileDIC() {
       'type' => 'module',
       'pathname' => drupal_get_filename('module', 'service_provider_test'),
       'filename' => NULL,
+      'weight' => 0,
     ));
   }
 
diff --git a/core/tests/Drupal/Tests/Core/DependencyInjection/Compiler/RegisterEventListenersPassTest.php b/core/tests/Drupal/Tests/Core/DependencyInjection/Compiler/RegisterEventListenersPassTest.php
new file mode 100644
index 0000000..a9ef0d4
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/DependencyInjection/Compiler/RegisterEventListenersPassTest.php
@@ -0,0 +1,202 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\DependencyInjection\Compiler\RegisterEventListenersPassTest.
+ */
+
+namespace Drupal\Tests\Core\DependencyInjection\Compiler {
+
+use Drupal\Core\DependencyInjection\Compiler\RegisterEventListenersPass;
+use Drupal\Tests\UnitTestCase;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * @coversDefaultClass \Drupal\Core\DependencyInjection\Compiler\RegisterEventListenersPass
+ * @group DependencyInjection
+ */
+class RegisterEventListenersPassTest extends UnitTestCase {
+
+  /**
+   * The tested compiler pass.
+   *
+   * @var \Drupal\Core\DependencyInjection\Compiler\RegisterEventListenersPass
+   */
+  protected $pass;
+
+  protected function setUp() {
+    parent::setUp();
+
+    $this->pass = new RegisterEventListenersPass();
+  }
+
+  /**
+   * Tests process with a service with an invalid interface.
+   *
+   * @expectedException \InvalidArgumentException
+   */
+  public function testProcessWithWrongInterface() {
+    $builder = new ContainerBuilder();
+    $builder->register('event_dispatcher', 'Symfony\Component\EventDispatcher\EventDispatcher');
+
+    $builder->register('test_service', 'Drupal\Tests\Core\DependencyInjection\Compiler\TestServiceWithoutInterface')
+      ->addTag('event_subscriber');
+    $this->pass->process($builder);
+  }
+
+  /**
+   * Tests process with a single subscriber.
+   */
+  public function testProcessWithSubscriber() {
+    $builder = new ContainerBuilder();
+    $event_dispatcher_definition = $builder->register('event_dispatcher', 'Symfony\Component\EventDispatcher\EventDispatcher');
+
+    $builder->register('test_service', 'Drupal\register_event_listener_pass_test_module\TestService1')
+      ->addTag('event_subscriber');
+
+    $this->pass->process($builder);
+
+    $listeners = $event_dispatcher_definition->getArguments()[0];
+    $this->assertEquals([[0 => ['service' => ['test_service', 'onExample']]]], $listeners['example']);
+  }
+
+  /**
+   * Tests process with multiple listeners and priority.
+   */
+  public function testProcessWithSubscriberWithPriorities() {
+    $builder = new ContainerBuilder();
+    $event_dispatcher_definition = $builder->register('event_dispatcher', 'Symfony\Component\EventDispatcher\EventDispatcher');
+
+    $builder->register('test_service', 'Drupal\register_event_listener_pass_test_module\TestService2')
+      ->addTag('event_subscriber');
+
+    $this->pass->process($builder);
+
+    $listeners = $event_dispatcher_definition->getArguments()[0];
+    $this->assertEquals([
+      10 => [['service' => ['test_service', 'onExample2']]],
+      0 => [['service' => ['test_service', 'onExample1']]]
+    ], $listeners['example']);
+  }
+
+  /**
+   * Tests process with multiple subscribers in different modules and same prio.
+   *
+   * We register the subscribers ascending in the module name.
+   */
+  public function testProcessWithMultipleSubscribersWithModuleWeightAndSamePriorities() {
+    // @FIXME Introduce the weight of the modules.
+
+    $builder = new ContainerBuilder();
+    $event_dispatcher_definition = $builder->register('event_dispatcher', 'Symfony\Component\EventDispatcher\EventDispatcher');
+    $builder->setParameter('container.modules', [
+      'register_event_listener_pass_test_nodule' => [
+        'weight' => -10,
+      ],
+      'register_event_listener_pass_test_module' => [
+        'weight' => 0,
+      ],
+    ]);
+
+    $builder->register('test_service_0', 'Drupal\register_event_listener_pass_test_module\TestService1')
+      ->addTag('event_subscriber');
+    $builder->register('test_service_1', 'Drupal\register_event_listener_pass_test_nodule\TestService1')
+      ->addTag('event_subscriber');
+
+    $this->pass->process($builder);
+
+    $listeners = $event_dispatcher_definition->getArguments()[0];
+    $this->assertEquals([
+      0 => [
+        ['service' => ['test_service_1', 'onExample']],
+        ['service' => ['test_service_0', 'onExample']],
+      ],
+    ], $listeners['example']);
+  }
+
+  /**
+   * Tests process with multiple subscribers, same module and same priorities.
+   *
+   * The idea is that we sort the listeners by class name as well, so
+   * setup the later classname first in the container.
+   */
+  public function testProcessWithMultipleSubscribersSameModuleAndSamePriorities() {
+    $builder = new ContainerBuilder();
+    $event_dispatcher_definition = $builder->register('event_dispatcher', 'Symfony\Component\EventDispatcher\EventDispatcher');
+
+    $builder->register('test_service_0', 'Drupal\register_event_listener_pass_test_module\TestService2')
+      ->addTag('event_subscriber');
+    $builder->register('test_service_1', 'Drupal\register_event_listener_pass_test_module\TestService1')
+      ->addTag('event_subscriber');
+
+    $this->pass->process($builder);
+
+    $listeners = $event_dispatcher_definition->getArguments()[0];
+    $this->assertEquals([
+      10 => [['service' => ['test_service_0', 'onExample2']]],
+      0 => [
+        ['service' => ['test_service_1', 'onExample']],
+        ['service' => ['test_service_0', 'onExample1']]
+      ],
+    ], $listeners['example']);
+  }
+
+}
+
+class TestServiceWithoutInterface {
+
+}
+
+}
+
+namespace Drupal\register_event_listener_pass_test_module {
+
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+class TestService1 implements EventSubscriberInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents() {
+    $events['example'] = 'onExample';
+
+    return $events;
+  }
+
+}
+
+class TestService2 implements EventSubscriberInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents() {
+    $events['example'][] = ['onExample1'];
+    $events['example'][] = ['onExample2', 10];
+
+    return $events;
+  }
+
+}
+}
+
+namespace Drupal\register_event_listener_pass_test_nodule {
+
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+class TestService1 implements EventSubscriberInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents() {
+    $events['example'] = 'onExample';
+
+    return $events;
+  }
+}
+
+}
+
