Чем отличается java 8 от java 11
Перейти к содержимому

Чем отличается java 8 от java 11

  • автор:

What is the Difference between Java 8 v/s Java 11?

Java 8 is a version of Java that was available to the public in March 2014. Java 11 was a version of Java made publicly available on September 25, 2018. It provides Long Term Support (LTS) with new and updated features.

Java 11 supports local variable var for lambda expressions, pattern recognition, ChaCha20, and ChaCha20-Poly1305 Cipher cryptographic algorithms. Deprecations of Java Applet and Java Web Start were in the later version. Java FX introduced in Java 8 got removed from Java 11. Let us dive deep into the features of the latest LTS version.

The new features in Java version 8

In Java version 8, oracle switched away from the Binary code license. This JDK version gets licensed under GNU General Public License version 2 .

It provides a commercial license named Oracle Technology Network License Agreement (ONTLA) to Oracle technology and services.

Several significant changes come along with major transformations in Java 8. Let’s have a look at a few of them.

  • It supports Lambda expressions that add methods to interfaces without impacting the existing implementations.
  • Functional style operations get enabled by the support of lambda expressions on the stream of elements such as MapReduce.
  • It provides a Date and Time API that supports time concepts like time, date, time-zone, and instant time. It also defines a calender API for the Java platform.
  • Implementation of a Javascript Engine named Nashorn gets integrated into the JDK. It is made available on all Java applications using the javax.script API or a new command-line tool.
  • It makes use of the arithmetic defined on Unsigned integers.
  • Java 8 supports the enhancement of command line launchers that support the launch of JavaFX applications.

The new features introduced in Java version 11

Java 11 has brought numerous new features with its release. Let’s have a look at some of them.

  • It introduces nest-based access control aligning with the nested types in Java programming language.
  • It introduces a No-op garbage collector named epsilon to handle memory allocation without any actual memory reclamation mechanism.
  • Formal parameters of implicit lambda expressions get replaced by the local variable, var.
  • It upgraded the existing APIs according to the 10th version of the Unicode standard.
  • It provides ChaCha20 and ChaCha20-Poly1305 Cipher cryptographic algorithms implemented in the SunJCE provider.

Deprecations and Other Changes

  • The support of Java Applet ended in March 2019 as Java developers migrated from plugin-free web-start technologies, which resulted in its deprecation in Java SE 9 and removal in Java SE 11.
  • Oracle deprecated Java Web Start in Java SE 11 in March 2018 to transition to alternative deployment technologies for developers.
  • Oracle will remove JavaFX from JDK 11 as the OpenFX community will now be responsible for the growth of the technology.

Java 8 v/s Java 11: Key Differences

We have already discussed key features in Java 8 and Java 11. Let us look at the key differences in both versions of Java.

Java 8 Java 11
Java version 8 supports the Applet Viewer tool. Applet API has been deprecated from Java 11 as it does not support Java browser plugins.
Java 8 does not support pattern recognition. Java 11 supports pattern recognition by using methods such as asMatchPredicate().
Java 8 contained methods such as Files.lines() and Files.write() to return the content of a file and write text to a file. Java 11 contained methods such as writeString(), readString(), and isSameFile() to perform read, write and search operations on the file.
Oracle JDK in Java 8 contains the JMC and JavaFX tools. Oracle JDK in Java 11 removed JMC and JavaFX.

Several Reasons Why One Should Upgrade from Java 8 to Java 11

There are many reasons why we should upgrade from Java version 8 to Java 11. Here’s a list of a few of them that will help you decide better.

  • Applications in the later versions of Java 8 are faster and more secure than before.
  • Garbage collection has improved due to garbage collectors like ZGC and Epsilon.
  • Including the var keyword in the language made the code and development process simple and user-friendly.

The Migration Process

You can migrate from Java 8 to Java 11 using the following options:

  • Migrating from Java 8 to Java 11 with commercial restrictions
  • Migrating from Java 8 to Java 11 OpenJDK 11 with free distributions

You can change the Java version in your pom.xml file with the following code: 1.8 to 11

Here, in Java version 1.8, 8 is the product version number, and its developer version is 1.8 . Both of these numbers refer to Java JDK 8.

Learn More

