diff --git a/core/core.services.yml b/core/core.services.yml
index 5b410a2..72a256a 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -185,6 +185,9 @@ services:
   path.alias_manager:
     class: Drupal\Core\Path\AliasManager
     arguments: ['@path.alias_storage', '@path.alias_whitelist', '@language_manager']
+  path.matcher:
+    class: Drupal\Core\Path\PathMatcher
+    arguments: ['@config.factory']
   http_client:
     class: Drupal\Core\Http\Client
     tags:
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index b00d23b..7108d24 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -322,6 +322,9 @@ function install_begin_request(&$install_state) {
   $container
     ->register('string_translation', 'Drupal\Core\StringTranslation\TranslationManager')
     ->addArgument(new Reference('language_manager'));
+  $container
+    ->register('path.matcher', 'Drupal\Core\Path\PathMatcher')
+    ->addArgument(new Reference('config.factory'));
 
   \Drupal::setContainer($container);
 
diff --git a/core/includes/path.inc b/core/includes/path.inc
index 6043749..02ab498 100644
--- a/core/includes/path.inc
+++ b/core/includes/path.inc
@@ -41,27 +41,12 @@ function drupal_is_front_page() {
  *
  * @return
  *   Boolean value: TRUE if the path matches a pattern, FALSE otherwise.
+ *
+ * @deprecated as of Drupal 8.0. Use
+ *   \Drupal\Core\Path\PathMatcherInterface::matchPath() instead.
  */
 function drupal_match_path($path, $patterns) {
-  $regexps = &drupal_static(__FUNCTION__);
-
-  if (!isset($regexps[$patterns])) {
-    // Convert path settings to a regular expression.
-    // Therefore replace newlines with a logical or, /* with asterisks and the <front> with the frontpage.
-    $to_replace = array(
-      '/(\r\n?|\n)/', // newlines
-      '/\\\\\*/',     // asterisks
-      '/(^|\|)\\\\<front\\\\>($|\|)/' // <front>
-    );
-    $replacements = array(
-      '|',
-      '.*',
-      '\1' . preg_quote(\Drupal::config('system.site')->get('page.front'), '/') . '\2'
-    );
-    $patterns_quoted = preg_quote($patterns, '/');
-    $regexps[$patterns] = '/^(' . preg_replace($to_replace, $replacements, $patterns_quoted) . ')$/';
-  }
-  return (bool)preg_match($regexps[$patterns], $path);
+  return \Drupal::service('path.matcher')->matchPath($path, $patterns);
 }
 
 /**
diff --git a/core/lib/Drupal/Core/Path/PathMatcher.php b/core/lib/Drupal/Core/Path/PathMatcher.php
new file mode 100644
index 0000000..449ba2b
--- /dev/null
+++ b/core/lib/Drupal/Core/Path/PathMatcher.php
@@ -0,0 +1,77 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Path\PathMatcher.
+ */
+
+namespace Drupal\Core\Path;
+
+use Drupal\Core\Config\ConfigFactoryInterface;
+
+/**
+ * Provides a path matcher.
+ */
+class PathMatcher implements PathMatcherInterface {
+
+  /**
+   * The default front page.
+   *
+   * @var string
+   */
+  protected $frontPage;
+
+  /**
+   * The cache of regular expressions.
+   *
+   * @var array
+   */
+  protected $regexes;
+
+  /**
+   * The config factory service.
+   *
+   * @var \Drupal\Core\Config\ConfigFactoryInterface
+   */
+  protected $configFactory;
+
+  /**
+   * Creates a new PathMatcher.
+   *
+   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+   *   The config factory.
+   */
+  public function __construct(ConfigFactoryInterface $config_factory) {
+    $this->configFactory = $config_factory;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function matchPath($path, $patterns) {
+
+    if (!isset($this->regexes[$patterns])) {
+      // Lazy-load front page config.
+      if (!isset($this->frontPage)) {
+        $this->frontPage = $this->configFactory->get('system.site')->get('page.front');
+      }
+      // Convert path settings to a regular expression.
+      $to_replace = array(
+        // Replace newlines with a logical 'or'.
+        '/(\r\n?|\n)/',
+        // Quote asterisks.
+        '/\\\\\*/',
+        // Quote <front> keyword.
+        '/(^|\|)\\\\<front\\\\>($|\|)/',
+      );
+      $replacements = array(
+        '|',
+        '.*',
+        '\1' . preg_quote($this->frontPage, '/') . '\2',
+      );
+      $patterns_quoted = preg_quote($patterns, '/');
+      $this->regexes[$patterns] = '/^(' . preg_replace($to_replace, $replacements, $patterns_quoted) . ')$/';
+    }
+    return (bool) preg_match($this->regexes[$patterns], $path);
+  }
+}
diff --git a/core/lib/Drupal/Core/Path/PathMatcherInterface.php b/core/lib/Drupal/Core/Path/PathMatcherInterface.php
new file mode 100644
index 0000000..8c0b800
--- /dev/null
+++ b/core/lib/Drupal/Core/Path/PathMatcherInterface.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Path\PathMatcherInterface
+ */
+
+namespace Drupal\Core\Path;
+
+/**
+ * Provides an interface for URL path matchers.
+ */
+interface PathMatcherInterface {
+
+  /**
+   * Checks if a path matches any pattern in a set of patterns.
+   *
+   * @param string $path
+   *   The path to match.
+   * @param string $patterns
+   *   A set of patterns separated by a newline.
+   *
+   * @return bool
+   *   TRUE if the path matches a pattern, FALSE otherwise.
+   */
+  public function matchPath($path, $patterns);
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Path/PathMatcherTest.php b/core/tests/Drupal/Tests/Core/Path/PathMatcherTest.php
new file mode 100644
index 0000000..9c36e2a
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Path/PathMatcherTest.php
@@ -0,0 +1,116 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Tests\Core\Path\PathMatcherTest
+ */
+
+namespace Drupal\Tests\Core\Path;
+
+use Drupal\Core\Path\PathMatcher;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @group Drupal
+ * @see \Drupal\Core\Path\PathMatcher
+ */
+class PathMatcherTest extends UnitTestCase {
+
+  /**
+   * The path matcher under test.
+   *
+   * @var \Drupal\Core\Path\PathMatcher
+   */
+  protected $pathMatcher;
+
+  /**
+   * @var string
+   */
+  protected $patterns;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Path Matcher tests',
+      'description' => 'Tests that path matching is working properly.',
+      'group' => 'Path',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    // Create a stub config factory with all config settings that will be
+    // checked during this test.
+    $config_factory_stub = $this->getConfigFactoryStub(
+      array(
+        'system.site' => array(
+          'page.front' => 'user',
+        ),
+      )
+    );
+    $this->pathMatcher = new PathMatcher($config_factory_stub);
+  }
+
+
+  /**
+   * Test that paths matching works with multiple patterns.
+   *
+   * @dataProvider getMatchPathData
+   */
+  public function testMatchPath($patterns, $paths) {
+    foreach ($paths as $path) {
+      $this->assertTrue($this->pathMatcher->matchPath($path, $patterns), "The path $path matches the patterns.");
+    }
+  }
+
+  /**
+   * Test that standard paths works with multiple patterns.
+   *
+   * @dataProvider getNoMatchPathData
+   */
+  public function testNoMatchPath($patterns, $paths) {
+    foreach ($paths as $path) {
+      $this->assertFalse($this->pathMatcher->matchPath($path, $patterns), "The path $path does not match the patterns.");
+    }
+  }
+
+  /**
+   * Provides test path data.
+   *
+   * @return array
+   *   A nested array of pattern arrays and path arrays.
+   */
+  public function getMatchPathData() {
+    return array(
+      // Match explicit path pattern.
+      array(
+        "my/pass/page\r\nmy/pass/page2\r\nfoo",
+        array('my/pass/page', 'my/pass/page2'),
+      ),
+      // Match wildcard path pattern.
+      array(
+        'my/pass/*',
+        array('my/pass/page3'),
+      ),
+    );
+  }
+
+  /**
+   * Provides test path data for non-matches.
+   *
+   * @return array
+   *   A nested array of pattern arrays and path arrays.
+   */
+  public function getNoMatchPathData() {
+    return array(
+      array(
+        "my/pass/page\r\nmy/pass/page2\r\nfoo",
+        array('my/pass/page4'),
+      ),
+    );
+  }
+}
