diff --git a/core/core.services.yml b/core/core.services.yml
index 6b8334a..3513c96 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -508,11 +508,6 @@ services:
     calls:
       - [setContext, ['@router.request_context']]
       - [add, ['@router.dynamic']]
-  router.path_roots_subscriber:
-    class: Drupal\Core\EventSubscriber\PathRootsSubscriber
-    arguments: ['@state']
-    tags:
-      - { name: event_subscriber }
   entity.query:
     class: Drupal\Core\Entity\Query\QueryFactory
     arguments: ['@entity.manager']
@@ -645,10 +640,6 @@ services:
     class: Drupal\Core\EventSubscriber\SpecialAttributesRouteSubscriber
     tags:
       - { name: event_subscriber }
-  route_http_method_subscriber:
-    class: Drupal\Core\EventSubscriber\RouteMethodSubscriber
-    tags:
-      - { name: event_subscriber }
   controller.page:
     class: Drupal\Core\Controller\HtmlPageController
     arguments: ['@controller_resolver', '@title_resolver', '@render_html_renderer']
@@ -698,11 +689,6 @@ services:
     arguments: ['@router.route_provider', '@paramconverter_manager', '@access_arguments_resolver_factory', '@current_user']
     calls:
       - [setContainer, ['@service_container']]
-  access_route_subscriber:
-    class: Drupal\Core\EventSubscriber\AccessRouteSubscriber
-    tags:
-      - { name: event_subscriber }
-    arguments: ['@access_manager']
   access_check.default:
     class: Drupal\Core\Access\DefaultAccessCheck
     tags:
diff --git a/core/lib/Drupal/Core/EventSubscriber/AccessRouteSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/AccessRouteSubscriber.php
deleted file mode 100644
index 240073b..0000000
--- a/core/lib/Drupal/Core/EventSubscriber/AccessRouteSubscriber.php
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\EventSubscriber\AccessRouteSubscriber.
- */
-
-namespace Drupal\Core\EventSubscriber;
-
-use Drupal\Core\Access\AccessManagerInterface;
-use Drupal\Core\Routing\RouteBuildEvent;
-use Drupal\Core\Routing\RoutingEvents;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-
-/**
- * Provides a subscriber to set access checkers on route building.
- */
-class AccessRouteSubscriber implements EventSubscriberInterface {
-
-  /**
-   * The access manager.
-   *
-   * @var \Drupal\Core\Access\AccessManagerInterface
-   */
-  protected $accessManager;
-
-  /**
-   * Constructs a new AccessSubscriber.
-   *
-   * @param \Drupal\Core\Access\AccessManagerInterface $access_manager
-   *   The access check manager that will be responsible for applying
-   *   AccessCheckers against routes.
-   */
-  public function __construct(AccessManagerInterface $access_manager) {
-    $this->accessManager = $access_manager;
-  }
-
-  /**
-   * Apply access checks to routes.
-   *
-   * @param \Drupal\Core\Routing\RouteBuildEvent $event
-   *   The event to process.
-   */
-  public function onRoutingRouteAlterSetAccessCheck(RouteBuildEvent $event) {
-    $this->accessManager->setChecks($event->getRouteCollection());
-  }
-
-  /**
-   * Registers the methods in this class that should be listeners.
-   *
-   * @return array
-   *   An array of event listener definitions.
-   */
-  static function getSubscribedEvents() {
-    // Setting very low priority to ensure access checks are run after alters.
-    $events[RoutingEvents::ALTER][] = array('onRoutingRouteAlterSetAccessCheck', -1000);
-
-    return $events;
-  }
-
-}
diff --git a/core/lib/Drupal/Core/EventSubscriber/PathRootsSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/PathRootsSubscriber.php
deleted file mode 100644
index 8d96767..0000000
--- a/core/lib/Drupal/Core/EventSubscriber/PathRootsSubscriber.php
+++ /dev/null
@@ -1,81 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\EventSubscriber\PathRootsSubscriber.
- */
-
-namespace Drupal\Core\EventSubscriber;
-
-use Drupal\Core\State\StateInterface;
-use Drupal\Core\Routing\RouteBuildEvent;
-use Drupal\Core\Routing\RoutingEvents;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-use Symfony\Component\Routing\RouteCollection;
-
-/**
- * Provides all available first bits of all route paths.
- */
-class PathRootsSubscriber implements EventSubscriberInterface {
-
-  /**
-   * Stores the path roots available in the router.
-   *
-   * A path root is the first virtual directory of a path, like 'admin', 'node'
-   * or 'user'.
-   *
-   * @var array
-   */
-  protected $pathRoots;
-
-  /**
-   * The state key value store.
-   *
-   * @var \Drupal\Core\State\StateInterface
-   */
-  protected $state;
-
-  /**
-   * Constructs a new PathRootsSubscriber instance.
-   *
-   * @param \Drupal\Core\State\StateInterface $state
-   *   The state key value store.
-   */
-  public function __construct(StateInterface $state) {
-    $this->state = $state;
-  }
-
-  /**
-   * Collects all path roots.
-   *
-   * @param \Drupal\Core\Routing\RouteBuildEvent $event
-   *   The route build event.
-   */
-  public function onRouteAlter(RouteBuildEvent $event) {
-    $collection = $event->getRouteCollection();
-    foreach ($collection->all() as $route) {
-      $bits = explode('/', ltrim($route->getPath(), '/'));
-      $this->pathRoots[$bits[0]] = $bits[0];
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function onRouteFinished() {
-    $this->state->set('router.path_roots', array_keys($this->pathRoots));
-    unset($this->pathRoots);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function getSubscribedEvents() {
-    $events = array();
-    // Try to set a low priority to ensure that all routes are already added.
-    $events[RoutingEvents::ALTER][] = array('onRouteAlter', -1024);
-    $events[RoutingEvents::FINISHED][] = array('onRouteFinished');
-    return $events;
-  }
-
-}
diff --git a/core/lib/Drupal/Core/EventSubscriber/RouteMethodSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/RouteMethodSubscriber.php
deleted file mode 100644
index f422b2a..0000000
--- a/core/lib/Drupal/Core/EventSubscriber/RouteMethodSubscriber.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\EventSubscriber\RouteMethodSubscriber.
- */
-
-namespace Drupal\Core\EventSubscriber;
-
-use Drupal\Core\Routing\RouteBuildEvent;
-use Drupal\Core\Routing\RoutingEvents;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-
-/**
- * Provides a default value for the HTTP method restriction on routes.
- *
- * Most routes will only deal with GET and POST requests, so we restrict them to
- * those two if nothing else is specified. This is necessary to give other
- * routes a chance during the route matching process when they are listening
- * for example to DELETE requests on the same path. A typical use case are REST
- * web service routes that use the full spectrum of HTTP methods.
- */
-class RouteMethodSubscriber implements EventSubscriberInterface {
-
-  /**
-   * Sets a default value of GET|POST for the _method route property.
-   *
-   * @param \Drupal\Core\Routing\RouteBuildEvent $event
-   *   The event containing the build routes.
-   */
-  public function onRouteBuilding(RouteBuildEvent $event) {
-    foreach ($event->getRouteCollection() as $route) {
-      $methods = $route->getMethods();
-      if (empty($methods)) {
-        $route->setMethods(array('GET', 'POST'));
-      }
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  static function getSubscribedEvents() {
-    // Set a higher priority to ensure that routes get the default HTTP methods
-    // as early as possible.
-    $events[RoutingEvents::ALTER][] = array('onRouteBuilding', 5000);
-    return $events;
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Routing/RouteBuilder.php b/core/lib/Drupal/Core/Routing/RouteBuilder.php
index 5bea0a5..12eb5b7 100644
--- a/core/lib/Drupal/Core/Routing/RouteBuilder.php
+++ b/core/lib/Drupal/Core/Routing/RouteBuilder.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Routing;
 
 use Drupal\Component\Discovery\YamlDiscovery;
+use Drupal\Core\Access\AccessManagerInterface;
 use Drupal\Core\Controller\ControllerResolverInterface;
 use Drupal\Core\State\StateInterface;
 use Symfony\Component\EventDispatcher\Event;
@@ -92,7 +93,7 @@ class RouteBuilder implements RouteBuilderInterface {
    *   The module handler.
    * @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
    *   The controller resolver.
-   * @param \Drupal\Core\KeyValueStore\StateInterface $state
+   * @param \Drupal\Core\State\StateInterface $state
    *   The state.
    */
   public function __construct(MatcherDumperInterface $dumper, LockBackendInterface $lock, EventDispatcherInterface $dispatcher, ModuleHandlerInterface $module_handler, ControllerResolverInterface $controller_resolver, StateInterface $state = NULL) {
@@ -105,6 +106,68 @@ public function __construct(MatcherDumperInterface $dumper, LockBackendInterface
   }
 
   /**
+   * @param $route
+   * @return bool
+   */
+  public static function isAdminRoute(Route $route) {
+    return strpos($route->getPath(), '/admin/') === 0 || $route->getPath() === '/admin' || $route->getOption('_admin_route');
+  }
+
+  /**
+   * Provides a default value for the HTTP method restriction on routes.
+   *
+   * Most routes will only deal with GET and POST requests, so we restrict them to
+   * those two if nothing else is specified. This is necessary to give other
+   * routes a chance during the route matching process when they are listening
+   * for example to DELETE requests on the same path. A typical use case are REST
+   * web service routes that use the full spectrum of HTTP methods.
+   *
+   * @param RouteCollection $collection
+   */
+  public static function setDefaultMethods(RouteCollection $collection) {
+    foreach ($collection->all() as $route) {
+      if (!$route->getMethods()) {
+        $route->setMethods(array('GET', 'POST'));
+      }
+    }
+  }
+
+  /**
+   * Apply access checks to routes.
+   *
+   * @param \Symfony\Component\Routing\RouteCollection $collection
+   *   A collection of routes to apply checks to.
+   * @param \Drupal\Core\Access\AccessManagerInterface $access_manager
+   *   The access check manager that will be responsible for applying
+   *   AccessCheckers against routes.
+   */
+  public static function addChecks(RouteCollection $collection, AccessManagerInterface $access_manager = NULL) {
+    if (!$access_manager) {
+      $access_manager = \Drupal::accessManager();
+    }
+    $access_manager->setChecks($collection);
+  }
+
+  /**
+   * Collects all path roots.
+   *
+   * @param \Symfony\Component\Routing\RouteCollection $collection
+   *   A collection of routes to collect path roots from.
+   * @param \Drupal\Core\State\StateInterface $state
+   */
+  public static function collectPathRoots(RouteCollection $collection, StateInterface $state = NULL) {
+    if (!$state) {
+      $state = \Drupal::state();
+    }
+    $path_roots = [];
+    foreach ($collection->all() as $route) {
+      $path_root = explode('/', ltrim($route->getPath(), '/'))[0];
+      $path_roots[$path_root] = $path_root;
+    }
+    $state->set('router.path_roots', array_keys($path_roots));
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function rebuild() {
@@ -172,6 +235,10 @@ public function rebuild() {
     // make it clear.
     $this->dispatcher->dispatch(RoutingEvents::ALTER, new RouteBuildEvent($collection));
 
+    static::setDefaultMethods($collection);
+    static::addChecks($collection);
+    static::collectPathRoots($collection, $this->state);
+
     $this->dumper->addRoutes($collection);
     $this->dumper->dump();
 
diff --git a/core/lib/Drupal/Core/Routing/RoutePreloader.php b/core/lib/Drupal/Core/Routing/RoutePreloader.php
index 7952d17..e52d1c0 100644
--- a/core/lib/Drupal/Core/Routing/RoutePreloader.php
+++ b/core/lib/Drupal/Core/Routing/RoutePreloader.php
@@ -98,11 +98,11 @@ protected function loadNonAdminRoutes() {
   public function onAlterRoutes(RouteBuildEvent $event) {
     $collection = $event->getRouteCollection();
     foreach ($collection->all() as $name => $route) {
-      if (strpos($route->getPath(), '/admin/') !== 0 && $route->getPath() != '/admin') {
-        $this->nonAdminRoutesOnRebuild[] = $name;
+      if (!RouteBuilder::isAdminRoute($route)) {
+        $this->nonAdminRoutesOnRebuild[$name] = $name;
       }
     }
-    $this->nonAdminRoutesOnRebuild = array_unique($this->nonAdminRoutesOnRebuild);
+    $this->nonAdminRoutesOnRebuild = array_keys($this->nonAdminRoutesOnRebuild);
   }
 
   /**
diff --git a/core/modules/system/src/EventSubscriber/AdminRouteSubscriber.php b/core/modules/system/src/EventSubscriber/AdminRouteSubscriber.php
index eef05e1..f57c4c7 100644
--- a/core/modules/system/src/EventSubscriber/AdminRouteSubscriber.php
+++ b/core/modules/system/src/EventSubscriber/AdminRouteSubscriber.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\system\EventSubscriber;
 
+use Drupal\Core\Routing\RouteBuilder;
 use Drupal\Core\Routing\RouteSubscriberBase;
 use Drupal\Core\Routing\RoutingEvents;
 use Symfony\Component\Routing\RouteCollection;
@@ -21,7 +22,7 @@ class AdminRouteSubscriber extends RouteSubscriberBase {
    */
   protected function alterRoutes(RouteCollection $collection) {
     foreach ($collection->all() as $route) {
-      if (strpos($route->getPath(), '/admin') === 0 && !$route->hasOption('_admin_route')) {
+      if (RouteBuilder::isAdminRoute($route)) {
         $route->setOption('_admin_route', TRUE);
       }
     }
diff --git a/core/tests/Drupal/Tests/Core/EventSubscriber/PathRootsSubscriberTest.php b/core/tests/Drupal/Tests/Core/EventSubscriber/PathRootsSubscriberTest.php
deleted file mode 100644
index 02acb66..0000000
--- a/core/tests/Drupal/Tests/Core/EventSubscriber/PathRootsSubscriberTest.php
+++ /dev/null
@@ -1,74 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Tests\Core\EventSubscriber\PathRootsSubscriberTest.
- */
-
-namespace Drupal\Tests\Core\EventSubscriber;
-
-use Drupal\Core\EventSubscriber\PathRootsSubscriber;
-use Drupal\Core\Routing\RouteBuildEvent;
-use Drupal\Tests\UnitTestCase;
-use Symfony\Component\Routing\Route;
-use Symfony\Component\Routing\RouteCollection;
-
-/**
- * @coversDefaultClass \Drupal\Core\EventSubscriber\PathRootsSubscriber
- * @group EventSubscriber
- */
-class PathRootsSubscriberTest extends UnitTestCase {
-
-  /**
-   * The mocked state.
-   *
-   * @var \Drupal\Core\State\StateInterface|\PHPUnit_Framework_MockObject_MockObject
-   */
-  protected $state;
-
-  /**
-   * The tested path root subscriber.
-   *
-   * @var \Drupal\Core\EventSubscriber\PathRootsSubscriber
-   */
-  protected $pathRootsSubscriber;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    $this->state = $this->getMock('Drupal\Core\State\StateInterface');
-    $this->pathRootsSubscriber = new PathRootsSubscriber($this->state);
-  }
-
-  /**
-   * Tests altering and finished event.
-   *
-   * @covers ::onRouteAlter()
-   * @covers ::onRouteFinished()
-   */
-  public function testSubscribing() {
-    $route_collection = new RouteCollection();
-    $route_collection->add('test_route1', new Route('/test/bar'));
-    $route_collection->add('test_route2', new Route('/test/baz'));
-    $route_collection->add('test_route3', new Route('/test2/bar/baz'));
-
-    $event = new RouteBuildEvent($route_collection, 'provider');
-    $this->pathRootsSubscriber->onRouteAlter($event);
-
-    $route_collection = new RouteCollection();
-    $route_collection->add('test_route4', new Route('/test1/bar'));
-    $route_collection->add('test_route5', new Route('/test2/baz'));
-    $route_collection->add('test_route6', new Route('/test2/bar/baz'));
-
-    $event = new RouteBuildEvent($route_collection, 'provider');
-    $this->pathRootsSubscriber->onRouteAlter($event);
-
-    $this->state->expects($this->once())
-      ->method('set')
-      ->with('router.path_roots', array('test', 'test2', 'test1'));
-
-    $this->pathRootsSubscriber->onRouteFinished();
-  }
-
-}
diff --git a/core/tests/Drupal/Tests/Core/Routing/RouteBuilderTest.php b/core/tests/Drupal/Tests/Core/Routing/RouteBuilderTest.php
index aff98962..022fd29 100644
--- a/core/tests/Drupal/Tests/Core/Routing/RouteBuilderTest.php
+++ b/core/tests/Drupal/Tests/Core/Routing/RouteBuilderTest.php
@@ -91,6 +91,9 @@ protected function setUp() {
 
     $this->routeBuilder = new TestRouteBuilder($this->dumper, $this->lock, $this->dispatcher, $this->moduleHandler, $this->controllerResolver, $this->state);
     $this->routeBuilder->setYamlDiscovery($this->yamlDiscovery);
+    $container = new ContainerBuilder();
+    $container->set('access_manager', $this->getMock('Drupal\Core\Access\AccessManagerInterface'));
+    \Drupal::setContainer($container);
   }
 
   /**
@@ -168,16 +171,19 @@ public function testRebuildWithStaticModuleRoutes() {
     $this->dispatcher->expects($this->at(1))
       ->method('dispatch')
       ->with(RoutingEvents::ALTER, $route_build_event);
+    $expected_collection = clone $route_collection;
+    RouteBuilder::setDefaultMethods($expected_collection);
 
     // Ensure that the routes are set to the dumper and dumped.
     $this->dumper->expects($this->at(0))
       ->method('addRoutes')
-      ->with($route_collection);
+      ->with($expected_collection);
     $this->dumper->expects($this->at(1))
       ->method('dump')
       ->with();
 
     $this->assertTrue($this->routeBuilder->rebuild());
+    RouteBuilder::setDefaultMethods($route_collection);
   }
 
   /**
@@ -233,15 +239,18 @@ public function testRebuildWithProviderBasedRoutes() {
     $this->dispatcher->expects($this->at(1))
       ->method('dispatch')
       ->with(RoutingEvents::ALTER, $route_build_event);
+    $expected_collection = clone $route_collection_filled;
+    RouteBuilder::setDefaultMethods($expected_collection);
 
     // Ensure that the routes are set to the dumper and dumped.
     $this->dumper->expects($this->at(0))
       ->method('addRoutes')
-      ->with($route_collection_filled);
+      ->with($expected_collection);
     $this->dumper->expects($this->at(1))
       ->method('dump');
 
     $this->assertTrue($this->routeBuilder->rebuild());
+    RouteBuilder::setDefaultMethods($route_collection_filled);
   }
 
   /**
@@ -257,9 +266,8 @@ public function testRebuildIfNecessary() {
                ->method('release')
                ->with('router_rebuild');
 
-    $this->state->expects($this->once())
-                ->method('set')
-                ->with('router_rebuild_needed');
+    $this->state->expects($this->exactly(2))
+                ->method('set');
 
     $this->state->expects($this->once())
                 ->method('delete')