You can learn more about related topics using articles on Scaler Topics.

  • Operators in Java
  • Primitive Data Types in Java
  • Methods in Java
  • OOPs concept in Java
  • Exception Handling in Java


  • Java 8 is a version of Java released in March 2014, while Java 11 is a version of Java released on September 25, 2018.
  • Java 11 has new and updated features with the latest LTS version.
  • Java 11 has a local variable var to replace the lambda expressions in Java 8.
  • Java 11 removed Applet API, which got deprecated in Java 9 for security reasons.
  • Oracle deprecated Java web start in Java 11 to find alternative deployment technologies for developers.
  • Oracle removed JavaFX from Java 11 as the OpenFX community took responsibility for the growth of the technology.
  • Java 11 has improved garbage collection due to garbage collectors like ZGC and Epsilon.
  • Thus, applications in Java 11 are faster and more secure than in Java 8.

Java 8 v/s Java 11


Java 11 was publicly available on 25 September 2018 in the market. It is an open-source reference implementation of Java SE platform version 11. Java 11 was released after four years of releasing Java 8.

Java 11 comes with new features to provide more functionality. Below are the features which are added in the four and a half years in between these two versions.

Java 8 v/s Java 11


The Modularity feature is not available in Java 8. It is one of the biggest changes that have been added in Java 9. By using modularity, we can split our programs or applications into different modules. Modularity allows us to test our application easily and also managing access to what parts of our code are public-facing. We can compile our code without compiling the file by simply placed it into the module having no name. It behaves in the same way as the Java 8 compile code.

—release flag

It is a very simple combination of -target and -source that allows us -bootclasspath for compiling at the older version. The -release 8 is an example that we need to compile at a Java 8 level.

Multi-jar releases

It is one of the features which is added in Java 11. Multi-jar provides a way to still the code with the latest features of Java 11 while maintaining support and functionality for Java 8 clients.

Var keyword

In Java 10, the var keyword was introduced, which improved in Java 11. The var keyword is a developer-friendly keyword that helps us to reduce the boilerplate coding. The type of infection prevents repeating the same text over and over again by affecting only local variables.

Version String Schema

It is another change between Java 8 and Java 11 which defines how the version strings should be formatted. A new schema introduces for the versions. The schema looks something like as:

Let’s understand the difference between both versions of Java on the basis of deprecations. These are the following deprecations which are done in between Java 8 and Java 11.

  1. In Java 11, the support for Java browser plugins is removed and due to which the Applet API has been deprecated.
    Note: it is only depreciated, not yet removed.
  2. CMS, i.e., Concurrent Mark Sweep Garbage Collector, is depreciated and not supported now. The reason for removing it is to reduce the maintenance burden of the GCC base.
  3. With the rapid changes to the ECMAScript API, it has been removed due to the amount of maintenance of the Nashorn JavaScript engine.
  4. In Java 9, the compression scheme is improved, and after this improvement, the Pack200 tools and APIs have been removed.
  5. Java EE module has been removed due to overlap with the Java EE platform specification.
  6. The CORBA module has been removed due to evolving independently of Java SE.

Difference between Java 8 and Java 11

These are the following differences between Java 8 and Java 11:

Sr. No. Java 8 Java 11
1. The appletviewer tool is available in Java 8. The appletviewer tool is not available in Java 11.
2. Java 8 has the AWTUtilities class, which we didn’t recommend you to use because it can break any program depending on it. In Java 11, the AWTUtilities class is not available.
3. It has fewer string methods. Several new methods of String such as isBlank(), lines(),repeat(n), stripLeading(), stripTrailing(), and strip() are introduce.
4. No special variables are used for lambda parameters. Java 11 allows us to use var variables to be used in lambda expressions.
5. Java Deployment Technologies are available in Java 8. Java Deployment Technologies are removed in Java 11.
6. JMC and JavaFX are available in the Oracle JDK. JMC and JavaFX are removed from the Oracle JDK in Java 11.
7. There are no suitable methods to work with the file. In Java 11, there are various methods, such as writeString(), readString(), and isSameFile() which help us to perform several operations on file.
8. Pattern recognizing is not possible. Pattern recognizing is possible with the help of the asMatchPredicate() method.

Next Topic Login Form Java


For Videos Join Our Youtube Channel: Join Now


  • Send your Feedback to [email protected]

Чем отличается java 8 от java 11

