diff --git a/core/core.services.yml b/core/core.services.yml
index a6663b4..e2b0a4a 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -164,6 +164,7 @@ services:
   cron:
     class: Drupal\Core\Cron
     arguments: ['@module_handler', '@lock', '@queue', '@state', '@account_switcher', '@logger.channel.cron', '@plugin.manager.queue_worker']
+    lazy: true
   diff.formatter:
     class: Drupal\Core\Diff\DiffFormatter
     arguments: ['@config.factory']
diff --git a/core/lib/Drupal/Component/ProxyBuilder/ProxyBuilder.php b/core/lib/Drupal/Component/ProxyBuilder/ProxyBuilder.php
new file mode 100644
index 0000000..78c4dcf
--- /dev/null
+++ b/core/lib/Drupal/Component/ProxyBuilder/ProxyBuilder.php
@@ -0,0 +1,217 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\ProxyBuilder\ProxyBuilder.
+ */
+
+namespace Drupal\Component\ProxyBuilder;
+
+/**
+ * Generates the string representation of the proxy service.
+ */
+class ProxyBuilder {
+
+  /**
+   * Generates the used proxy class name from a given class name.
+   *
+   * @param string $class_name
+   *   The class name of the actual service.
+   *
+   * @return string
+   *   The class name of the proxy.
+   */
+  public function buildProxyClassName($class_name) {
+    return str_replace('\\', '_', $class_name) . '_Proxy';
+  }
+
+  /**
+   * Builds a proxy class string.
+   *
+   * @param string $class_name
+   *   The class name of the actual service.
+   *
+   * @return string
+   *   The full string with namespace class and methods.
+   */
+  public function build($class_name) {
+    $reflection = new \ReflectionClass($class_name);
+
+    // The actual class;
+    $output = '';
+    $class_start = 'class ' . $this->buildProxyClassName($class_name);
+
+    if ($interfaces = $reflection->getInterfaceNames()) {
+      foreach ($interfaces as &$interface) {
+        $interface = '\\' . $interface;
+      }
+      $output .= ' implements ' . implode(', ', $interfaces);
+    }
+
+    $output .= " {\n";
+
+    // Add the variables.
+    $output .= "\n/**
+ * @var string
+ */
+protected \$serviceId;
+
+/**
+ * @var \\$class_name
+ */
+protected \$service;\n\n";
+
+    // Add all the methods.
+    $methods = [];
+    $methods[] = $this->buildConstructorMethod();
+    $methods[] = $this->buildLazyLoadItselfMethod();
+
+    // Add all the methods of the proxied service.
+    $reflection_methods = $reflection->getMethods();
+
+    foreach ($reflection_methods as $method) {
+      if ($method->getName() === '__construct') {
+        continue;
+      }
+
+      if ($method->isPublic()) {
+        $methods[] = $this->buildMethod($method) . "\n";
+      }
+    }
+
+    $output .= implode("\n", $methods);
+
+    // Intend the output.
+    $output = implode("\n", array_map(function($value) {
+      if ($value === '') {
+        return $value;
+      }
+      return "  $value";
+    }, explode("\n", $output)));
+
+    return $class_start . $output . "\n}\n";
+  }
+
+  /**
+   * Generates the string for the method which loads the actual service.
+   *
+   * @return string
+   */
+  protected function buildLazyLoadItselfMethod() {
+    $output = "protected function lazyLoadItself() {
+  if (!isset(\$this->service)) {
+    \$method_name = 'get' . Container::camelize(\$this->serviceId) . 'Service';
+    \$this->service = \\Drupal::getContainer()->\$method_name(FALSE);
+  }
+
+  return \$this->service;
+}
+";
+
+    return $output;
+  }
+
+  /**
+   * Generates the string representation of a single method: signature, body.
+   *
+   * @param \ReflectionMethod $reflection_method
+   *   A reflection method for the method.
+   *
+   * @return string
+   */
+  protected function buildMethod(\ReflectionMethod $reflection_method) {
+
+    $parameters = [];
+    foreach ($reflection_method->getParameters() as $parameter) {
+      $parameters[] = $this->buildParameter($parameter);
+    }
+
+    $function_name = $reflection_method->getName();
+
+    $signature_line = 'public function ' . $function_name . '(';
+    $signature_line .= implode(', ', $parameters);
+    $signature_line .= ')';
+
+    $output = $signature_line . ' {' . "\n";
+
+    $output .= $this->buildMethodBody($reflection_method);
+
+    $output .= "\n". '}';
+    return $output;
+  }
+
+  /**
+   * Builds a string for a single parameter of a method.
+   *
+   * @param \ReflectionParameter $parameter
+   *   A reflection object of the parameter.
+   *
+   * @return string
+   */
+  protected function buildParameter(\ReflectionParameter $parameter) {
+    $parameter_string = '';
+
+    if ($parameter->isArray()) {
+      $parameter_string .= 'array ';
+    }
+    elseif ($parameter->isCallable()) {
+      $parameter_string .= 'callable ';
+    }
+    elseif ($class = $parameter->getClass()) {
+      $parameter_string .= '\\' . $class->getName() . ' ';
+    }
+
+    if ($parameter->isPassedByReference()) {
+      $parameter_string .= '&';
+    }
+
+    $parameter_string .= '$' . $parameter->getName();
+
+    if ($parameter->isDefaultValueAvailable()) {
+      $parameter_string .= ' = ';
+      $parameter_string .= var_export($parameter->getDefaultValue(), TRUE);
+    }
+
+    return $parameter_string;
+  }
+
+  /**
+   * Builds the body of a wrapped method.
+   *
+   * @param \ReflectionMethod $reflection_method
+   *   A reflection method for the method.
+   *
+   * @return string
+   */
+  protected function buildMethodBody(\ReflectionMethod $reflection_method) {
+    $output = '';
+
+    $function_name = $reflection_method->getName();
+
+    $output .= '  return $this->lazyLoadItself()->' . $function_name . '(';
+
+    // Add parameters;
+    $parameters = [];
+    foreach ($reflection_method->getParameters() as $parameter) {
+      $parameters[] = '$' . $parameter->getName();
+    }
+
+    $output .= implode(', ', $parameters) . ');';
+
+    return $output;
+  }
+
+  /**
+   * Builds the constructor used to inject the actual service ID.
+   *
+   * @return string
+   */
+  protected function buildConstructorMethod() {
+    $output = 'public function __construct($service_id) {
+  $this->serviceId = $service_id;
+}
+';
+
+    return $output;
+  }
+}
diff --git a/core/lib/Drupal/Component/ProxyBuilder/ProxyDumper.php b/core/lib/Drupal/Component/ProxyBuilder/ProxyDumper.php
new file mode 100644
index 0000000..07e30ee
--- /dev/null
+++ b/core/lib/Drupal/Component/ProxyBuilder/ProxyDumper.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\ProxyBuilder\ProxyDumper.
+ */
+
+namespace Drupal\Component\ProxyBuilder;
+
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface;
+
+/**
+ * Dumps the proxy service into the dumped PHP container file.
+ */
+class ProxyDumper implements DumperInterface {
+
+  /**
+   * The proxy builder.
+   *
+   * @var \Drupal\Component\ProxyBuilder\ProxyBuilder
+   */
+  protected $builder;
+
+  public function __construct(ProxyBuilder $builder) {
+    $this->builder = $builder;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isProxyCandidate(Definition $definition) {
+    return $definition->isLazy() && ($class = $definition->getClass()) && class_exists($class);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getProxyFactoryCode(Definition $definition, $id) {
+    $id = var_export($id, TRUE);
+    // Note: the specific get method is called initially with $lazyLoad=TRUE;
+    // When you want to retrieve the actual service, the code generated in
+    // ProxyBuilder calls the method with lazy loading disabled.
+    $output = "        if (\$lazyLoad) {\n";
+    $output .= "            return \$this->services[$id] = new " . $this->builder->buildProxyClassName($definition->getClass()) . '(' . $id . ");\n";
+    $output .= "        }\n";
+
+    return $output;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getProxyCode(Definition $definition) {
+    return $this->builder->build($definition->getClass());
+  }
+
+}
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index 2c58ccc..88e317a 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\Core;
 
+use Drupal\Component\ProxyBuilder\ProxyBuilder;
+use Drupal\Component\ProxyBuilder\ProxyDumper;
 use Drupal\Component\Utility\Crypt;
 use Drupal\Component\Utility\Timer;
 use Drupal\Component\Utility\Unicode;
@@ -1146,6 +1148,7 @@ protected function dumpDrupalContainer(ContainerBuilder $container, $baseClass)
     }
     // Cache the container.
     $dumper = new PhpDumper($container);
+    $dumper->setProxyDumper(new ProxyDumper(new ProxyBuilder()));
     $class = $this->getClassName();
     $content = $dumper->dump(array('class' => $class, 'base_class' => $baseClass));
     return $this->storage()->save($class . '.php', $content);
diff --git a/core/tests/Drupal/Tests/Component/ProxyBuilder/ProxyBuilderTest.php b/core/tests/Drupal/Tests/Component/ProxyBuilder/ProxyBuilderTest.php
new file mode 100644
index 0000000..e284902
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/ProxyBuilder/ProxyBuilderTest.php
@@ -0,0 +1,253 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Component\ProxyBuilder\ProxyBuilderTest.
+ */
+
+namespace Drupal\Tests\Component\ProxyBuilder;
+
+use Drupal\Component\ProxyBuilder\ProxyBuilder;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * @coversDefaultClass \Drupal\Component\ProxyBuilder\ProxyBuilder
+ * @group proxy_builder
+ */
+class ProxyBuilderTest extends UnitTestCase {
+
+  /**
+   * The tested proxy builder.
+   *
+   * @var \Drupal\Component\ProxyBuilder\ProxyBuilder
+   */
+  protected $proxyBuilder;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->proxyBuilder = new ProxyBuilder();
+  }
+
+  /**
+   * @covers ::buildProxyClassName()
+   */
+  public function testBuildProxyClassName() {
+    $class_name = $this->proxyBuilder->buildProxyClassName('Drupal\Tests\Component\ProxyBuilder\TestServiceNoMethod');
+    $this->assertEquals('Drupal_Tests_Component_ProxyBuilder_TestServiceNoMethod_Proxy', $class_name);
+  }
+
+  /**
+   * Tests the basic methods like the constructor and the lazyLoadItself method.
+   *
+   * @covers ::build()
+   * @covers ::buildConstructorMethod()
+   * @covers ::buildLazyLoadItselfMethod()
+   */
+  public function testBuildNoMethod() {
+    $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceNoMethod';
+
+    $result = $this->proxyBuilder->build($class);
+    $this->assertEquals($this->buildExpectedClass($class, ''), $result);
+  }
+
+  /**
+   * @covers ::buildMethod()
+   * @covers ::buildMethodBody()
+   */
+  public function testBuildSimpleMethod() {
+    $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceSimpleMethod';
+
+    $result = $this->proxyBuilder->build($class);
+
+    $method_body = '
+  public function method() {
+    return $this->lazyLoadItself()->method();
+  }
+';
+    $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
+  }
+
+  /**
+   * @covers ::buildMethod()
+   * @covers ::buildParameter()
+   * @covers ::buildMethodBody()
+   */
+  public function testBuildMethodWithParameter() {
+    $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceMethodWithParameter';
+
+    $result = $this->proxyBuilder->build($class);
+
+    $method_body = '
+  public function methodWithParameter($parameter) {
+    return $this->lazyLoadItself()->methodWithParameter($parameter);
+  }
+';
+    $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
+  }
+
+  /**
+   * @covers ::buildMethod()
+   * @covers ::buildParameter()
+   * @covers ::buildMethodBody()
+   */
+  public function testBuildComplexMethod() {
+    $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceComplexMethod';
+
+    $result = $this->proxyBuilder->build($class);
+
+    // @todo Solve the silly linebreak for array()
+    $method_body = '
+  public function complexMethod($parameter, callable $function, \Drupal\Tests\Component\ProxyBuilder\TestServiceNoMethod $test_service = NULL, array &$elements = array (
+  )) {
+    return $this->lazyLoadItself()->complexMethod($parameter, $function, $test_service, $elements);
+  }
+';
+    $this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
+  }
+
+  /**
+   * @covers ::buildMethod()
+   * @covers ::buildParameter()
+   * @covers ::buildMethodBody()
+   */
+  public function testBuildWithInterface() {
+    $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceWithInterface';
+
+    $result = $this->proxyBuilder->build($class);
+
+    // @todo Solve the silly linebreak for array()
+    $method_body = '
+  public function testMethod($parameter) {
+    return $this->lazyLoadItself()->testMethod($parameter);
+  }
+';
+
+    $interface_string = '  implements \Drupal\Tests\Component\ProxyBuilder\TestInterface';
+    $this->assertEquals($this->buildExpectedClass($class, $method_body, $interface_string), $result);
+  }
+
+  /**
+   * @covers ::buildMethod()
+   * @covers ::buildParameter()
+   * @covers ::buildMethodBody()
+   */
+  public function testBuildWithProtectedAndPrivateMethod() {
+    $class = 'Drupal\Tests\Component\ProxyBuilder\TestServiceWithProtectedMethods';
+
+    $result = $this->proxyBuilder->build($class);
+
+    // @todo Solve the silly linebreak for array()
+    $method_body = '
+  public function testMethod($parameter) {
+    return $this->lazyLoadItself()->testMethod($parameter);
+  }
+';
+
+$this->assertEquals($this->buildExpectedClass($class, $method_body), $result);
+  }
+
+  /**
+   * Constructs the expected class output.
+   *
+   * @param string $expected_methods_body
+   *   The expected body of decorated methods.
+   *
+   * @return string
+   *   The code of the entire proxy.
+   */
+  protected function buildExpectedClass($class, $expected_methods_body, $interface_string = ' ') {
+    $proxy_class = $this->proxyBuilder->buildProxyClassName($class);
+    $expected_string = "class $proxy_class $interface_string {
+
+  /**
+   * @var string
+   */
+  protected \$serviceId;
+
+  /**
+   * @var \\$class
+   */
+  protected \$service;
+
+  public function __construct(\$service_id) {
+    \$this->serviceId = \$service_id;
+  }
+
+  protected function lazyLoadItself() {
+    if (!isset(\$this->service)) {
+      \$method_name = 'get' . Container::camelize(\$this->serviceId) . 'Service';
+      \$this->service = \\Drupal::getContainer()->\$method_name(FALSE);
+    }
+
+    return \$this->service;
+  }
+$expected_methods_body
+}
+";
+
+    return $expected_string;
+  }
+
+}
+
+class TestServiceNoMethod {
+
+}
+
+class TestServiceSimpleMethod {
+
+  public function method() {
+
+  }
+
+}
+
+class TestServiceMethodWithParameter {
+
+  public function methodWithParameter($parameter) {
+
+  }
+
+}
+
+class TestServiceComplexMethod {
+
+  public function complexMethod($parameter, callable $function, TestServiceNoMethod $test_service = NULL, array &$elements = array()) {
+
+  }
+
+}
+
+interface TestInterface {
+
+  public function testMethod($parameter);
+
+}
+
+class TestServiceWithInterface implements TestInterface {
+
+  public function testMethod($parameter) {
+
+  }
+
+}
+
+class TestServiceWithProtectedMethods {
+
+  public function testMethod($parameter) {
+
+  }
+
+  protected function protectedMethod($parameter) {
+
+  }
+
+  protected function privateMethod($parameter) {
+
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Component/ProxyBuilder/ProxyDumperTest.php b/core/tests/Drupal/Tests/Component/ProxyBuilder/ProxyDumperTest.php
new file mode 100644
index 0000000..70b6a7b
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/ProxyBuilder/ProxyDumperTest.php
@@ -0,0 +1,104 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Component\ProxyBuilder\ProxyDumperTest.
+ */
+
+namespace Drupal\Tests\Component\ProxyBuilder;
+
+use Drupal\Component\ProxyBuilder\ProxyDumper;
+use Drupal\Tests\UnitTestCase;
+use Symfony\Component\DependencyInjection\Definition;
+
+/**
+ * @coversDefaultClass \Drupal\Component\ProxyBuilder\ProxyDumper
+ * @group proxy_builder
+ */
+class ProxyDumperTest extends UnitTestCase {
+
+  /**
+   * The mocked proxy builder.
+   *
+   * @var \Drupal\Component\ProxyBuilder\ProxyBuilder|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $proxyBuilder;
+
+  /**
+   * The tested proxy dumper.
+   *
+   * @var \Drupal\Component\ProxyBuilder\ProxyDumper
+   */
+  protected $proxyDumper;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->proxyBuilder = $this->getMockBuilder('Drupal\Component\ProxyBuilder\ProxyBuilder')
+      ->disableOriginalConstructor()
+      ->setMethods(['build'])
+      ->getMock();
+    $this->proxyDumper = new ProxyDumper($this->proxyBuilder);
+  }
+
+  /**
+   * @dataProvider providerTestIsProxyCandidate
+   * @covers ::isProxyCandidate()
+   */
+  public function testIsProxyCandidate(Definition $definition, $expected) {
+    $this->assertSame($expected, $this->proxyDumper->isProxyCandidate($definition));
+  }
+
+  public function providerTestIsProxyCandidate() {
+    // Not lazy service.
+    $data = [];
+    $definition = new Definition('Drupal\Tests\Component\ProxyBuilder\TestService');
+    $data[] = [$definition, FALSE];
+    // Not existing service.
+    $definition = new Definition('Drupal\Tests\Component\ProxyBuilder\TestNotExistingService');
+    $definition->setLazy(TRUE);
+    $data[] = [$definition, FALSE];
+    // Existing and lazy service.
+    $definition = new Definition('Drupal\Tests\Component\ProxyBuilder\TestService');
+    $definition->setLazy(TRUE);
+    $data[] = [$definition, TRUE];
+    // Existing and lazy service.
+
+    return $data;
+  }
+
+  public function testGetProxyFactoryCode() {
+    $definition = new Definition('Drupal\Tests\Component\ProxyBuilder\TestService');
+    $definition->setLazy(TRUE);
+
+    $result = $this->proxyDumper->getProxyFactoryCode($definition, 'test_service');
+
+    $this->assertEquals(
+"        if (\$lazyLoad) {
+            return \$this->services['test_service'] = new Drupal_Tests_Component_ProxyBuilder_TestService_Proxy('test_service');
+        }
+", $result);
+  }
+
+  public function testGetProxyCode() {
+    $definition = new Definition('Drupal\Tests\Component\ProxyBuilder\TestService');
+    $definition->setLazy(TRUE);
+
+    $class = 'class Drupal_Tests_Component_ProxyBuilder_TestService_Proxy {}';
+    $this->proxyBuilder->expects($this->once())
+      ->method('build')
+      ->with('Drupal\Tests\Component\ProxyBuilder\TestService')
+      ->willReturn($class);
+
+    $result = $this->proxyDumper->getProxyCode($definition);
+    $this->assertEquals($class, $result);
+  }
+
+}
+
+class TestService {
+
+}
