diff --git a/core/includes/menu.inc b/core/includes/menu.inc
index 581a6ce436abe36d2cbfb777a54e93dd45ad1697..400e2abcd4a32695e3bf7ecfb4716610c0ba724e 100644
--- a/core/includes/menu.inc
+++ b/core/includes/menu.inc
@@ -480,56 +480,6 @@ function menu_get_item($path = NULL, $router_item = NULL) {
   return $router_items[$path];
 }
 
-/**
- * Execute the page callback associated with the current path.
- *
- * @param $path
- *   The drupal path whose handler is to be be executed. If set to NULL, then
- *   the current path is used.
- * @param $deliver
- *   (optional) A boolean to indicate whether the content should be sent to the
- *   browser using the appropriate delivery callback (TRUE) or whether to return
- *   the result to the caller (FALSE).
- */
-function menu_execute_active_handler($path = NULL, $deliver = TRUE) {
-  // Check if site is offline.
-  $page_callback_result = _menu_site_is_offline() ? MENU_SITE_OFFLINE : MENU_SITE_ONLINE;
-
-  // Allow other modules to change the site status but not the path because that
-  // would not change the global variable. hook_url_inbound_alter() can be used
-  // to change the path. Code later will not use the $read_only_path variable.
-  $read_only_path = !empty($path) ? $path : current_path();
-  drupal_alter('menu_site_status', $page_callback_result, $read_only_path);
-
-  // Only continue if the site status is not set.
-  if ($page_callback_result == MENU_SITE_ONLINE) {
-    if ($router_item = menu_get_item($path)) {
-      if ($router_item['access']) {
-        if ($router_item['include_file']) {
-          require_once DRUPAL_ROOT . '/' . $router_item['include_file'];
-        }
-        $page_callback_result = call_user_func_array($router_item['page_callback'], $router_item['page_arguments']);
-      }
-      else {
-        $page_callback_result = MENU_ACCESS_DENIED;
-      }
-    }
-    else {
-      $page_callback_result = MENU_NOT_FOUND;
-    }
-  }
-
-  // Deliver the result of the page callback to the browser, or if requested,
-  // return it raw, so calling code can do more processing.
-  if ($deliver) {
-    $default_delivery_callback = (isset($router_item) && $router_item) ? $router_item['delivery_callback'] : NULL;
-    drupal_deliver_page($page_callback_result, $default_delivery_callback);
-  }
-  else {
-    return $page_callback_result;
-  }
-}
-
 /**
  * Loads objects into the map as defined in the $item['load_functions'].
  *
@@ -2295,8 +2245,8 @@ function menu_get_active_menu_names() {
  * Set the active path, which determines which page is loaded.
  *
  * Note that this may not have the desired effect unless invoked very early
- * in the page load, such as during hook_boot, or unless you call
- * menu_execute_active_handler() to generate your page output.
+ * in the page load, such as during hook_boot, or unless you do a subrequest
+ * to generate your page output.
  *
  * @param $path
  *   A Drupal path - not a path alias.
@@ -2660,7 +2610,7 @@ function menu_router_rebuild() {
   if (!lock_acquire(__FUNCTION__)) {
     // Wait for another request that is already doing this work.
     // We choose to block here since otherwise the router item may not
-    // be available in menu_execute_active_handler() resulting in a 404.
+    // be available during routing resulting in a 404.
     lock_wait(__FUNCTION__);
     return FALSE;
   }
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index a6230f2336fe8cbbe97fa42c6c218df2e8b00096..9f47d37b2ab979993f819c98b158cc438e601725 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -10,7 +10,9 @@
  */
 
 use Drupal\node\Node;