С установленным JDK вашего любимого поставщика (и, возможно, с LTS в заднем кармане) вы хотите чтобы ваш проект на Java 8 заработал на Java 11. Мы знаем, что вы готовы к апгрейду, но прежде, чем мы пойдем дальше, необходимо обсудить, как подготовиться к переходу наилучшим образом.

Быстрый или длительный переход?

Перед началом перехода с Java 8 на Java 11 или на более позднюю версию, первый вопрос, на который необходимо ответить — можете ли вы реализовать переход одним махом или вам необходимо провести его в течение длительного промежутка времени.

Если миграция обещает быть быстрой или к проекту могут быть предъявлены новые требования по использованию версии Java, используйте новую версию Java сразу для всего процесса сборки, включая компиляцию. Осталось только исправить проблемы, которые при этом могут возникнуть.

Если же вы не хотите изменять требования к минимальной версии Java или ваш проект слишком большой, мы рекомендуем следующий подход:

  • Не создавайте отдельную долговременную ветку для перехода — вместо этого делайте это в регулярной ветке развития. Таким образом, вы не столкнетесь с конфликтами при слиянии и можете быть уверены, что изменения ваших коллег также построены на Java 11.
  • Настройте ваш сервер непрерывной интеграции для запуска сборок проекта как в своей общей конфигурации, так и на Java 11.
  • Изучите, как ваша система сборки может поддерживать различные конфигурации, зависящие от версии Java (в Maven для этого используются профайлы). Таким образом, вы можете сохранить старую версию сборки, добавив одновременно конфигурацию, которая использует новую версию.
  • Постарайтесь сократить изменения в конфигурации, зависящие от версии Java до минимума.

Таким образом, вы можете гарантировать, что ваш проект работает и на Java 8 и на Java 11 (или более поздней версии). Если вы захотите работать с двумя (или более) версиями Java, то сможете быстро переключать профайлы и работать с ними. А когда вы совсем перестанете использовать Java 8, то не забудьте объединить версии конфигурации, чтобы уменьшить сложность проекта.

Делаем общий апгрейд

Первое правило перехода на Java 11 — обновить все: вашу IDE, систему сборки, ее плагины и, самое главное, ваши зависимости. Вам не обязательно делать все эти обновления заранее, но если вы это можете, то вы должны так сделать — это, скорее всего, поможет вам преодолеть некоторые препятствия, относительно которых вы останетесь в блаженном неведении.

Ниже приведены необходимые минимальные версии для некоторых приложений:

Некоторые зависимости, которые вы должны отслеживать (а также версии, которые, как известно, работают на Java 11):

  • Все, что использует для работы байт-код, например ASM (7.0), Byte Buddy (1.9.0), cglib (3.2.8) или Javassist (3.23.1-GA). Начиная с Java 9, модификации байт-кода происходят каждые шесть месяцев, поэтому вам придется регулярно обновлять такие библиотеки.
  • Все, что использует то, что работает с байт-кодом, например Spring (5.1), Hibernate (неизвестно), Mockito (2.20.0) и многие, многие другие проекты.

Второй совет слишком общий и не очень-то помогает, но это печальная правда: многие мощные проекты работают с байт-кодом под капотом. Это помогает развить подход к выявлению проблем, связанных с этим.

Вот некоторые советы — обращайте внимание в логах на:

  • трассировки стеков, которые заканчиваются вызовом библиотек, использующих байт-коды;
  • ошибки или предупреждения, которые жалуются на уровень байт-кода;
  • ошибки или предупреждения, которые бормочут о «unknown (constant pool) entries»;

Если вы не обновились заранее, то обновление библиотек и фреймворков все равно будет первым действием, которое вы предпримите, столкнувшись с проблемой с каким-либо конкретным инструментом или зависимостью. В любом случае, вы можете иногда сталкиваться с проблемами, даже если ваши зависимости были обновлены. В этом случае взгляните на точный артефакт, вызывающий проблему — скорее всего, это транзитивная зависимость, и в этом случае вы должны изучить ее отдельно.

Например, для более старой версией Hibernate необходимо было обновить Javassist для работы с Java 11:

  org.hibernate hibernate-core 5.2.12.Final   org.javassist javassist 3.23.1-GA  

