diff --git a/core/core.services.yml b/core/core.services.yml
index 1449b3b..f325c8b 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -108,6 +108,9 @@ services:
   config.typed:
     class: Drupal\Core\Config\TypedConfigManager
     arguments: ['@config.storage', '@config.storage.schema', '@cache.config']
+  cron:
+    class: Drupal\Core\Cron
+    arguments: ['@module_handler', '@lock', '@queue', '@state']
   database:
     class: Drupal\Core\Database\Connection
     factory_class: Drupal\Core\Database\Database
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 0099008..6c5a476 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -3171,96 +3171,6 @@ function drupal_page_set_cache(Response $response, Request $request) {
 }
 
 /**
- * Executes a cron run when called.
- *
- * Do not call this function from a test. Use $this->cronRun() instead.
- *
- * @return
- *   TRUE if cron ran successfully.
- */
-function drupal_cron_run() {
-  // Allow execution to continue even if the request gets canceled.
-  @ignore_user_abort(TRUE);
-
-  // Prevent session information from being saved while cron is running.
-  $original_session_saving = drupal_save_session();
-  drupal_save_session(FALSE);
-
-  // Force the current user to anonymous to ensure consistent permissions on
-  // cron runs.
-  $original_user = $GLOBALS['user'];
-  $GLOBALS['user'] = drupal_anonymous_user();
-
-  // Try to allocate enough time to run all the hook_cron implementations.
-  drupal_set_time_limit(240);
-
-  $return = FALSE;
-  // Grab the defined cron queues.
-  $queues = \Drupal::moduleHandler()->invokeAll('queue_info');
-  drupal_alter('queue_info', $queues);
-
-  // Try to acquire cron lock.
-  if (!lock()->acquire('cron', 240.0)) {
-    // Cron is still running normally.
-    watchdog('cron', 'Attempting to re-run cron while it is already running.', array(), WATCHDOG_WARNING);
-  }
-  else {
-    // Make sure every queue exists. There is no harm in trying to recreate an
-    // existing queue.
-    foreach ($queues as $queue_name => $info) {
-      if (isset($info['cron'])) {
-        \Drupal::queue($queue_name)->createQueue();
-      }
-    }
-
-    // Iterate through the modules calling their cron handlers (if any):
-    foreach (\Drupal::moduleHandler()->getImplementations('cron') as $module) {
-      // Do not let an exception thrown by one module disturb another.
-      try {
-        module_invoke($module, 'cron');
-      }
-      catch (Exception $e) {
-        watchdog_exception('cron', $e);
-      }
-    }
-
-    // Record cron time.
-    \Drupal::state()->set('system.cron_last', REQUEST_TIME);
-    watchdog('cron', 'Cron run completed.', array(), WATCHDOG_NOTICE);
-
-    // Release cron lock.
-    lock()->release('cron');
-
-    // Return TRUE so other functions can check if it did run successfully
-    $return = TRUE;
-  }
-
-  foreach ($queues as $queue_name => $info) {
-    if (isset($info['cron'])) {
-      $callback = $info['worker callback'];
-      $end = time() + (isset($info['cron']['time']) ? $info['cron']['time'] : 15);
-      $queue = \Drupal::queue($queue_name);
-      while (time() < $end && ($item = $queue->claimItem())) {
-        try {
-          call_user_func_array($callback, array($item->data));
-          $queue->deleteItem($item);
-        }
-        catch (Exception $e) {
-          // In case of exception log it and leave the item in the queue
-          // to be processed again later.
-          watchdog_exception('cron', $e);
-        }
-      }
-    }
-  }
-  // Restore the user.
-  $GLOBALS['user'] = $original_user;
-  drupal_save_session($original_session_saving);
-
-  return $return;
-}
-
-/**
  * This function is kept only for backward compatibility.
  *
  * @see \Drupal\Core\SystemListing::scan().
diff --git a/core/lib/Drupal/Core/Cron.php b/core/lib/Drupal/Core/Cron.php
new file mode 100644
index 0000000..9ec09be
--- /dev/null
+++ b/core/lib/Drupal/Core/Cron.php
@@ -0,0 +1,136 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Cron.
+ */
+
+namespace Drupal\Core;
+
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\KeyValueStore\StateInterface;
+use Drupal\Core\Lock\LockBackendInterface;
+use Drupal\Core\Queue\QueueFactory;
+
+/**
+ * @todo
+ */
+class Cron implements CronInterface {
+
+  /**
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
+   * @var \Drupal\Core\Lock\LockBackendInterface
+   */
+  protected $lock;
+
+  /**
+   * @var \Drupal\Core\Queue\QueueFactory
+   */
+  protected $queueFactory;
+
+  /**
+   * @var \Drupal\Core\KeyValueStore\StateInterface
+   */
+  protected $state;
+
+  /**
+   *
+   */
+  public function __construct(ModuleHandlerInterface $module_handler, LockBackendInterface $lock, QueueFactory $queue_factory, StateInterface $state) {
+    $this->moduleHandler = $module_handler;
+    $this->lock = $lock;
+    $this->queueFactory = $queue_factory;
+    $this->state = $state;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function run() {
+    // Allow execution to continue even if the request gets cancelled.
+    @ignore_user_abort(TRUE);
+
+    // Prevent session information from being saved while cron is running.
+    $original_session_saving = drupal_save_session();
+    drupal_save_session(FALSE);
+
+    // Force the current user to anonymous to ensure consistent permissions on
+    // cron runs.
+    $original_user = $GLOBALS['user'];
+    $GLOBALS['user'] = drupal_anonymous_user();
+
+    // Try to allocate enough time to run all the hook_cron implementations.
+    drupal_set_time_limit(240);
+
+    $return = FALSE;
+    // Grab the defined cron queues.
+    $queues = $this->moduleHandler->invokeAll('queue_info');
+    $this->moduleHandler->alter('queue_info', $queues);
+
+    // Try to acquire cron lock.
+    if (!$this->lock->acquire('cron', 240.0)) {
+      // Cron is still running normally.
+      watchdog('cron', 'Attempting to re-run cron while it is already running.', array(), WATCHDOG_WARNING);
+    }
+    else {
+      // Make sure every queue exists. There is no harm in trying to recreate an
+      // existing queue.
+      foreach ($queues as $queue_name => $info) {
+        if (isset($info['cron'])) {
+          $this->queueFactory->get($queue_name)->createQueue();
+        }
+      }
+
+      // Iterate through the modules calling their cron handlers (if any):
+      foreach ($this->moduleHandler->getImplementations('cron') as $module) {
+        // Do not let an exception thrown by one module disturb another.
+        try {
+          $this->moduleHandler->invoke($module, 'cron');
+        }
+        catch (\Exception $e) {
+          watchdog_exception('cron', $e);
+        }
+      }
+
+      // Record cron time.
+      $this->state->set('system.cron_last', REQUEST_TIME);
+      watchdog('cron', 'Cron run completed.', array(), WATCHDOG_NOTICE);
+
+      // Release cron lock.
+      $this->lock->release('cron');
+
+      // Return TRUE so other functions can check if it did run successfully
+      $return = TRUE;
+    }
+
+    foreach ($queues as $queue_name => $info) {
+      if (isset($info['cron'])) {
+        $callback = $info['worker callback'];
+        $end = time() + (isset($info['cron']['time']) ? $info['cron']['time'] : 15);
+        $queue = $this->queueFactory->get($queue_name);
+        while (time() < $end && ($item = $queue->claimItem())) {
+          try {
+            call_user_func_array($callback, array($item->data));
+            $queue->deleteItem($item);
+          }
+          catch (\Exception $e) {
+            // In case of exception log it and leave the item in the queue
+            // to be processed again later.
+            watchdog_exception('cron', $e);
+          }
+        }
+      }
+    }
+
+    // Restore the user.
+    $GLOBALS['user'] = $original_user;
+    drupal_save_session($original_session_saving);
+
+    return $return;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/CronInterface.php b/core/lib/Drupal/Core/CronInterface.php
new file mode 100644
index 0000000..be3ce67
--- /dev/null
+++ b/core/lib/Drupal/Core/CronInterface.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * Contains \Drupal\Core\CronInterface.
+ */
+
+namespace Drupal\Core;
+
+/**
+ * An interface for running cron tasks.
+ */
+interface CronInterface {
+
+  /**
+   * Executes a cron run.
+   *
+   * Do not call this function from a test. Use $this->cronRun() instead.
+   *
+   * @return bool
+   *   TRUE upon success, FALSE otherwise.
+   */
+  public function run();
+
+}
diff --git a/core/modules/system/lib/Drupal/system/CronController.php b/core/modules/system/lib/Drupal/system/CronController.php
index 4c9161f..d8c3781 100644
--- a/core/modules/system/lib/Drupal/system/CronController.php
+++ b/core/modules/system/lib/Drupal/system/CronController.php
@@ -7,13 +7,14 @@
 
 namespace Drupal\system;
 
+use Drupal\Core\Controller\ControllerBase;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 
 /**
  * Controller for Cron handling.
  */
-class CronController {
+class CronController extends ControllerBase {
 
   /**
    * Run Cron once.
@@ -22,8 +23,8 @@ class CronController {
    *   A Symfony response object.
    */
   public function run() {
-    // @todo Make this an injected object.
-    drupal_cron_run();
+    // @todo inject this as a service?
+    \Drupal::service('cron')->run();
 
     // HTTP 204 is "No content", meaning "I did what you asked and we're done."
     return new Response('', 204);
@@ -36,13 +37,15 @@ public function run() {
    *   A Symfony direct response object.
    */
   public function runManually() {
-    if (drupal_cron_run()) {
-      drupal_set_message(t('Cron ran successfully.'));
+    // @todo inject this as a service?
+    if (\Drupal::service('cron')->run()) {
+      drupal_set_message($this->t('Cron ran successfully.'));
     }
     else {
-      drupal_set_message(t('Cron run failed.'), 'error');
+      drupal_set_message($this->t('Cron run failed.'), 'error');
     }
-    return new RedirectResponse(url('admin/reports/status', array('absolute' => TRUE)));
+
+    return $this->redirect('system.status');
   }
 
 }
