diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php
index 5585650..f2a5003 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentLinksTest.php
@@ -21,6 +21,8 @@ class CommentLinksTest extends CommentTestBase {
    */
   public static $modules = array('views');
 
+  protected $access;
+
   public static function getInfo() {
     return array(
       'name' => 'Comment links',
@@ -29,6 +31,12 @@ public static function getInfo() {
     );
   }
 
+  function setUp() {
+    parent::setUp();
+
+    $this->access = \Drupal::service('user.access');
+  }
+
   /**
    * Tests comment links.
    *
@@ -262,7 +270,7 @@ function assertCommentLinks(array $info) {
         // authenticated users are allowed to post comments.
         // @see theme_comment_post_forbidden()
         if (!$this->loggedInUser) {
-          if (user_access('post comments', $this->web_user)) {
+          if ($this->access->check('post comments', $this->web_user)) {
             // The note depends on whether users are actually able to register.
             if ($info['user_register'] != USER_REGISTER_ADMINISTRATORS_ONLY) {
               $this->assertText('Log in or register to post comments');
diff --git a/core/modules/user/lib/Drupal/user/RoleStorageController.php b/core/modules/user/lib/Drupal/user/RoleStorageController.php
index 680b412..1d3bf51 100644
--- a/core/modules/user/lib/Drupal/user/RoleStorageController.php
+++ b/core/modules/user/lib/Drupal/user/RoleStorageController.php
@@ -36,8 +36,8 @@ public function resetCache(array $ids = NULL) {
     parent::resetCache($ids);
 
     // Clear the user access cache.
-    drupal_static_reset('user_access');
-    drupal_static_reset('user_role_permissions');
+    \Drupal::service('user.access')->resetCache();
+    \Drupal::service('user.access')->resetRoleCache();
   }
 
   /**
diff --git a/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php
index 2455b10..c55552c 100644
--- a/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php
+++ b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php
@@ -10,6 +10,7 @@
 use Drupal\simpletest\WebTestBase;
 
 class UserPermissionsTest extends WebTestBase {
+  protected $access;
   protected $admin_user;
   protected $rid;
 
@@ -23,7 +24,7 @@ public static function getInfo() {
 
   function setUp() {
     parent::setUp();
-
+    $this->access = \Drupal::service('user.access');
     $this->admin_user = $this->drupalCreateUser(array('administer permissions', 'access user profiles', 'administer site configuration', 'administer modules', 'administer users'));
 
     // Find the new role ID.
@@ -46,9 +47,9 @@ function testUserPermissionChanges() {
     $edit[$rid . '[administer nodes]'] = TRUE;
     $this->drupalPost('admin/people/permissions', $edit, t('Save permissions'));
     $this->assertText(t('The changes have been saved.'), 'Successful save message displayed.');
-    drupal_static_reset('user_access');
-    drupal_static_reset('user_role_permissions');
-    $this->assertTrue(user_access('administer nodes', $account), 'User now has "administer nodes" permission.');
+    $this->access->resetCache();
+    $this->access->resetRoleCache();
+    $this->assertTrue($this->access->check('administer nodes', $account), 'User now has "administer nodes" permission.');
 
     // Remove a permission.
     $this->assertTrue(user_access('access user profiles', $account), 'User has "access user profiles" permission.');
@@ -56,9 +57,9 @@ function testUserPermissionChanges() {
     $edit[$rid . '[access user profiles]'] = FALSE;
     $this->drupalPost('admin/people/permissions', $edit, t('Save permissions'));
     $this->assertText(t('The changes have been saved.'), 'Successful save message displayed.');
-    drupal_static_reset('user_access');
-    drupal_static_reset('user_role_permissions');
-    $this->assertFalse(user_access('access user profiles', $account), 'User no longer has "access user profiles" permission.');
+    $this->access->resetCache();
+    $this->access->resetRoleCache();
+    $this->assertFalse($this->access->check('access user profiles', $account), 'User no longer has "access user profiles" permission.');
   }
 
   /**
@@ -80,7 +81,7 @@ function testAdministratorRole() {
     // Aggregator depends on file module, enable that as well.
     $edit['modules[Core][file][enable]'] = TRUE;
     $this->drupalPost('admin/modules', $edit, t('Save configuration'));
-    $this->assertTrue(user_access('administer news feeds', $this->admin_user), 'The permission was automatically assigned to the administrator role');
+    $this->assertTrue($this->access->check('administer news feeds', $this->admin_user), 'The permission was automatically assigned to the administrator role');
   }
 
   /**
@@ -91,9 +92,9 @@ function testUserRoleChangePermissions() {
     $account = $this->admin_user;
 
     // Verify current permissions.
-    $this->assertFalse(user_access('administer nodes', $account), 'User does not have "administer nodes" permission.');
-    $this->assertTrue(user_access('access user profiles', $account), 'User has "access user profiles" permission.');
-    $this->assertTrue(user_access('administer site configuration', $account), 'User has "administer site configuration" permission.');
+    $this->assertFalse($this->access->check('administer nodes', $account), 'User does not have "administer nodes" permission.');
+    $this->assertTrue($this->access->check('access user profiles', $account), 'User has "access user profiles" permission.');
+    $this->assertTrue($this->access->check('administer site configuration', $account), 'User has "administer site configuration" permission.');
 
     // Change permissions.
     $permissions = array(
@@ -103,8 +104,8 @@ function testUserRoleChangePermissions() {
     user_role_change_permissions($rid, $permissions);
 
     // Verify proper permission changes.
-    $this->assertTrue(user_access('administer nodes', $account), 'User now has "administer nodes" permission.');
-    $this->assertFalse(user_access('access user profiles', $account), 'User no longer has "access user profiles" permission.');
-    $this->assertTrue(user_access('administer site configuration', $account), 'User still has "administer site configuration" permission.');
+    $this->assertTrue($this->access->check('administer nodes', $account), 'User now has "administer nodes" permission.');
+    $this->assertFalse($this->access->check('access user profiles', $account), 'User no longer has "access user profiles" permission.');
+    $this->assertTrue($this->access->check('administer site configuration', $account), 'User still has "administer site configuration" permission.');
   }
 }
diff --git a/core/modules/user/lib/Drupal/user/UserAccess.php b/core/modules/user/lib/Drupal/user/UserAccess.php
new file mode 100644
index 0000000..62f29d2
--- /dev/null
+++ b/core/modules/user/lib/Drupal/user/UserAccess.php
@@ -0,0 +1,116 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\user\UserAccess.
+ */
+
+namespace Drupal\user;
+use Drupal\Core\Database\Connection;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\Core\ControllerInterface;
+
+class UserAccess implements ControllerInterface {
+  /**
+   * TODO - docs
+   * @var unknown_type
+   */
+  protected $perm = array();
+
+  protected $role_cache = array();
+
+  /**
+   * The database connection object for this controller.
+   *
+   * @var \Drupal\Core\Database\Connection
+   */
+  protected $database;
+
+  /**
+   * Constructs a new ActionController.
+   *
+   * @param \Drupal\Core\Database\Connection $database
+   *   The database connection object to be used by this controller.
+   */
+  public function __construct(Connection $database) {
+    $this->database = $database;
+  }
+
+  /**
+   * Implements \Drupal\Core\ControllerInterface::create().
+   */
+  public static function create(ContainerInterface $container) {
+    return new static($container->get('database'));
+  }
+
+  public function check($string, $account) {
+    // User #1 has all privileges:
+    if ($account->uid == 1) {
+      return TRUE;
+    }
+
+    // To reduce the number of SQL queries, we cache the user's permissions.
+    if (!isset($this->perm[$account->uid])) {
+      $role_permissions = $this->userRolePermissions($account->roles);
+
+      $perms = array();
+      foreach ($role_permissions as $one_role) {
+        $perms += $one_role;
+      }
+      $this->perm[$account->uid] = $perms;
+    }
+
+    return isset($this->perm[$account->uid][$string]);
+  }
+
+  public function resetCache() {
+    // @todo -rename to permisisonCache to distinguish from roles cache
+    $this->perm = array();
+  }
+
+  /**
+   * Determines the permissions for one or more roles.
+   *
+   * @param $roles
+   *   An array whose keys are the role IDs of interest, such as $user->roles.
+   *
+   * @return
+   *   An array indexed by role ID. Each value is an array whose keys are the
+   *   permission strings for the given role ID.
+   */
+  public function userRolePermissions($roles) {
+    $role_permissions = $fetch = array();
+
+    foreach ($roles as $rid => $name) {
+      if (isset($this->role_cache[$rid])) {
+        $role_permissions[$rid] = $this->role_cache[$rid];
+      }
+      else {
+        // Add this rid to the list of those needing to be fetched.
+        $fetch[] = $rid;
+        // Prepare in case no permissions are returned.
+        $this->role_cache[$rid] = array();
+      }
+    }
+
+    if ($fetch) {
+      // Get from the database permissions that were not in the static variable.
+      // Only role IDs with at least one permission assigned will return rows.
+      $result = db_query("SELECT rid, permission FROM {role_permission} WHERE rid IN (:fetch)", array(':fetch' => $fetch));
+
+      foreach ($result as $row) {
+        $this->role_cache[$row->rid][$row->permission] = TRUE;
+      }
+      foreach ($fetch as $rid) {
+        // For every rid, we know we at least assigned an empty array.
+        $role_permissions[$rid] = $this->role_cache[$rid];
+      }
+    }
+
+    return $role_permissions;
+  }
+
+  public function resetRoleCache() {
+    $this->role_cache = array();
+  }
+}
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 3ae6154..bbc18fc 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -471,36 +471,8 @@ function user_role_permissions($roles) {
  * can perform all actions.
  */
 function user_access($string, $account = NULL) {
-  global $user;
-
-  if (!isset($account)) {
-    $account = $user;
-  }
-
-  // User #1 has all privileges:
-  if ($account->uid == 1) {
-    return TRUE;
-  }
-
-  // To reduce the number of SQL queries, we cache the user's permissions
-  // in a static variable.
-  // Use the advanced drupal_static() pattern, since this is called very often.
-  static $drupal_static_fast;
-  if (!isset($drupal_static_fast)) {
-    $drupal_static_fast['perm'] = &drupal_static(__FUNCTION__);
-  }
-  $perm = &$drupal_static_fast['perm'];
-  if (!isset($perm[$account->uid])) {
-    $role_permissions = user_role_permissions($account->roles);
-
-    $perms = array();
-    foreach ($role_permissions as $one_role) {
-      $perms += $one_role;
-    }
-    $perm[$account->uid] = $perms;
-  }
-
-  return isset($perm[$account->uid][$string]);
+  $service = \Drupal::service('user.access');
+  return $service->check($string, isset($account) ? $account : $GLOBALS['user']);
 }
 
 /**
@@ -1997,8 +1969,8 @@ function user_role_grant_permissions($rid, array $permissions = array()) {
   }
 
   // Clear the user access cache.
-  drupal_static_reset('user_access');
-  drupal_static_reset('user_role_permissions');
+  \Drupal::service('user.access')->resetCache();
+  \Drupal::service('user.access')->resetRoleCache();
 }
 
 /**
@@ -2020,8 +1992,8 @@ function user_role_revoke_permissions($rid, array $permissions = array()) {
     ->execute();
 
   // Clear the user access cache.
-  drupal_static_reset('user_access');
-  drupal_static_reset('user_role_permissions');
+  \Drupal::service('user.access')->resetCache();
+  \Drupal::service('user.access')->resetRoleCache();
 }
 
 /**
diff --git a/core/modules/user/user.services.yml b/core/modules/user/user.services.yml
index 77f93e2..ddb6762 100644
--- a/core/modules/user/user.services.yml
+++ b/core/modules/user/user.services.yml
@@ -17,3 +17,6 @@ services:
   user.autocomplete:
     class: Drupal\user\UserAutocomplete
     arguments: ['@database', '@config.factory']
+  user.access:
+    class: Drupal\user\UserAccess
+    arguments: ['@database']
