diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 0ea383f..8538ac9 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -13,7 +13,6 @@
 use Drupal\Core\DrupalKernel;
 use Drupal\Core\Extension\ExtensionDiscovery;
 use Drupal\Core\Logger\RfcLogLevel;
-use Drupal\Core\Site\Settings;
 use Drupal\Core\Utility\Error;
 use Symfony\Component\ClassLoader\ApcClassLoader;
 use Symfony\Component\HttpFoundation\Request;
diff --git a/core/includes/install.inc b/core/includes/install.inc
index bcca67c..1984e78 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -323,7 +323,7 @@ function drupal_rewrite_settings($settings = array(), $settings_file = NULL) {
       // Settings singleton.
       if (!empty($settings_settings)) {
         $old_settings = Settings::getAll();
-        new Settings($settings_settings + $old_settings);
+        Settings::setCreateInstance($settings_settings + $old_settings);
       }
       // The existing settings.php file might have been included already. In
       // case an opcode cache is enabled, the rewritten contents of the file
diff --git a/core/lib/Drupal/Core/Cache/CacheFactory.php b/core/lib/Drupal/Core/Cache/CacheFactory.php
index 0a0a977..94eb812 100644
--- a/core/lib/Drupal/Core/Cache/CacheFactory.php
+++ b/core/lib/Drupal/Core/Cache/CacheFactory.php
@@ -10,7 +10,7 @@
 /**
  * Defines the cache backend factory.
  */
-use Drupal\Core\Site\Settings;
+use Drupal\Core\Site\Settings\SettingsInterface;
 use Symfony\Component\DependencyInjection\ContainerAwareInterface;
 use Symfony\Component\DependencyInjection\ContainerAwareTrait;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -22,7 +22,7 @@ class CacheFactory implements CacheFactoryInterface,  ContainerAwareInterface {
   /**
    * The settings array.
    *
-   * @var \Drupal\Core\Site\Settings
+   * @var \Drupal\Core\Site\Settings\SettingsInterface
    */
   protected $settings;
 
@@ -42,13 +42,13 @@ class CacheFactory implements CacheFactoryInterface,  ContainerAwareInterface {
   /**
    * Constructs CacheFactory object.
    *
-   * @param \Drupal\Core\Site\Settings $settings
+   * @param \Drupal\Core\Site\Settings\SettingsInterface $settings
    *   The settings array.
    * @param array $default_bin_backends
    *   (optional) A mapping of bin to backend service name. Mappings in
    *   $settings take precedence over this.
    */
-  public function __construct(Settings $settings, array $default_bin_backends = array()) {
+  public function __construct(SettingsInterface $settings, array $default_bin_backends = array()) {
     $this->settings = $settings;
     $this->defaultBinBackends = $default_bin_backends;
   }
diff --git a/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php b/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php
index c261b84..6225e55 100644
--- a/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php
+++ b/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php
@@ -6,7 +6,8 @@
  */
 
 namespace Drupal\Core\Cache;
-use Drupal\Core\Site\Settings;
+
+use Drupal\Core\Site\Settings\SettingsInterface;
 use Symfony\Component\DependencyInjection\ContainerAwareTrait;
 
 /**
@@ -33,7 +34,7 @@ class ChainedFastBackendFactory implements CacheFactoryInterface {
   /**
    * Constructs ChainedFastBackendFactory object.
    *
-   * @param \Drupal\Core\Site\Settings|NULL $settings
+   * @param \Drupal\Core\Site\Settings\SettingsInterface|NULL $settings
    *   (optional) The settings object.
    * @param string|NULL $consistent_service_name
    *   (optional) The service name of the consistent backend factory. Defaults
@@ -45,7 +46,7 @@ class ChainedFastBackendFactory implements CacheFactoryInterface {
    *   - 'cache.backend.apcu' (if the PHP process has APCu enabled)
    *   - NULL (if the PHP process doesn't have APCu enabled)
    */
-  public function __construct(Settings $settings = NULL, $consistent_service_name = NULL, $fast_service_name = NULL) {
+  public function __construct(SettingsInterface $settings = NULL, $consistent_service_name = NULL, $fast_service_name = NULL) {
     // Default the consistent backend to the site's default backend.
     if (!isset($consistent_service_name)) {
       $cache_settings = isset($settings) ? $settings->get('cache') : array();
diff --git a/core/lib/Drupal/Core/Installer/InstallerKernel.php b/core/lib/Drupal/Core/Installer/InstallerKernel.php
index 9b0b645..c363970 100644
--- a/core/lib/Drupal/Core/Installer/InstallerKernel.php
+++ b/core/lib/Drupal/Core/Installer/InstallerKernel.php
@@ -9,7 +9,6 @@
 
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\DrupalKernel;
-use Drupal\Core\Site\Settings;
 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
 
 /**
diff --git a/core/lib/Drupal/Core/Queue/QueueFactory.php b/core/lib/Drupal/Core/Queue/QueueFactory.php
index 70824c3..ad4a84e 100644
--- a/core/lib/Drupal/Core/Queue/QueueFactory.php
+++ b/core/lib/Drupal/Core/Queue/QueueFactory.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Queue;
 
-use Drupal\Core\Site\Settings;
+use Drupal\Core\Site\Settings\SettingsInterface;
 use Symfony\Component\DependencyInjection\ContainerAwareInterface;
 use Symfony\Component\DependencyInjection\ContainerAwareTrait;
 
@@ -28,15 +28,17 @@ class QueueFactory implements ContainerAwareInterface {
   /**
    * The settings object.
    *
-   * @var \Drupal\Core\Site\Settings
+   * @var \Drupal\Core\Site\Settings\SettingsInterface
    */
   protected $settings;
 
-
   /**
    * Constructs a queue factory.
+   *
+   * @param \Drupal\Core\Site\Settings\SettingsInterface $settings
+   *   The settings object.
    */
-  function __construct(Settings $settings) {
+  function __construct(SettingsInterface $settings) {
     $this->settings = $settings;
   }
 
diff --git a/core/lib/Drupal/Core/Routing/UrlGenerator.php b/core/lib/Drupal/Core/Routing/UrlGenerator.php
index 4657fdf..832a564 100644
--- a/core/lib/Drupal/Core/Routing/UrlGenerator.php
+++ b/core/lib/Drupal/Core/Routing/UrlGenerator.php
@@ -20,7 +20,7 @@
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
 use Drupal\Core\RouteProcessor\OutboundRouteProcessorInterface;
-use Drupal\Core\Site\Settings;
+use Drupal\Core\Site\Settings\SettingsInterface;
 
 /**
  * Generates URLs from route names and parameters.
@@ -78,14 +78,14 @@ class UrlGenerator extends ProviderBasedGenerator implements UrlGeneratorInterfa
    *   The route processor.
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config
    *    The config factory.
-   * @param \Drupal\Core\Site\Settings $settings
+   * @param \Drupal\Core\Site\Settings\SettingsInterface $settings
    *    The read only settings.
    * @param \Psr\Log\LoggerInterface $logger
    *   An optional logger for recording errors.
    * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
    *   A request stack object.
    */
-  public function __construct(RouteProviderInterface $provider, OutboundPathProcessorInterface $path_processor, OutboundRouteProcessorInterface $route_processor, ConfigFactoryInterface $config, Settings $settings, LoggerInterface $logger = NULL, RequestStack $request_stack) {
+  public function __construct(RouteProviderInterface $provider, OutboundPathProcessorInterface $path_processor, OutboundRouteProcessorInterface $route_processor, ConfigFactoryInterface $config, SettingsInterface $settings, LoggerInterface $logger = NULL, RequestStack $request_stack) {
     parent::__construct($provider, $logger);
 
     $this->pathProcessor = $path_processor;
diff --git a/core/lib/Drupal/Core/Session/MetadataBag.php b/core/lib/Drupal/Core/Session/MetadataBag.php
index 4b44739..518163c 100644
--- a/core/lib/Drupal/Core/Session/MetadataBag.php
+++ b/core/lib/Drupal/Core/Session/MetadataBag.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Session;
 
-use Drupal\Core\Site\Settings;
+use Drupal\Core\Site\Settings\SettingsInterface;
 use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag as SymfonyMetadataBag;
 
 /**
@@ -23,10 +23,10 @@ class MetadataBag extends SymfonyMetadataBag {
   /**
    * Constructs a new metadata bag instance.
    *
-   * @param \Drupal\Core\Site\Settings $settings
+   * @param \Drupal\Core\Site\Settings\SettingsInterface $settings
    *   The settings instance.
    */
-  public function __construct(Settings $settings) {
+  public function __construct(SettingsInterface $settings) {
     $update_threshold = $settings->get('session_write_interval', 180);
     parent::__construct('_sf2_meta', $update_threshold);
   }
diff --git a/core/lib/Drupal/Core/Session/SessionManager.php b/core/lib/Drupal/Core/Session/SessionManager.php
index efb3b7a..2e43939 100644
--- a/core/lib/Drupal/Core/Session/SessionManager.php
+++ b/core/lib/Drupal/Core/Session/SessionManager.php
@@ -11,7 +11,7 @@
 use Drupal\Core\Database\Connection;
 use Drupal\Core\Session\AnonymousUserSession;
 use Drupal\Core\Session\SessionHandler;
-use Drupal\Core\Site\Settings;
+use Drupal\Core\Site\Settings\SettingsInterface;
 use Symfony\Component\HttpFoundation\RequestStack;
 use Symfony\Component\HttpFoundation\Session\Storage\Handler\WriteCheckSessionHandler;
 use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
@@ -84,10 +84,10 @@ class SessionManager extends NativeSessionStorage implements SessionManagerInter
    *   The database connection.
    * @param \Drupal\Core\Session\MetadataBag $metadata_bag
    *   The session metadata bag.
-   * @param \Drupal\Core\Site\Settings $settings
+   * @param \Drupal\Core\Site\Settings\SettingsInterface $settings
    *   The settings instance.
    */
-  public function __construct(RequestStack $request_stack, Connection $connection, MetadataBag $metadata_bag, Settings $settings) {
+  public function __construct(RequestStack $request_stack, Connection $connection, MetadataBag $metadata_bag, SettingsInterface $settings) {
     $options = array();
     $this->requestStack = $request_stack;
     $this->connection = $connection;
diff --git a/core/lib/Drupal/Core/Site/Settings.php b/core/lib/Drupal/Core/Site/Settings.php
index def307f..2be949c 100644
--- a/core/lib/Drupal/Core/Site/Settings.php
+++ b/core/lib/Drupal/Core/Site/Settings.php
@@ -8,37 +8,74 @@
 namespace Drupal\Core\Site;
 
 use Drupal\Core\Database\Database;
+use Drupal\Core\Site\Settings\PlaceholderSettings;
+use Drupal\Core\Site\Settings\SettingsInstance;
+use Drupal\Core\Site\Settings\SettingsInterface;
+
+/**
+ * Initialize Settings::$instance with a placeholder object.
+ * See https://www.drupal.org/node/2363881
+ *
+ * This technique is the most reliable way to initialize static properties with
+ * non-trivial expressions. It should NOT be used for anything else. Also, the
+ * code being called MUST NOT have any side effects other than initializing the
+ * static properties.
+ *
+ * In general (e.g. in PSR-1), a PHP file should either declare symbols OR have
+ * side-effects, but not both. This specific case is ok only because the side
+ * effect applies to nothing else but the class declared in the same file, and
+ * it happens immediately after the class is being declared. A version of the
+ * class without this initialization applied is never available to the outside
+ * world.
+ *
+ * Note: PHP does not care whether this is called before or after the class
+ * declaration. It is called before only for better visibility.
+ */
+Settings::initStaticProperties();
 
 /**
  * Read only settings that are initialized with the class.
  *
  * @ingroup utility
  */
-final class Settings {
+abstract class Settings {
 
   /**
-   * Array with the settings.
+   * Singleton instance.
    *
-   * @var array
+   * @var \Drupal\Core\Site\Settings\SettingsInterface
    */
-  private $storage = array();
+  protected static $instance;
 
   /**
-   * Singleton instance.
-   *
-   * @var \Drupal\Core\Site\Settings
+   * Initializes the static properties. Called once from within the class file.
    */
-  private static $instance;
+  public static function initStaticProperties() {
+    static::$instance = new PlaceholderSettings('Settings::$instance is not initialized yet.');
+  }
 
   /**
-   * Constructor.
+   * Sets or replaces static::$instance with a new Settings object created from a
+   * settings array.
    *
    * @param array $settings
    *   Array with the settings.
+   *
+   * @return \Drupal\Core\Site\Settings\SettingsInterface
+   *   The new value of static::$instance.
    */
-  public function __construct(array $settings) {
-    $this->storage = $settings;
-    self::$instance = $this;
+  public static function setCreateInstance(array $settings) {
+    static::$instance = new SettingsInstance($settings);
+    return static::$instance;
+  }
+
+  /**
+   * Sets or replaces static::$instance with the given Settings object.
+   *
+   * @param \Drupal\Core\Site\Settings\SettingsInterface $instance
+   */
+  public static function setInstance(SettingsInterface $instance) {
+    static::$instance = $instance;
   }
 
   /**
@@ -47,10 +84,13 @@ public function __construct(array $settings) {
    * A singleton is used because this class is used before the container is
    * available.
    *
-   * @return \Drupal\Core\Site\Settings
+   * @return \Drupal\Core\Site\Settings\SettingsInterface|null
    */
   public static function getInstance() {
-    return self::$instance;
+    if (static::$instance instanceof PlaceholderSettings) {
+      return NULL;
+    }
+    return static::$instance;
   }
 
   /**
@@ -69,7 +109,7 @@ public static function getInstance() {
    *   The value of the setting, the provided default if not set.
    */
   public static function get($name, $default = NULL) {
-    return isset(self::$instance->storage[$name]) ? self::$instance->storage[$name] : $default;
+    return static::$instance->get($name, $default);
   }
 
   /**
@@ -79,7 +119,7 @@ public static function get($name, $default = NULL) {
    *   All the settings.
    */
   public static function getAll() {
-    return self::$instance->storage;
+    return static::$instance->getAll();
   }
 
   /**
@@ -110,7 +150,7 @@ public static function initialize($site_path, &$class_loader) {
     Database::setMultipleConnectionInfo($databases);
 
     // Initialize Settings.
-    new Settings($settings);
+    static::setCreateInstance($settings);
   }
 
   /**
@@ -122,15 +162,7 @@ public static function initialize($site_path, &$class_loader) {
    * @throws \RuntimeException
    */
   public static function getHashSalt() {
-    $hash_salt = self::$instance->get('hash_salt');
-    // This should never happen, as it breaks user logins and many other
-    // services. Therefore, explicitly notify the user (developer) by throwing
-    // an exception.
-    if (empty($hash_salt)) {
-      throw new \RuntimeException('Missing $settings[\'hash_salt\'] in settings.php.');
-    }
-
-    return $hash_salt;
+    return static::$instance->getHashSalt();
   }
 
 }
diff --git a/core/lib/Drupal/Core/Site/Settings/PlaceholderSettings.php b/core/lib/Drupal/Core/Site/Settings/PlaceholderSettings.php
new file mode 100644
index 0000000..6654885
--- /dev/null
+++ b/core/lib/Drupal/Core/Site/Settings/PlaceholderSettings.php
@@ -0,0 +1,55 @@
+<?php
+
+
+namespace Drupal\Core\Site\Settings;
+
+use Drupal\Core\Site\Settings\SettingsInterface;
+use Symfony\Component\Debug\Exception\ContextErrorException;
+
+/**
+ * Placeholder settings object.
+ *
+ * Throws exceptions instead of doing anything.
+ *
+ * @see \Drupal\Core\Site\Settings::$instance
+ */
+class PlaceholderSettings implements SettingsInterface {
+
+  /**
+   * @var string
+   */
+  private $message;
+
+  /**
+   * Constructor
+   *
+   * @param string $message
+   *   Message for exceptions.
+   */
+  function __construct($message = NULL) {
+    $this->message = isset($message)
+      ? $message
+      : 'Settings not initialized.';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function get($name, $default = NULL) {
+    throw new SettingsNotInitializedException($this->message);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getAll() {
+    throw new SettingsNotInitializedException($this->message);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getHashSalt() {
+    throw new SettingsNotInitializedException($this->message);
+  }
+}
diff --git a/core/lib/Drupal/Core/Site/Settings/SettingsInstance.php b/core/lib/Drupal/Core/Site/Settings/SettingsInstance.php
new file mode 100644
index 0000000..ca569ac
--- /dev/null
+++ b/core/lib/Drupal/Core/Site/Settings/SettingsInstance.php
@@ -0,0 +1,82 @@
+<?php
+
+
+namespace Drupal\Core\Site\Settings;
+
+use Drupal\Core\Site\Settings\SettingsInterface;
+
+/**
+ * Object to encapsulate the $settings array from settings.php.
+ *
+ * @see \Drupal\Core\Site\Settings
+ */
+class SettingsInstance implements SettingsInterface {
+
+  /**
+   * Array with the settings.
+   *
+   * @var array
+   */
+  private $storage = array();
+
+  /**
+   * Constructor.
+   *
+   * @param array $settings
+   *   Array with the settings.
+   */
+  public function __construct(array $settings) {
+    $this->storage = $settings;
+  }
+
+  /**
+   * Returns a setting.
+   *
+   * Settings can be set in settings.php in the $settings array and requested
+   * by this function. Settings should be used over configuration for read-only,
+   * possibly low bootstrap configuration that is environment specific.
+   *
+   * @param string $name
+   *   The name of the setting to return.
+   * @param mixed $default
+   *   (optional) The default value to use if this setting is not set.
+   *
+   * @return mixed
+   *   The value of the setting, the provided default if not set.
+   */
+  public function get($name, $default = NULL) {
+    return isset($this->storage[$name])
+      ? $this->storage[$name]
+      : $default;
+  }
+
+  /**
+   * Returns all the settings. This is only used for testing purposes.
+   *
+   * @return array
+   *   All the settings.
+   */
+  public function getAll() {
+    return $this->storage;
+  }
+
+  /**
+   * Gets a salt useful for hardening against SQL injection.
+   *
+   * @return string
+   *   A salt based on information in settings.php, not in the database.
+   *
+   * @throws \RuntimeException
+   */
+  public function getHashSalt() {
+    $hash_salt = $this->get('hash_salt');
+    // This should never happen, as it breaks user logins and many other
+    // services. Therefore, explicitly notify the user (developer) by throwing
+    // an exception.
+    if (empty($hash_salt)) {
+      throw new \RuntimeException('Missing $settings[\'hash_salt\'] in settings.php.');
+    }
+
+    return $hash_salt;
+  }
+}
diff --git a/core/lib/Drupal/Core/Site/Settings/SettingsInterface.php b/core/lib/Drupal/Core/Site/Settings/SettingsInterface.php
new file mode 100644
index 0000000..351f79f
--- /dev/null
+++ b/core/lib/Drupal/Core/Site/Settings/SettingsInterface.php
@@ -0,0 +1,46 @@
+<?php
+namespace Drupal\Core\Site\Settings;
+
+/**
+ * Read only settings that are initialized with the class.
+ *
+ * @ingroup utility
+ */
+interface SettingsInterface {
+
+  /**
+   * Returns a setting.
+   *
+   * Settings can be set in settings.php in the $settings array and requested
+   * by this function. Settings should be used over configuration for read-only,
+   * possibly low bootstrap configuration that is environment specific.
+   *
+   * @param string $name
+   *   The name of the setting to return.
+   * @param mixed $default
+   *   (optional) The default value to use if this setting is not set.
+   *
+   * @return mixed
+   *   The value of the setting, the provided default if not set.
+   */
+  public function get($name, $default = NULL);
+
+  /**
+   * Returns all the settings. This is only used for testing purposes.
+   *
+   * @return array
+   *   All the settings.
+   */
+  public function getAll();
+
+  /**
+   * Gets a salt useful for hardening against SQL injection.
+   *
+   * @return string
+   *   A salt based on information in settings.php, not in the database.
+   *
+   * @throws \RuntimeException
+   */
+  public function getHashSalt();
+
+}
diff --git a/core/lib/Drupal/Core/Site/Settings/SettingsNotInitializedException.php b/core/lib/Drupal/Core/Site/Settings/SettingsNotInitializedException.php
new file mode 100644
index 0000000..6e60c4d
--- /dev/null
+++ b/core/lib/Drupal/Core/Site/Settings/SettingsNotInitializedException.php
@@ -0,0 +1,13 @@
+<?php
+
+
+namespace Drupal\Core\Site\Settings;
+
+/**
+ * Exception that is thrown if a settings variable is not initialized.
+ *
+ * @see \Drupal\Core\Site\Settings\PlaceholderSettings
+ */
+class SettingsNotInitializedException extends \RuntimeException {
+
+}
diff --git a/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php b/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php
index 344364d..65f4325 100644
--- a/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php
+++ b/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php
@@ -6,7 +6,7 @@
 
 namespace Drupal\Core\StackMiddleware;
 
-use Drupal\Core\Site\Settings;
+use Drupal\Core\Site\Settings\SettingsInterface;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\HttpKernelInterface;
 
@@ -25,7 +25,7 @@ class ReverseProxyMiddleware implements HttpKernelInterface {
   /**
    * The site settings.
    *
-   * @var \Drupal\Core\Site\Settings
+   * @var \Drupal\Core\Site\Settings\SettingsInterface
    */
   protected $settings;
 
@@ -34,10 +34,10 @@ class ReverseProxyMiddleware implements HttpKernelInterface {
    *
    * @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel
    *   The decorated kernel.
-   * @param \Drupal\Core\Site\Settings $settings
+   * @param \Drupal\Core\Site\Settings\SettingsInterface $settings
    *   The site settings.
    */
-  public function __construct(HttpKernelInterface $http_kernel, Settings $settings) {
+  public function __construct(HttpKernelInterface $http_kernel, SettingsInterface $settings) {
     $this->httpKernel = $http_kernel;
     $this->settings = $settings;
   }
diff --git a/core/lib/Drupal/Core/StringTranslation/Translator/CustomStrings.php b/core/lib/Drupal/Core/StringTranslation/Translator/CustomStrings.php
index 24f5085..eafc524 100644
--- a/core/lib/Drupal/Core/StringTranslation/Translator/CustomStrings.php
+++ b/core/lib/Drupal/Core/StringTranslation/Translator/CustomStrings.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\StringTranslation\Translator;
 
-use Drupal\Core\Site\Settings;
+use Drupal\Core\Site\Settings\SettingsInterface;
 
 /**
  * String translator using overrides from variables.
@@ -20,17 +20,17 @@ class CustomStrings extends StaticTranslation {
   /**
    * The settings read only object.
    *
-   * @var \Drupal\Core\Site\Settings
+   * @var \Drupal\Core\Site\Settings\SettingsInterface
    */
   protected $settings;
 
   /**
    * Constructs a CustomStrings object.
    *
-   * @param \Drupal\Core\Site\Settings $settings
+   * @param \Drupal\Core\Site\Settings\SettingsInterface $settings
    *   The settings read only object.
    */
-  public function __construct(Settings $settings) {
+  public function __construct(SettingsInterface $settings) {
     parent::__construct();
     $this->settings = $settings;
   }
diff --git a/core/lib/Drupal/Core/Template/TwigNodeTrans.php b/core/lib/Drupal/Core/Template/TwigNodeTrans.php
index ea51846..2f2ec25 100644
--- a/core/lib/Drupal/Core/Template/TwigNodeTrans.php
+++ b/core/lib/Drupal/Core/Template/TwigNodeTrans.php
@@ -15,7 +15,6 @@
 namespace Drupal\Core\Template;
 
 use Drupal\Component\Utility\Unicode;
-use Drupal\Core\Site\Settings;
 
 /**
  * A class that defines the Twig 'trans' tag for Drupal.
diff --git a/core/lib/Drupal/Core/Test/TestRunnerKernel.php b/core/lib/Drupal/Core/Test/TestRunnerKernel.php
index 8829113..940cb23 100644
--- a/core/lib/Drupal/Core/Test/TestRunnerKernel.php
+++ b/core/lib/Drupal/Core/Test/TestRunnerKernel.php
@@ -53,7 +53,7 @@ public function __construct($environment, $class_loader) {
   public function boot() {
     // Ensure that required Settings exist.
     if (!Settings::getAll()) {
-      new Settings(array(
+      Settings::setCreateInstance(array(
         'hash_salt' => 'run-tests',
         // If there is no settings.php, then there is no parent site. In turn,
         // there is no public files directory; use a custom public files path.
diff --git a/core/modules/forum/src/Tests/ForumUninstallTest.php b/core/modules/forum/src/Tests/ForumUninstallTest.php
index 70983fd..b6d3c10 100644
--- a/core/modules/forum/src/Tests/ForumUninstallTest.php
+++ b/core/modules/forum/src/Tests/ForumUninstallTest.php
@@ -12,7 +12,6 @@
 use Drupal\Component\Utility\String;
 use Drupal\Core\DrupalKernel;
 use Drupal\Core\Session\UserSession;
-use Drupal\Core\Site\Settings;
 use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\node\Entity\NodeType;
 use Drupal\simpletest\WebTestBase;
diff --git a/core/modules/language/src/HttpKernel/PathProcessorLanguage.php b/core/modules/language/src/HttpKernel/PathProcessorLanguage.php
index c3a6a9f..a14053b 100644
--- a/core/modules/language/src/HttpKernel/PathProcessorLanguage.php
+++ b/core/modules/language/src/HttpKernel/PathProcessorLanguage.php
@@ -11,7 +11,7 @@
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
 use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
-use Drupal\Core\Site\Settings;
+use Drupal\Core\Site\Settings\SettingsInterface;
 use Drupal\language\ConfigurableLanguageManagerInterface;
 use Drupal\language\LanguageNegotiatorInterface;
 use Symfony\Component\HttpFoundation\Request;
@@ -69,7 +69,7 @@ class PathProcessorLanguage implements InboundPathProcessorInterface, OutboundPa
    *
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config
    *   A config factory object for retrieving configuration settings.
-   * @param \Drupal\Core\Site\Settings $settings
+   * @param \Drupal\Core\Site\Settings\SettingsInterface $settings
    *   The settings instance.
    * @param \Drupal\language\ConfigurableLanguageManagerInterface $language_manager
    *   The configurable language manager.
@@ -78,7 +78,7 @@ class PathProcessorLanguage implements InboundPathProcessorInterface, OutboundPa
    * @param \Drupal\Core\Session\AccountInterface $current_user
    *   The current active user.
    */
-  public function __construct(ConfigFactoryInterface $config, Settings $settings, ConfigurableLanguageManagerInterface $language_manager, LanguageNegotiatorInterface $negotiator, AccountInterface $current_user) {
+  public function __construct(ConfigFactoryInterface $config, SettingsInterface $settings, ConfigurableLanguageManagerInterface $language_manager, LanguageNegotiatorInterface $negotiator, AccountInterface $current_user) {
     $this->config = $config;
     $this->mixedModeSessions = $settings->get('mixed_mode_sessions', FALSE);
     $this->languageManager = $language_manager;
diff --git a/core/modules/language/src/LanguageNegotiator.php b/core/modules/language/src/LanguageNegotiator.php
index 57f8490..1ba403a 100644
--- a/core/modules/language/src/LanguageNegotiator.php
+++ b/core/modules/language/src/LanguageNegotiator.php
@@ -10,7 +10,7 @@
 use Drupal\Component\Plugin\PluginManagerInterface;
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Session\AccountInterface;
-use Drupal\Core\Site\Settings;
+use Drupal\Core\Site\Settings\SettingsInterface;
 use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUI;
 use Symfony\Component\HttpFoundation\RequestStack;
 
@@ -43,7 +43,7 @@ class LanguageNegotiator implements LanguageNegotiatorInterface {
   /**
    * The settings instance.
    *
-   * @return \Drupal\Core\Site\Settings
+   * @return \Drupal\Core\Site\Settings\SettingsInterface
    */
   protected $settings;
 
@@ -84,10 +84,10 @@ class LanguageNegotiator implements LanguageNegotiatorInterface {
    *   The language negotiation methods plugin manager
    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
    *   The configuration factory.
-   * @param \Drupal\Core\Site\Settings $settings
+   * @param \Drupal\Core\Site\Settings\SettingsInterface $settings
    *   The settings instance.
    */
-  public function __construct(ConfigurableLanguageManagerInterface $language_manager, PluginManagerInterface $negotiator_manager, ConfigFactoryInterface $config_factory, Settings $settings, RequestStack $requestStack) {
+  public function __construct(ConfigurableLanguageManagerInterface $language_manager, PluginManagerInterface $negotiator_manager, ConfigFactoryInterface $config_factory, SettingsInterface $settings, RequestStack $requestStack) {
     $this->languageManager = $language_manager;
     $this->negotiatorManager = $negotiator_manager;
     $this->configFactory = $config_factory;
diff --git a/core/modules/simpletest/src/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php
index e281988..45da868 100644
--- a/core/modules/simpletest/src/KernelTestBase.php
+++ b/core/modules/simpletest/src/KernelTestBase.php
@@ -161,7 +161,7 @@ protected function setUp() {
     // Restore and merge settings.
     // DrupalKernel::boot() initializes new Settings, and the containerBuild()
     // method sets additional settings.
-    new Settings($settings + Settings::getAll());
+    Settings::setCreateInstance($settings + Settings::getAll());
 
     // Set the request scope.
     $this->container = $this->kernel->getContainer();
diff --git a/core/modules/simpletest/src/TestBase.php b/core/modules/simpletest/src/TestBase.php
index 9475715..0be52e3 100644
--- a/core/modules/simpletest/src/TestBase.php
+++ b/core/modules/simpletest/src/TestBase.php
@@ -1090,7 +1090,7 @@ private function prepareEnvironment() {
     conf_path(FALSE, TRUE);
 
     // Reset settings.
-    new Settings(array(
+    Settings::setCreateInstance(array(
       // For performance, simply use the database prefix as hash salt.
       'hash_salt' => $this->databasePrefix,
     ));
@@ -1179,7 +1179,7 @@ private function restoreEnvironment() {
     // Restore original in-memory configuration.
     $GLOBALS['config'] = $this->originalConfig;
     $GLOBALS['conf'] = $this->originalConf;
-    new Settings($this->originalSettings);
+    Settings::setCreateInstance($this->originalSettings);
 
     // Restore original statics and globals.
     \Drupal::setContainer($this->originalContainer);
@@ -1279,7 +1279,7 @@ protected function exceptionHandler($exception) {
   protected function settingsSet($name, $value) {
     $settings = Settings::getAll();
     $settings[$name] = $value;
-    new Settings($settings);
+    Settings::setCreateInstance($settings);
   }
 
   /**
diff --git a/core/modules/system/src/Tests/PhpStorage/PhpStorageFactoryTest.php b/core/modules/system/src/Tests/PhpStorage/PhpStorageFactoryTest.php
index 166f3ff..f060a15 100644
--- a/core/modules/system/src/Tests/PhpStorage/PhpStorageFactoryTest.php
+++ b/core/modules/system/src/Tests/PhpStorage/PhpStorageFactoryTest.php
@@ -82,7 +82,7 @@ protected function setSettings($name = 'default', array $configuration = array()
       'secret' => $this->randomString(),
       'bin' => 'test',
     );
-    new Settings($settings);
+    Settings::setCreateInstance($settings);
   }
 
 }
diff --git a/core/modules/system/src/Tests/Theme/TwigEnvironmentTest.php b/core/modules/system/src/Tests/Theme/TwigEnvironmentTest.php
index 6ecabec..050a860 100644
--- a/core/modules/system/src/Tests/Theme/TwigEnvironmentTest.php
+++ b/core/modules/system/src/Tests/Theme/TwigEnvironmentTest.php
@@ -49,7 +49,7 @@ public function testInlineTemplate() {
     $settings['twig_debug'] = TRUE;
     $settings['twig_auto_reload'] = TRUE;
 
-    new Settings($settings);
+    Settings::setCreateInstance($settings);
     $this->container = $this->kernel->rebuildContainer();
     \Drupal::setContainer($this->container);
 
diff --git a/core/modules/update/src/Access/UpdateManagerAccessCheck.php b/core/modules/update/src/Access/UpdateManagerAccessCheck.php
index d057ce3..c13a910 100644
--- a/core/modules/update/src/Access/UpdateManagerAccessCheck.php
+++ b/core/modules/update/src/Access/UpdateManagerAccessCheck.php
@@ -9,7 +9,7 @@
 
 use Drupal\Core\Access\AccessResult;
 use Drupal\Core\Routing\Access\AccessInterface;
-use Drupal\Core\Site\Settings;
+use Drupal\Core\Site\Settings\SettingsInterface;
 
 /**
  * Determines whether allow authorized operations is set.
@@ -19,17 +19,17 @@ class UpdateManagerAccessCheck implements AccessInterface {
   /**
    * Settings Service.
    *
-   * @var \Drupal\Core\Site\Settings
+   * @var \Drupal\Core\Site\Settings\SettingsInterface
    */
   protected $settings;
 
   /**
    * Constructs a UpdateManagerAccessCheck object.
    *
-   * @param \Drupal\Core\Site\Settings $settings
+   * @param \Drupal\Core\Site\Settings\SettingsInterface $settings
    *   The read-only settings container.
    */
-  public function __construct(Settings $settings) {
+  public function __construct(SettingsInterface $settings) {
     $this->settings = $settings;
   }
 
diff --git a/core/modules/user/tests/src/Unit/PermissionsHashTest.php b/core/modules/user/tests/src/Unit/PermissionsHashTest.php
index 2579682..6a5c7b2 100644
--- a/core/modules/user/tests/src/Unit/PermissionsHashTest.php
+++ b/core/modules/user/tests/src/Unit/PermissionsHashTest.php
@@ -67,7 +67,7 @@ class PermissionsHashTest extends UnitTestCase {
   protected function setUp() {
     parent::setUp();
 
-    new Settings(array('hash_salt' => 'test'));
+    Settings::setCreateInstance(array('hash_salt' => 'test'));
 
     // Account 1: 'administrator' and 'authenticated' roles.
     $roles_1 = array('administrator', 'authenticated');
diff --git a/core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php b/core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php
index ec2abec..25cb023 100644
--- a/core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php
+++ b/core/tests/Drupal/Tests/Core/Access/CsrfTokenGeneratorTest.php
@@ -61,7 +61,7 @@ protected function setUp() {
       'hash_salt' => $this->randomMachineName(),
     );
 
-    new Settings($settings);
+    Settings::setCreateInstance($settings);
 
     $this->generator = new CsrfTokenGenerator($this->privateKey, $this->sessionMetadata);
   }
@@ -208,7 +208,7 @@ public function providerTestInvalidParameterTypes() {
    */
   public function testGetWithNoHashSalt() {
     // Update settings with no hash salt.
-    new Settings(array());
+    Settings::setCreateInstance(array());
     $generator = new CsrfTokenGenerator($this->privateKey, $this->sessionMetadata);
     $generator->get();
   }
diff --git a/core/tests/Drupal/Tests/Core/Cache/CacheFactoryTest.php b/core/tests/Drupal/Tests/Core/Cache/CacheFactoryTest.php
index 4869bea..cf20ce7 100644
--- a/core/tests/Drupal/Tests/Core/Cache/CacheFactoryTest.php
+++ b/core/tests/Drupal/Tests/Core/Cache/CacheFactoryTest.php
@@ -25,7 +25,7 @@ class CacheFactoryTest extends UnitTestCase {
    * @covers ::get
    */
   public function testCacheFactoryWithDefaultSettings() {
-    $settings = new Settings(array());
+    $settings = Settings::setCreateInstance(array());
     $cache_factory = new CacheFactory($settings);
 
     $container = new ContainerBuilder();
@@ -51,7 +51,7 @@ public function testCacheFactoryWithDefaultSettings() {
    * @covers ::get
    */
   public function testCacheFactoryWithCustomizedDefaultBackend() {
-    $settings = new Settings(array(
+    $settings = Settings::setCreateInstance(array(
       'cache' => array(
         'default' => 'cache.backend.custom',
       ),
@@ -81,7 +81,7 @@ public function testCacheFactoryWithCustomizedDefaultBackend() {
    * @covers ::get
    */
   public function testCacheFactoryWithSpecifiedPerBinBackend() {
-    $settings = new Settings(array(
+    $settings = Settings::setCreateInstance(array(
       'cache' => array(
         'bins' => array(
           'render' => 'cache.backend.custom',
diff --git a/core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php b/core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php
index ef0a528..f988730 100644
--- a/core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php
+++ b/core/tests/Drupal/Tests/Core/PathProcessor/PathProcessorTest.php
@@ -151,7 +151,7 @@ function testProcessInbound() {
     $alias_processor = new PathProcessorAlias($alias_manager);
     $decode_processor = new PathProcessorDecode();
     $front_processor = new PathProcessorFront($config_factory_stub);
-    $language_processor = new PathProcessorLanguage($config_factory_stub, new Settings(array()), $this->languageManager, $negotiator, $current_user);
+    $language_processor = new PathProcessorLanguage($config_factory_stub, Settings::setCreateInstance(array()), $this->languageManager, $negotiator, $current_user);
 
     // First, test the processor manager with the processors in the incorrect
     // order. The alias processor will run before the language processor, meaning
diff --git a/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php b/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php
index 7404372..95e5ecd 100644
--- a/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php
+++ b/core/tests/Drupal/Tests/Core/Routing/UrlGeneratorTest.php
@@ -137,12 +137,12 @@ protected function setUp() {
 
     $config_factory_stub = $this->getConfigFactoryStub(array('system.filter' => array('protocols' => array('http', 'https'))));
 
-    $generator = new UrlGenerator($provider, $processor_manager, $this->routeProcessorManager, $config_factory_stub, new Settings(array()), NULL, $this->requestStack);
+    $generator = new UrlGenerator($provider, $processor_manager, $this->routeProcessorManager, $config_factory_stub, Settings::setCreateInstance(array()), NULL, $this->requestStack);
     $generator->setContext($context);
     $this->generator = $generator;
 
     // Second generator for mixed-mode sessions.
-    $generator = new UrlGenerator($provider, $processor_manager, $this->routeProcessorManager, $config_factory_stub, new Settings(array('mixed_mode_sessions' => TRUE)), NULL, $this->requestStack);
+    $generator = new UrlGenerator($provider, $processor_manager, $this->routeProcessorManager, $config_factory_stub, Settings::setCreateInstance(array('mixed_mode_sessions' => TRUE)), NULL, $this->requestStack);
     $generator->setContext($context);
     $this->generatorMixedMode = $generator;
   }
diff --git a/core/tests/Drupal/Tests/Core/Site/SettingsNotInitializedTest.php b/core/tests/Drupal/Tests/Core/Site/SettingsNotInitializedTest.php
new file mode 100644
index 0000000..d8f2cf7
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Site/SettingsNotInitializedTest.php
@@ -0,0 +1,53 @@
+<?php
+
+
+namespace Drupal\Tests\Core\Site;
+
+use Drupal\Core\Site\Settings\SettingsNotInitializedException;
+
+/**
+ * Tests the case where Settings::$instance is not initialized yet.
+ *
+ * @see \Drupal\Core\Site\Settings::$instance
+ *
+ * @group Site
+ */
+class SettingsNotInitializedTest extends \PHPUnit_Framework_TestCase {
+
+  /**
+   * Tests the case where Settings::$instance is not initialized.
+   *
+   * @dataProvider methodsWithExceptionProvider
+   *
+   * @param string $method
+   *   The static method to call on \Drupal::
+   * @param array $args
+   *   Arguments to pass into \Drupal::$method(..)
+   */
+  public function testSettingsNotInitializedException($method, $args = array()) {
+    try {
+      call_user_func_array(['Drupal\Core\Site\Settings', $method], $args);
+    }
+    catch (SettingsNotInitializedException $e) {
+      $this->assertEquals(
+        'Settings::$instance is not initialized yet.',
+        $e->getMessage());
+      return;
+    }
+    $this->fail("Settings::$method() should trigger an exception, if Settings::\$instance is not initialized.");
+  }
+
+  /**
+   * Data provider for one method, see "@see" below.
+   *
+   * @see testSettingsNotInitializedException()
+   */
+  public function methodsWithExceptionProvider() {
+    return array(
+      ['get', ['example_key']],
+      ['getAll'],
+      ['getHashSalt'],
+    );
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Site/SettingsTest.php b/core/tests/Drupal/Tests/Core/Site/SettingsTest.php
index f2121ed..8c404dd 100644
--- a/core/tests/Drupal/Tests/Core/Site/SettingsTest.php
+++ b/core/tests/Drupal/Tests/Core/Site/SettingsTest.php
@@ -26,7 +26,7 @@ class SettingsTest extends UnitTestCase {
   /**
    * The class under test.
    *
-   * @var \Drupal\Core\Site\Settings
+   * @var \Drupal\Core\Site\Settings\SettingsInterface
    */
   protected $settings;
 
@@ -39,7 +39,7 @@ protected function setUp(){
       'two' => '2',
       'hash_salt' => $this->randomMachineName(),
     );
-    $this->settings = new Settings($this->config);
+    $this->settings = Settings::setCreateInstance($this->config);
   }
 
   /**
@@ -66,7 +66,7 @@ public function testGetAll() {
    * @covers ::getInstance
    */
   public function testGetInstance() {
-    $singleton = $this->settings->getInstance();
+    $singleton = Settings::getInstance();
     $this->assertEquals($singleton, $this->settings);
   }
 
@@ -90,7 +90,7 @@ public function testGetHashSalt() {
    */
   public function testGetHashSaltEmpty(array $config) {
     // Re-create settings with no 'hash_salt' key.
-    $settings = new Settings($config);
+    $settings = Settings::setCreateInstance($config);
     $settings->getHashSalt();
   }
 
diff --git a/core/tests/Drupal/Tests/Core/StackMiddleware/ReverseProxyMiddlewareTest.php b/core/tests/Drupal/Tests/Core/StackMiddleware/ReverseProxyMiddlewareTest.php
index 231f833..c8a1120 100644
--- a/core/tests/Drupal/Tests/Core/StackMiddleware/ReverseProxyMiddlewareTest.php
+++ b/core/tests/Drupal/Tests/Core/StackMiddleware/ReverseProxyMiddlewareTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\Tests\Core\StackMiddleware;
 
 use Drupal\Core\Site\Settings;
+use Drupal\Core\Site\Settings\SettingsInterface;
 use Drupal\Core\StackMiddleware\ReverseProxyMiddleware;
 use Drupal\Tests\UnitTestCase;
 use Symfony\Component\HttpFoundation\Request;
@@ -35,7 +36,7 @@ public function setUp() {
    * Tests that subscriber does not act when reverse proxy is not set.
    */
   public function testNoProxy() {
-    $settings = new Settings(array());
+    $settings = Settings::setCreateInstance(array());
     $this->assertEquals(0, $settings->get('reverse_proxy'));
 
     $middleware = new ReverseProxyMiddleware($this->mockHttpKernel, $settings);
@@ -55,7 +56,7 @@ public function testNoProxy() {
    */
   public function testReverseProxyEnabled($provided_settings) {
       // Enable reverse proxy and add test values.
-      $settings = new Settings(array('reverse_proxy' => 1) + $provided_settings);
+      $settings = Settings::setCreateInstance(array('reverse_proxy' => 1) + $provided_settings);
       $this->trustedHeadersAreSet($settings);
   }
 
@@ -86,10 +87,10 @@ public function testReverseProxyEnabledProvider() {
    * \Symfony\Component\HttpFoundation\Request::setTrustedProxies() should
    * always be called when reverse proxy settings are enabled.
    *
-   * @param \Drupal\Core\Site\Settings $settings
+   * @param \Drupal\Core\Site\Settings\SettingsInterface $settings
    *   The settings object that holds reverse proxy configuration.
    */
-  protected function trustedHeadersAreSet(Settings $settings) {
+  protected function trustedHeadersAreSet(SettingsInterface $settings) {
     $middleware = new ReverseProxyMiddleware($this->mockHttpKernel, $settings);
     $request = new Request();
 