Аналогично, при использовании устаревшей версии Maven-плагина 3.7.0 для компиляции, необходимо было обновление его зависимости от ASM:

  org.apache.maven.plugins maven-compiler-plugin 3.7.0 $   org.ow2.asm asm 6.2    

К сожалению, не у всех, используемых в вашем проекте библиотек, поддержка может находиться в хорошем состоянии и даже, возможно, что она прекращена. В этом случае вам нужно искать альтернативы. Примерами могут являтся FindBugs (вместо этого используйте SpotBugs), Log4j 1 (используйте Log4J 2) и Cobertura (используйте JaCoCo).

Однако, если проблема кроется в вашем собственном коде или такие обновления / замены не помогают или невозможны, тогда имеет смысл заняться углубленным ее изучением.

Причины перехода на Java 11 и более

Вопрос заключается не в том, следует ли перейти на Java 11 или более позднюю версию, а когда. В течение следующих нескольких лет Java 8 больше не будет поддерживаться, и пользователям придется перейти на Java 11 или более поздней версии. Мы уверены, что переход на Java 11 дает весомые преимущества, и рекомендуем всем разработчикам выполнить его как можно скорее.

После выхода Java 8 было добавлено много новых функций и улучшений. В API внесены существенные дополнения и изменения, а также улучшены такие характеристики, как скорость запуска, производительность и потребление памяти.

Переход на Java 11

Переход на Java 11 можно выполнять поэтапно. Для работы с Java 11 вам не нужно использовать в коде специальные модули Java. Java 11 можно использовать для запуска кода, который был разработан и скомпилирован в JDK 8. Но при этом могут возникать некоторые проблемы, которые преимущественно связаны с устаревшими API, загрузчиками классов и отражениями.

Обобщенное описание отличий между Java 8 и 11

В этом разделе не перечисляются все изменения, внесенные в Java версии 9 [1], 10 [2], и 11 [3]. Выделены лишь те из них, которые заметно влияют на эффективность, диагностику и производительность.

Модули [4]

Модули устраняют проблемы с конфигурацией и инкапсуляцией, которые трудно отслеживать в крупномасштабных приложениях на основе classpath. Модуль — это самоописывающая коллекция классов и интерфейсов Java со всеми связанными ресурсами.

Модули позволяют настраивать конфигурации среды выполнения, которые содержат только необходимые для приложения компоненты. Это помогает сократить потребление памяти, позволяя приложению использовать статическое связывание с jlink в пользовательской среде выполнения для развертывания. Сниженное потребление памяти особенно полезно при использовании архитектуры микрослужб.

На внутреннем уровне виртуальная машина Java может применять модули для повышения эффективности загрузки классов. Благодаря этому среда выполнения будет меньше, легче и быстрее. Методы оптимизации, которые виртуальная машина Java использует для повышения производительности, могут оказаться более эффективными, так как модули кодируют компоненты, требуемые для класса.

Модули помогают программистам обеспечить строгую инкапсуляцию, так как требуют явного объявления экспортируемых модулем пакетов и необходимых компонентов, а также ограничивают отражающий доступ. Такой уровень инкапсуляции делает приложение более надежным и простым в обслуживании.

В приложении можно как и прежде использовать classpath. При этом вам не нужно переходить на использование модулей работы с Java 11.

Профилирование и диагностика

Летчик Java [5]

Java Flight Recorder собирает данные диагностики и профилирования из запущенного приложения Java. Java Flight Recorder практически не влияет на работу приложения Java. Собранные данные потом можно проанализировать с помощью Java Mission Control или других средств. В Java 8 Java Flight Recorder и Java Mission Control предоставлялись на коммерческой основе, а в Java 11 они включены как компоненты с открытым кодом.

Управление миссиями Java [6]

Java Mission Control (JMC) предоставляет графическое отображение данных, собранных Java Flight Recorder (JFR) и открытый код в Java 11. Помимо общих сведений о работающем приложении JMC позволяет пользователю детализировать данные. Java Flight Recorder и Java Mission Control можно использовать для диагностики проблем, возникающих во время выполнения, включая утечки памяти, затраты на сборку мусора, горячие методы, узкие места и блокирующие операции ввода-вывода.

Единое ведение журнала [7]

В Java 11 организована централизованная система ведения журналов для всех компонентов виртуальной машины Java. Эта система позволяет пользователю выбирать компоненты и уровни детализации для регистрации. Такое детализированное ведение журналов полезно при анализе причин сбоев виртуальной машины Java и диагностики проблем с производительностью в рабочей среде.