+use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
 
 /**
  * Comment is awaiting approval.
@@ -501,11 +503,13 @@ function comment_permalink($cid) {
     // Find the current display page for this comment.
     $page = comment_get_display_page($comment->cid, $node->type);
 
-    // Return the node view, this will show the correct comment in context.
-    // @todo Refactor to use Symfony's Request object.
-    _current_path('node/' . $node->nid);
+    // @todo: Cleaner sub request handling.
+    $subrequest = Request::create('/node/' . $node->nid, 'GET', request()->query->all(), request()->cookies->all(), array(), request()->server->all());
+    $subrequest->query->set('page', $page);
+    // @todo: Convert the pager to use the request object.
     $_GET['page'] = $page;
-    return menu_execute_active_handler('node/' . $node->nid, FALSE);
+    request($subrequest);
+    return drupal_container()->get('httpkernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST);
   }
   throw new NotFoundHttpException();
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/RebuildTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/RebuildTest.php
index 7f5b22613a851a9582378fb299ecebda006cc2d2..b6e0ec29f9fde69117dd7b689dbf1f4f3f78d5fa 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Menu/RebuildTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Menu/RebuildTest.php
@@ -36,10 +36,10 @@ function testMenuRebuildByVariable() {
     $admin_exists = db_query('SELECT path from {menu_router} WHERE path = :path', array(':path' => 'admin'))->fetchField();
     $this->assertFalse($admin_exists, t("The path 'admin/' has been deleted and doesn't exist in the database."));
 
-    // Now we enable the rebuild variable and trigger menu_execute_active_handler()
-    // to rebuild the menu item. Now 'admin' should exist.
+    // Now we enable the rebuild variable and send a request to rebuild the menu
+    // item. Now 'admin' should exist.
     variable_set('menu_rebuild_needed', TRUE);
-    // menu_execute_active_handler() should trigger the rebuild.
+    // The request should trigger the rebuild.
     $this->drupalGet('<front>');
     $admin_exists = db_query('SELECT path from {menu_router} WHERE path = :path', array(':path' => 'admin'))->fetchField();
     $this->assertEqual($admin_exists, 'admin', t("The menu has been rebuilt, the path 'admin' now exists again."));
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index 12428fe3a0cdde2c3a4884aace5dab6f55f53501..2223dec385cc61415e1431037013095d411f0ba7 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -4106,9 +4106,8 @@ function hook_countries_alter(&$countries) {
  * Control site status before menu dispatching.
  *
  * The hook is called after checking whether the site is offline but before
- * the current router item is retrieved and executed by
- * menu_execute_active_handler(). If the site is in offline mode,
- * $menu_site_status is set to MENU_SITE_OFFLINE.
+ * the current router item is retrieved and executed. If the site is in offline
+ * mode, $menu_site_status is set to MENU_SITE_OFFLINE.
  *
  * @param $menu_site_status
  *   Supported values are MENU_SITE_OFFLINE, MENU_ACCESS_DENIED,
diff --git a/core/modules/system/tests/http.php b/core/modules/system/tests/http.php
index 2481d16b51ee5717969450c6e1232e4973f7488c..93646850e9656eaf5c9d655699836b679208daca 100644
--- a/core/modules/system/tests/http.php
+++ b/core/modules/system/tests/http.php
@@ -5,6 +5,8 @@
  * Fake an HTTP request, for use during testing.
  */
 
+use Symfony\Component\HttpFoundation\Request;
+
 // Set a global variable to indicate a mock HTTP request.
 $is_http_mock = !empty($_SERVER['HTTPS']);
 
@@ -28,5 +30,12 @@
   exit;
 }
 
-drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
-menu_execute_active_handler();
+// Continue with normal request handling.
+$request = Request::createFromGlobals();
+request($request);
+
+drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE);
+
+$kernel = drupal_container()->get('httpkernel');
+$response = $kernel->handle($request)->prepare($request)->send();
+$kernel->terminate($request, $response);
diff --git a/core/modules/system/tests/https.php b/core/modules/system/tests/https.php
index 3d07f0c8291fb118f5dc5aef3127fc29203352e1..11b7e13022cb7f33e2cf59f25ee1f59ae53020fb 100644
--- a/core/modules/system/tests/https.php
+++ b/core/modules/system/tests/https.php
@@ -5,6 +5,8 @@
  * Fake an https request, for use during testing.
  */
 
+use Symfony\Component\HttpFoundation\Request;
+
 // Set a global variable to indicate a mock HTTPS request.
 $is_https_mock = empty($_SERVER['HTTPS']);
 
@@ -27,5 +29,12 @@
   exit;
 }
 
-drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
-menu_execute_active_handler();
+// Continue with normal request handling.
+$request = Request::createFromGlobals();
+request($request);
+
+drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE);
+
+$kernel = drupal_container()->get('httpkernel');
+$response = $kernel->handle($request)->prepare($request)->send();
+$kernel->terminate($request, $response);
diff --git a/core/modules/user/user.pages.inc b/core/modules/user/user.pages.inc
index 6cdfd25c3672e78e2930436a0027800ccdb2ca99..b568f66be7c69bbb2f963d99791761ca025a1b1e 100644
--- a/core/modules/user/user.pages.inc
+++ b/core/modules/user/user.pages.inc
@@ -6,7 +6,9 @@
  */
 
 use Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
 
 /**
  * Menu callback; Retrieve a JSON object containing autocomplete suggestions for existing users.
@@ -495,8 +497,10 @@ function user_cancel_confirm($account, $timestamp = 0, $hashed_pass = '') {
 function user_page() {
   global $user;
   if ($user->uid) {
-    menu_set_active_item('user/' . $user->uid);
-    return menu_execute_active_handler(NULL, FALSE);
+    // @todo: Cleaner sub request handling.
+    $subrequest = Request::create('/user/' . $user->uid, 'GET', request()->query->all(), request()->cookies->all(), array(), request()->server->all());
+    request($subrequest);
+    return drupal_container()->get('httpkernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST);
   }
   else {
     return drupal_get_form('user_login');