Профилирование кучи с низкими затратами [8]

В виртуальную машину Java добавлен новый API, который предназначен для выборки выделений памяти в куче Java. Эта выборка создает низкую нагрузку и ее можно не отключать. Хотя выделение кучи можно отслеживать с помощью Java Flight Recorder, используемый метод выборки работает только для выделений. Кроме того, эта реализация может упускать выделения памяти. При этом выборка кучи в Java 11 предоставляет сведения как об активных, так и о неработающих объектах.

Поставщики средств наблюдения за производительностью приложений уже применяют эту новую функцию, и инженерная группа Java оценивает возможность объединить ее со средствами мониторинга производительности Azure.

StackWalker [9]

Получение моментального снимка стека в текущем потоке будет очень полезным при ведении журналов. Основная проблема заключается в том, чтобы выбрать объем трассировки стека для записи в журнал, а также принять решение о записи трассировки стека. Например, вам нужно отслеживать трассировку стека только для определенного исключения в одном методе. Класс StackWalker (добавлен в Java 9) предоставляет моментальный снимок стека и несколько методов, которые позволяют программисту контролировать использование трассировки стека.

Сборка мусора [10]

В Java 11 доступны следующие сборщики мусора: последовательные, параллельные, Garbage-First и Epsilon. По умолчанию в Java 11 используется сборщик мусора G1GC (Garbage First Garbage Collector).

Остальные здесь упоминаются для полноты информации. Сборщик мусора ZGC (Z Garbage Collector) нацелен на параллельное выполнение с низкой задержкой — по возможности не более 10 мс. ZGC используется в Java 11 в качестве экспериментальной функции. Сборщик мусора Shenandoah рассчитан на краткую приостановку, которой он добивается за счет выполнения большего количества сборок мусора параллельно с запущенной программой Java. Shenandoah предоставляется в качестве экспериментальной функции в Java 12, но существуют реализации с обратной совместимостью с Java 11. Доступен также сборщик CMS (Concurrent Mark and Sweep), но, начиная с версии Java 9, он объявлен нерекомендуемым.

В виртуальной машине Java по умолчанию назначается оптимальный сборщик мусора для усредненного сценария использования. Эти и другие параметры по умолчанию для сборки мусора иногда приходится изменять, чтобы добиться оптимальной пропускной способности или задержки в соответствии с требованиями приложения. Для правильной настройки сборщика мусора нужно хорошо разбираться в принципах его работы. В этом вам может помочь группа инженеров Microsoft Java.


По умолчанию в Java 11 используется сборщик мусора G1 (G1 Garbage Collector). Задача G1GC — найти баланс между задержкой и пропускной способностью. Сборщик мусора G1 пытается достичь высокой пропускной способности, с высокой вероятностью обеспечивая заданное значение приостановки. G1GC предназначен для предотвращения полных коллекций, но когда параллельные коллекции не могут освободить память достаточно быстро, будет выполнена резервная сборка мусора. При полной сборке мусора используется такое же количество параллельных рабочих потоков, что и при сборки молодого и смешанного мусора.

Сборщик мусора Parallel

Сборщик Parallel используется по умолчанию в Java 8. Сборщик мусора Parallel нацелен на обеспечение высокой пропускной способности при использовании нескольких потоков для ускорения сборки.

Epsilon [11]

Сборщик мусора Epsilon обрабатывает выделения, но не освобождает память. Когда куча будет исчерпана, виртуальная машина Java завершит работу. Epsilon удобно использовать для служб с коротким сроком жизни и приложений, которым гарантированно не требуется сборка мусора.

Улучшения для контейнеров Docker [12]

До версии Java 10 в виртуальной машине Java не учитывались ограничения памяти и ЦП, заданные для контейнера. Например, в Java 8 виртуальная машина Java по умолчанию ограничивала размер кучи на уровне 1/4 от общего объема физической памяти базового узла. Начиная с Java 10, в виртуальной машине Java учитываются ограничения, заданные для групп управления контейнерами (cgroup), при установке ограничений памяти и ЦП (см. примечание ниже). Например, максимальный размер кучи по умолчанию составляет 1/4 от ограничения памяти для контейнера (500 МБ при использовании -m2G).

Также добавлены новые параметры виртуальной машины Java. Они позволяют пользователям контейнеров Docker контролировать объем системной памяти, который будет использоваться для кучи Java.

Эта возможность включена по умолчанию, но доступна только на платформах под управлением Linux.

Большая часть работы по поддержке cgroup направлена на обеспечение обратной совместимости в Java 8, начиная с версии jdk8u191. Мы не гарантируем, что последующие улучшения будут доступны в версии 8.

Jar-файлы с несколькими выпусками [13]

В Java 11 можно создать JAR-файл, который содержит несколько версий файлов классов, предназначенных для конкретных выпусков Java. Такие JAR-файлы позволяют разработчикам библиотек поддерживать несколько версий Java без необходимости предоставлять несколько версий JAR-файлов. Для потребителей этих библиотек такие JAR-файлы решают проблему подбора правильных JAR-файлов для каждой целевой версии среды выполнения.

Разные улучшения производительности

Следующие изменения оказывают прямое влияние на производительность виртуальной машины Java.

  • JEP 197: сегментированные кэши кода [14] — делит кэш кода на отдельные сегменты. Такая сегментация позволяет управлять объемом памяти, используемой виртуальной машиной Java, ускоряет сканирование скомпилированных методов, значительно снижает фрагментацию кэша кода и повышает производительность.
  • JEP 254: компактные строки [15] — изменяет внутреннее представление строки с двух байтов на char на один или два байта на char в зависимости от кодировки char. Так как большинство строк содержат символы кодировки ISO-8859-1/Latin-1, это изменение вдвое сокращает пространство, необходимое для хранения строк.
  • JEP 310: совместное использование приложений Class-Data [16] — Class-Data общий доступ уменьшает время запуска, позволяя архивным классам сопоставляться с памятью во время выполнения. а также расширяет возможность совместного использования данных класса, позволяя размещать классы приложений в архив Common Data Service. Если несколько виртуальных машин Java совместно используют один и тот же файл архива, потребление памяти и общее время отклика системы снижаются.
  • JEP 312: Thread-Local подтверждения [17] — позволяет выполнять обратный вызов в потоках без выполнения глобальной безопасной точки виртуальной машины, что помогает виртуальной машине достичь меньшей задержки за счет уменьшения числа глобальных безопасных точек.
  • Отложенное выделение потоков компилятора [18] — в многоуровневом режиме компиляции виртуальная машина запускает большое количество потоков компилятора. Этот режим используется по умолчанию в системах с большим количеством процессоров. Такие потоки создаются независимо от объема доступной памяти или количества запросов компиляции. Потоки потребляют память, даже когда бездействуют (что происходит почти все время), что приводит к неэффективному использованию ресурсов. Для решения этой проблемы реализация изменена так, чтобы при запуске открывался только один поток компилятора каждого типа. Запуск дополнительных потоков и завершение работы неиспользуемых потоков осуществляется динамически.

Следующие изменения в основных библиотеках влияют на производительность нового или измененного кода.

  • JEP 193: дескриптора переменных [19] — определяет стандартный способ вызова эквивалентов различных операций java.util.concurrent.atomic и sun.misc.Unsafe при полях объектов и элементах массива, стандартный набор операций ограждения для точного управления упорядочением памяти, а также стандартная операция обеспечения доступности и ограждения для обеспечения строгой доступности объекта.
  • JEP 269: удобные фабричные методы для коллекций [20] — определяет API библиотеки, чтобы упростить создание экземпляров коллекций и карт с небольшим количеством элементов. Эти статические фабричные методы в интерфейсах коллекции создают компактный и неизменяемый экземпляр коллекции. Такие экземпляры по своей сути являются более эффективными. API создают коллекции, которые хранятся в компактном виде и не имеют класс-оболочку.
  • JEP 285: Spin-Wait подсказки [21] — предоставляет API, который позволяет Java намекать системе времени выполнения, что она находится в цикле спина. Некоторые аппаратные платформы могут использовать информацию от программного обеспечения о том, что поток находится в состоянии активного ожидания.
  • JEP 321: HTTP-клиент (стандартная версия) [22]. Предоставляет новый API клиента HTTP, который реализует HTTP/2 и WebSocket и может заменить устаревший API HttpURLConnection.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *