├── .gitignore ├── README.md ├── alternatives └── alternatives.md ├── database ├── database.md └── sql.md ├── development ├── development.md ├── images │ └── Cube.png └── microservices.md ├── hibernate └── hibernate.md ├── java ├── collections.md ├── concurrency.md ├── core.md └── jvm.md ├── libraries └── libraries.md ├── maintenance └── maintenance.md ├── misc └── usefulness.md └── spring └── spring.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # awesome-java-backend-interview 2 | 3 | Repository with java-backend interview questions and answers [RUS] 4 | 5 | ## Оглавление 6 | 7 | 1. Java 8 | - [Core](./java/core.md) 9 | - [Collections](./java/collections.md) 10 | - [Concurrency](./java/concurrency.md) 11 | - [JVM](./java/jvm.md) 12 | 1. [Spring](./spring/spring.md) 13 | 1. [Hibernate](./hibernate/hibernate.md) 14 | 1. [Популярные библиотеки](./libraries/libraries.md) 15 | 1. Базы данных 16 | - [Теория](./database/database.md) 17 | - [SQL](./database/sql.md) 18 | 1. Разработка ПО 19 | - [Принципы, паттерны, практики и подходы](./development/development.md) 20 | - [Микросервисы](./development/microservices.md) 21 | 1. [Сопровождение, поддержка, эксплуатация](./maintenance/maintenance.md) 22 | 1. [Полезные ссылки](./misc/usefulness.md) 23 | 1. [Альтернативы](./alternatives/alternatives.md) 24 | 25 | -------------------------------------------------------------------------------- /alternatives/alternatives.md: -------------------------------------------------------------------------------- 1 | [Оглавление](../README.md) 2 | 3 | # Аналогичные источники вопросов-ответов 4 | 5 | - [Вопросы к собеседованию Java-backend, Java core (60 вопросов)](https://habr.com/ru/post/485678/) на Хабре 6 | - [Spring: вопросы к собеседованию](https://habr.com/ru/post/350682/) на Хабре 7 | - [Шпаргалка Java программиста 1: JPA и Hibernate в вопросах и ответах](https://habr.com/ru/post/265061/) на Хабре 8 | - [JavaSobes](https://itsobes.ru/JavaSobes/tags/) и в [telegram](https://t.me/JavaSobes) 9 | - [Awesome-interview-questions/Java](https://github.com/MaximAbramchuck/awesome-interview-questions#java) 10 | - [Вопросы для собеседования на Java Developer](https://github.com/enhorse/java-interview) 11 | - [Вопросы и ответы на собеседование Java Developer](https://jsehelper.blogspot.com/p/welcome.html) 12 | - [Список вопросов с ответами для собеседования по Java](https://javastudy.ru/interview/list-of-question-java-interview/) 13 | - [Антон Архипов - Неадекватное Java-интервью](https://www.youtube.com/watch?v=Vlb_Is-rRTQ) 14 | 15 | -------------------------------------------------------------------------------- /database/database.md: -------------------------------------------------------------------------------- 1 | [Оглавление](../README.md) 2 | 3 | # Database 4 | 5 | - [ACID - расшифровать и немного раскрыть](#acid---расшифровать-и-немного-раскрыть) 6 | - [Уровни изолированности транзакции. Какую проблему решает каждый уровень? Какой по умолчанию в большинстве реляционных БД? Приходилось ли изменять уровень изолированности транзакции и для чего?](#уровни-изолированности-транзакции-какую-проблему-решает-каждый-уровень-какой-по-умолчанию-в-большинстве-реляционных-бд-приходилось-ли-изменять-уровень-изолированности-транзакции-и-для-чего) 7 | - [Какие бывают типы индексов в БД и как они устроены под капотом? Что такое индекс вообще?](#какие-бывают-типы-индексов-в-бд-и-как-они-устроены-под-капотом-что-такое-индекс-вообще) 8 | - [В чем разница между оптимистической и пессимистической блокировками?](#в-чем-разница-между-оптимистической-и-пессимистической-блокировками) 9 | 10 | ## ACID - расшифровать и немного раскрыть 11 | 12 | - *A* - Атомарность (Atomicity). Гарантирует, что никакая транзакция не будет зафиксирована в системе частично. 13 | - *C* - Согласованность (Consistency). Каждая успешная транзакция фиксирует только допустимые результаты. 14 | - *I* - Изолированность (Isolation). Во время выполнения транзакции параллельные транзакции не должны оказывать влияния на её результат. 15 | - *D* - Стойкость (Durability). Подтверждённые изменения не будут отменены (например, из-за сбоя). 16 | 17 | [к содержанию](#database) 18 | 19 | ## Уровни изолированности транзакции. Какую проблему решает каждый уровень? Какой по умолчанию в большинстве реляционных БД? Приходилось ли изменять уровень изолированности транзакции и для чего? 20 | 21 | Краткий конспект [статьи](https://ru.wikipedia.org/wiki/%D0%A3%D1%80%D0%BE%D0%B2%D0%B5%D0%BD%D1%8C_%D0%B8%D0%B7%D0%BE%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D0%B8_%D1%82%D1%80%D0%B0%D0%BD%D0%B7%D0%B0%D0%BA%D1%86%D0%B8%D0%B9) из Википедии: 22 | - `Read uncommitted` (чтение незафиксированных данных). Он гарантирует только отсутствие потерянных обновлений (ситуация, когда при одновременном изменении одного блока данных разными транзакциями одно из изменений теряется). 23 | - `Read committed` (чтение фиксированных данных). Именно он чаще всего является уровнем по умолчанию. Обеспечивает защиту от «грязного» чтения (чтение данных, добавленных или изменённых транзакцией, которая впоследствии откатится). 24 | - `Repeatable read` (повторяемость чтения). Решает проблему неповторяющегося чтения (ситуация, когда при повторном чтении в рамках одной транзакции ранее прочитанные данные оказываются изменёнными). 25 | - `Serializable` (упорядочиваемость). Транзакции полностью изолируются друг от друга, каждая выполняется так, как будто параллельных транзакций не существует - защищает от фантомного чтения (ситуация, когда при повторном чтении в рамках одной транзакции одна и та же выборка дает разные множества строк). 26 | 27 | На Хабре есть несколько статей по теме на любой вкус: 28 | - [Для самых маленьких](https://habr.com/ru/post/469415/) 29 | - Для MSSQL: [раз](https://habr.com/ru/post/305600/), [два](https://habr.com/ru/company/infopulse/blog/261097/), [три](https://habr.com/ru/company/infopulse/blog/261101/) 30 | - [Для PostgreSQL](https://habr.com/ru/post/317884/). Тут вообще стоит упомянуть для любителей углубиться в тему статьи из блога [Postgres Professional](https://habr.com/ru/company/postgrespro/), и в частности цикл статей @egorov по внутреннему устройству PostgreSQL (например, [раз](https://habr.com/ru/company/postgrespro/blog/442804/), [два](https://habr.com/ru/company/postgrespro/blog/462877/) и т.д.). А также на сайте Postgres Professional есть документация на русском языке и [страница](https://postgrespro.ru/docs/postgresql/12/transaction-iso) по данному вопросу. 31 | - Для MySQL: [раз](https://habr.com/ru/post/135217/), [два](https://habr.com/ru/post/238513/) 32 | - [Транзакции и механизмы их контроля](https://habr.com/ru/post/446662/) 33 | 34 | [к содержанию](#database) 35 | 36 | ## Какие бывают типы индексов в БД и как они устроены под капотом? Что такое индекс вообще? 37 | 38 | [Индекс БД](https://en.wikipedia.org/wiki/Database_index) - это структура данных, которая повышает скорость операций поиска данных в таблице БД за счет дополнительных операций записи и хранения для поддержания структуры данных индекса. Индексы используются для быстрого поиска данных без необходимости поиска каждой строки в таблице базы данных каждый раз при обращении к таблице БД. Ключом индекса выступает значение индексируемого столбца/столбцов. Некоторые БД позволяют строить индексы по выражениям. 39 | 40 | В основе индексов чаще всего лежат следующие структуры данных: 41 | - Семейство [B-Tree](https://en.wikipedia.org/wiki/B-tree) 42 | - [HASH-таблицы](https://en.wikipedia.org/wiki/Hash_table) 43 | - [Bitmap](http://citforum.ru/database/oracle/bitmap_index/) 44 | - [Фильтр Блума](https://en.wikipedia.org/wiki/Bloom_filter) 45 | - [Spatial grid](https://en.wikipedia.org/wiki/Grid_(spatial_index)) 46 | - [Quadtree](https://en.wikipedia.org/wiki/Quadtree) 47 | - [R-Tree](https://en.wikipedia.org/wiki/Hilbert_R-tree) 48 | - и другие. 49 | 50 | [Классификацию индексов](http://tokarchuk.ru/2012/08/indexes-classification/) можно разделить по различным критериям. Следует уточнить или предложить интервьюеру какой именно критерий имеется в виду. 51 | Например, по порядку сортировки: 52 | - Упорядоченные - индексы, в которых записи упорядочены по возрастанию или убыванию. Реализуются на B-деревьях. 53 | - Неупорядоченные - индексы, в которых записи неупорядоченны. Реализуются на хешах. 54 | Или по воздействию на источник данных: 55 | - Некластерные - такие индексы организуют ссылки на соответствующие строки и значения. Ссылка содержит информацию об ID файла, в котором хранится строка; ID страницы соответствующих данных; номер искомой строки на соответствующей странице; содержимое столбца. В таблице БД может быть несколько некластерных индексов. 56 | - Кластерные - такие индексы представляют собой древовидную структуру данных, при которой значения индекса хранятся вместе с соответствующими им данными. Физическое расположение данных перестраивается в соответствии с порядком индекса, поэтому может быть только один такой индекс на таблицу БД. 57 | 58 | Подробнее: 59 | - [Обзор типов индексов Oracle, MySQL, PostgreSQL, MS SQL](https://habr.com/ru/post/102785/) на Хабре 60 | - Великолепная серия статей от Егора Рогова про индексы в PostgreSQL: [часть 1](https://habr.com/ru/company/postgrespro/blog/326096/), [часть 2](https://habr.com/ru/company/postgrespro/blog/326106/), [часть 3](https://habr.com/ru/company/postgrespro/blog/328280/), [часть 4](https://habr.com/ru/company/postgrespro/blog/330544/), [часть 5](https://habr.com/ru/company/postgrespro/blog/333878/), [часть 6](https://habr.com/ru/company/postgrespro/blog/337502/), [часть 7](https://habr.com/ru/company/postgrespro/blog/340978/), [часть 8](https://habr.com/ru/company/postgrespro/blog/343488/), [часть 9](https://habr.com/ru/company/postgrespro/blog/346460/), [часть 10](https://habr.com/ru/company/postgrespro/blog/349224/) 61 | - [Кластерные и «обычные» индексы MySQL (InnoDB)](https://habr.com/ru/post/141767/) на Хабре 62 | - [«Под капотом» индексов Postgres](https://habr.com/ru/company/mailru/blog/261871/) на Хабре 63 | - [Типы индексов, виды индексов, или какие вообще бывают индексы?](http://tokarchuk.ru/2012/08/indexes-classification/) 64 | - [Индекс базы данных: типы индексов](https://alextoolsblog.blogspot.com/2019/11/database-index-types.html) 65 | - [Индекс базы данных: методы индексирования, приложения и ограничения](https://alextoolsblog.blogspot.com/2019/11/database-index-methods.html) 66 | - [Индекс базы данных](https://alextoolsblog.blogspot.com/2019/11/database-index.html) 67 | - [Database Indexes Explained](https://www.essentialsql.com/what-is-a-database-index/) 68 | - [Bitmap-индекс или B*tree-индекс: какой и когда применять?](http://citforum.ru/database/oracle/bb_indexes/) 69 | - [Индексы в MySQL](https://ruhighload.com/%D0%98%D0%BD%D0%B4%D0%B5%D0%BA%D1%81%D1%8B+%D0%B2+mysql) 70 | - [Как работает реляционная БД](https://habr.com/ru/company/mailru/blog/266811/) на Хабре 71 | - [Здоровье индексов в PostgreSQL глазами Java-разработчика](https://habr.com/ru/post/490824/) на Хабре 72 | - [14 вопросов об индексах в SQL Server, которые вы стеснялись задать](https://habr.com/ru/post/247373/) на Хабре 73 | - [Вопросы про индексы, которые вам не надо будет задавать](https://habr.com/ru/post/247949/) на Хабре 74 | - [Используем все возможности индексов в PostgreSQL](https://habr.com/ru/company/mailru/blog/453046/) 75 | - [Anatomy of an SQL Index](https://use-the-index-luke.com/sql/anatomy) 76 | - [SQL Indexing and Tuning e-Book](https://use-the-index-luke.com/) 77 | - [Deep dive into Hash indexes for In-Memory OLTP tables](https://www.sqlshack.com/deep-dive-hash-indexes-memory-oltp-tables/#:~:text=Simply%20explained%2C%20in%20the%20In,in%20an%20in%2Dmemory%20table.) 78 | - [Indexing based on Hashing](http://www.mathcs.emory.edu/~cheung/Courses/554/Syllabus/3-index/hashing.html) 79 | - [SQL Server Indexes Interview Questions and Answers](https://dotnettutorials.net/lesson/sql-server-indexes-interview-questions-answers/) 80 | - [Top 25 SQL interview questions and answers about indexes](https://www.sqlshack.com/top-25-sql-interview-questions-and-answers-about-indexes/) 81 | - [An in-depth look at Database Indexin](https://www.freecodecamp.org/news/database-indexing-at-a-glance-bb50809d48bd/) 82 | 83 | [к содержанию](#database) 84 | 85 | ## В чем разница между оптимистической и пессимистической блокировками? 86 | 87 | [Блокировка](https://ru.wikipedia.org/wiki/%D0%91%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0_(%D0%A1%D0%A3%D0%91%D0%94)) (lock) в СУБД — отметка о захвате объекта транзакцией в ограниченный или исключительный доступ с целью предотвращения коллизий и поддержания целостности данных. 88 | 89 | Пессимистическая блокировка - накладывается перед предполагаемой модификацией данных на все строки, которые такая модификация предположительно затрагивает. Во время действия такой блокировки исключена модификация данных из сторонних сессий, данные из блокированных строк доступны согласно уровню изолированности транзакции. По завершению предполагаемой модификации гарантируется непротиворечивая запись результатов. Недостатком является то, что записи могут быть заблокированы на очень долгое время, тем самым замедляя общую реакцию системы. 90 | Пессимистическая блокировка может быть двух типов: 91 | - shared (read) - блокирует писателей, но позволяет читателям продолжить работу. Иными словами, разрешает другим транзакциям захватывать блокировку на чтение, но запрещает блокировку на запись. 92 | - exclusive (write) - блокирует и писателей, и читателей. Делает все операции записи последовательными. Иными словами, запрещает другим транзакциям захватывать блокировки на чтение и на запись. 93 | 94 | [Оптимистическая блокировка](https://en.wikipedia.org/wiki/Optimistic_concurrency_control) - не ограничивает модификацию обрабатываемых данных сторонними сессиями, однако перед началом предполагаемой модификации запрашивает значение некоторого выделенного атрибута каждой из строк данных (обычно используется наименование `VERSION` и целочисленный тип с начальным значением `0`). Перед записью модификаций в базу данных перепроверяется значение выделенного атрибута, и если оно изменилось, то транзакция откатывается или применяются различные схемы разрешения коллизий. Если значение выделенного атрибута не изменилось — производится фиксация модификаций с одновременным изменением значения выделенного атрибута (например, инкрементом) для сигнализации другим сессиям, что данные изменились. 95 | 96 | Основное отличие в том, что оптимистическая блокировка приводит к накладным расходам только в случае конфликта, в то время как пессимистическая блокировка уменьшает накладные расходы на конфликт. Поэтому оптимистическая блокировка лучше всего подходит в случае, когда большинство транзакций не конфликтуют. 97 | 98 | Много статей про блокировки с кодом и картинками можно прочитать в блоге Vlad Mihalcea: 99 | - [A beginner’s guide to Java Persistence locking](https://vladmihalcea.com/a-beginners-guide-to-java-persistence-locking/) 100 | - [A beginner’s guide to database locking and the lost update phenomena](https://vladmihalcea.com/a-beginners-guide-to-database-locking-and-the-lost-update-phenomena/) 101 | - [How do LockModeType.PESSIMISTIC_READ and LockModeType.PESSIMISTIC_WRITE work in JPA and Hibernate](https://vladmihalcea.com/hibernate-locking-patterns-how-do-pessimistic_read-and-pessimistic_write-work/) 102 | - [How does LockModeType.PESSIMISTIC_FORCE_INCREMENT work in JPA and Hibernate](https://vladmihalcea.com/hibernate-locking-patterns-how-does-pessimistic_force_increment-lock-mode-work/) 103 | - [How does LockModeType.OPTIMISTIC work in JPA and Hibernate](https://vladmihalcea.com/hibernate-locking-patterns-how-does-optimistic-lock-mode-work/) 104 | - [How does LockModeType.OPTIMISTIC_FORCE_INCREMENT work in JPA and Hibernate](https://vladmihalcea.com/hibernate-locking-patterns-how-does-optimistic_force_increment-lock-mode-work/) 105 | - [How to prevent OptimisticLockException with Hibernate versionless optimistic locking](https://vladmihalcea.com/how-to-prevent-optimisticlockexception-using-hibernate-versionless-optimistic-locking/) 106 | - [How does database pessimistic locking interact with INSERT, UPDATE, and DELETE SQL statements](https://vladmihalcea.com/how-does-database-pessimistic-locking-interact-with-insert-update-and-delete-sql-statements/) 107 | - [How does MVCC (Multi-Version Concurrency Control) work](https://vladmihalcea.com/how-does-mvcc-multi-version-concurrency-control-work/) 108 | - [How does the 2PL (Two-Phase Locking) algorithm work](https://vladmihalcea.com/2pl-two-phase-locking/) 109 | - [How to prevent lost updates in long conversations](https://vladmihalcea.com/preventing-lost-updates-in-long-conversations/) 110 | 111 | Подробнее на Хабре: 112 | - [Конкурентный доступ к реляционным базам данных](https://habr.com/ru/post/121858/) 113 | - [Базы данных. Конфликты параллельного доступа](https://habr.com/ru/post/86302/) 114 | - [Замечательная аннотация Version в JPA](https://habr.com/ru/post/434836/) 115 | - [Документация разработчика Hibernate – Глава V. Блокировки](https://habr.com/ru/post/268903/) 116 | - [Блокировки в PostgreSQL: 1. Блокировки отношений](https://habr.com/ru/company/postgrespro/blog/462877/) 117 | - [Блокировки в PostgreSQL: 2. Блокировки строк](https://habr.com/ru/company/postgrespro/blog/463819/) 118 | - [Блокировки в PostgreSQL: 3. Блокировки других объектов](https://habr.com/ru/company/postgrespro/blog/465263/) 119 | - [Блокировки в PostgreSQL: 4. Блокировки в памяти](https://habr.com/ru/company/postgrespro/blog/466199/) 120 | 121 | Подробнее в других источниках: 122 | - [Pessimistic Locking in JPA](https://www.baeldung.com/jpa-pessimistic-locking) 123 | - [Optimistic Locking in JPA](https://www.baeldung.com/jpa-optimistic-locking) 124 | - [Enabling Transaction Locks in Spring Data JPA](https://www.baeldung.com/java-jpa-transaction-locks) 125 | - [Deadlock](https://en.wikipedia.org/wiki/Deadlock) 126 | - [Enum LockModeType](https://docs.oracle.com/javaee/7/api/javax/persistence/LockModeType.html) 127 | - [Явные блокировки в Postgresql](https://postgrespro.ru/docs/postgresql/12/explicit-locking) 128 | - [PostgreSQL Concurrency with MVCC](https://devcenter.heroku.com/articles/postgresql-concurrency) 129 | - [Locking](https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#locking) в документации Hibernate 130 | - [Optimistic locking](https://www.jooq.org/doc/latest/manual/sql-execution/crud-with-updatablerecords/optimistic-locking/) в документации JOOQ 131 | - [Optimistically Locking Your Spring Boot Web Services](https://medium.com/slalom-build/optimistically-locking-your-spring-boot-web-services-187662eb8a91) 132 | - [Optimistic and pessimistic locking with SQL](https://convincedcoder.com/2018/09/01/Optimistic-pessimistic-locking-sql/) 133 | 134 | [к содержанию](#database) -------------------------------------------------------------------------------- /database/sql.md: -------------------------------------------------------------------------------- 1 | [Оглавление](../README.md) 2 | 3 | # SQL 4 | 5 | - [В чем разница между where и having в SQL?](#в-чем-разница-между-where-и-having-в-sql) 6 | 7 | ## В чем разница между where и having в SQL? 8 | 9 | Есть исчерпывающий [ответ](https://www.postgresql.org/docs/12/tutorial-agg.html) на этот вопрос в документации к Postgresql. Вот его перевод с сайта [Postgres Pro](https://postgrespro.ru/docs/postgresql/12/tutorial-agg): 10 | >Основное отличие WHERE от HAVING заключается в том, что WHERE сначала выбирает строки, а затем группирует их и вычисляет агрегатные функции (таким образом, она отбирает строки для вычисления агрегатов), тогда как HAVING отбирает строки групп после группировки и вычисления агрегатных функций. Как следствие, предложение WHERE не должно содержать агрегатных функций; не имеет смысла использовать агрегатные функции для определения строк для вычисления агрегатных функций. Предложение HAVING, напротив, всегда содержит агрегатные функции. (Строго говоря, вы можете написать предложение HAVING, не используя агрегаты, но это редко бывает полезно. То же самое условие может работать более эффективно на стадии WHERE.) 11 | 12 | Но вас также может заинтересовать: 13 | - [Как работает реляционная БД](https://habr.com/ru/company/mailru/blog/266811/) на Хабре 14 | - [How does a relational database work](https://vladmihalcea.com/how-does-a-relational-database-work/) 15 | - [How does a relational database execute SQL statements and prepared statements](https://vladmihalcea.com/relational-database-sql-prepared-statements/) 16 | - [How Database Internally Works](https://dev.to/dhanushkadev/how-database-internally-works-pfh) 17 | - [Курс](https://www.youtube.com/playlist?list=PL-_cKNuVAYAWMRG7iKHGZMg9Az8HX735w) по БД от Ильи Тетерина или [курс](https://www.youtube.com/playlist?list=PL-_cKNuVAYAU-CO9NXtjzqdUsXoK047DZ) от Вадима Цесько 18 | - [Let's Build a Simple Database](https://cstack.github.io/db_tutorial/) 19 | - [Database internals](https://www.databass.dev/) 20 | 21 | [к содержанию](#sql) -------------------------------------------------------------------------------- /development/development.md: -------------------------------------------------------------------------------- 1 | [Оглавление](../README.md) 2 | 3 | # Принципы, паттерны, практики и подходы разработки ПО 4 | 5 | - [SOLID.](#solid) 6 | - [Паттерны. Какие знаете? Каких видов бывают? Расскажите парочку (желательно разных видов)? Какие применяли на практике или встречались где-то? Чем декоратор отличается от прокси, а абстрактная фабрика от обычной?](#паттерны-какие-знаете-каких-видов-бывают-расскажите-парочку-желательно-разных-видов-какие-применяли-на-практике-или-встречались-где-то-чем-декоратор-отличается-от-прокси-а-абстрактная-фабрика-от-обычной) 7 | - [Что такое coupling и cohesion? Что из них (или оба) должно быть сильным (высоким) и/или слабым (низким)?](#что-такое-coupling-и-cohesion-что-из-них-или-оба-должно-быть-сильным-высоким-иили-слабым-низким) 8 | - [Что такое куб масштабирования?](#что-такое-куб-масштабирования) 9 | - [Расскажите о CAP-теореме. Как MongoDB (например) удовлетворяет CAP-теореме?](#расскажите-о-cap-теореме-как-mongodb-например-удовлетворяет-cap-теореме) 10 | - [Чем композиция отличается от агрегации?](#чем-композиция-отличается-от-агрегации) 11 | - [Какие бывают тестовые объекты (заглушки)? Чем стаб отличается от мока?](#какие-бывают-тестовые-объекты-заглушки-чем-стаб-отличается-от-мока) 12 | - [Дайте определение полиморфизму](#дайте-определение-полиморфизму) 13 | - [Что такое REST? Какое API является RESTful? Чем REST отличается от SOAP?](#что-такое-rest-какое-api-является-restful-чем-rest-отличается-от-soap) 14 | 15 | ## SOLID. 16 | 17 | Обычно просто просят расшифровать, что каждая буква означает с минимальным пояснением. Никто из моих интервьюеров не стал размусоливать или обсуждать. Один раз спросили, зачем оно вообще надо. Но, я думаю, чем больше сеньорности в вакансии, тем глубже и интереснее дискуссия может возникнуть. 18 | 19 | - *S* - Принцип единственной ответственности (The Single Responsibility Principle). Каждый класс должен иметь одну и только одну причину для изменений. 20 | - *O* - Принцип открытости/закрытости (The Open Closed Principle). Сущности должны быть открыты для расширения, но закрыты для модификации. 21 | - *L* - Принцип подстановки Барбары Лисков (The Liskov Substitution Principle). Объекты должны быть заменяемыми на экземпляры их подтипов без изменения правильности выполнения программы. Наследующий класс должен дополнять, а не изменять базовый. 22 | - *I* - Принцип разделения интерфейса (The Interface Segregation Principle). Много специальных интерфейсов лучше, чем один универсальный. 23 | - *D* - Принцип инверсии зависимостей (The Dependency Inversion Principle). Зависеть нужно от абстракций, а не от реализаций. 24 | 25 | Первоисточником, сформулировавшим данные принципы стал дядюшка "Свет наш чистый код" [Боб Мартин](https://ru.wikipedia.org/wiki/%D0%9C%D0%B0%D1%80%D1%82%D0%B8%D0%BD,_%D0%A0%D0%BE%D0%B1%D0%B5%D1%80%D1%82_(%D0%B8%D0%BD%D0%B6%D0%B5%D0%BD%D0%B5%D1%80)), а акроним придумал один из его читателей. Хотите погрузиться глубже? Тогда читайте часть 3 его книги ["Чистая архитектура"](https://www.piter.com/product/chistaya-arhitektura-iskusstvo-razrabotki-programmnogo-obespecheniya). Книжка годная, читается легко, не пожалеете. Однако пропускайте всё через свой опыт и оценивайте критически, мало ли что :) 26 | 27 | Сама по себе тема богатая и холиворная, ибо многие начинают трактовать эти принципы по-своему. На этой почве может случиться недопонимание с собеседующим, будьте аккуратны и конструктивны. Достаточно [поискать статьи на Хабре](https://habr.com/ru/search/?q=SOLID#h) по SOLID или каким-нибудь принципам в отдельности и заглянуть в комментарии. Кому-то SOLID вообще не по душе. 28 | 29 | Также, могу посоветовать, самостоятельно разобрать каждый принцип на практическом примере, ибо за это тоже могут спросить. Или заглянуть на [Baeldung](https://www.baeldung.com/solid-principles). 30 | 31 | [к содержанию](#принципы-паттерны-практики-и-подходы-разработки-по) 32 | 33 | ## Паттерны. Какие знаете? Каких видов бывают? Расскажите парочку (желательно разных видов)? Какие применяли на практике или встречались где-то? Чем декоратор отличается от прокси, а абстрактная фабрика от обычной? 34 | 35 | Обычно советуют и в вакансиях пишут про [книжку GoF](https://www.ozon.ru/context/detail/id/2457392/). Но, на мой взгляд, сейчас есть вариант даже лучше - [refactoring.guru](https://refactoring.guru/ru/design-patterns). Там и сравнение, и на родной мове (русский, украинский, английский, китайский), и примеры на вашем любимом ЯП, прекрасные иллюстрации и диаграммы. Там также можно купить книжку по паттернам. Автору большой-большой респект. 36 | 37 | [к содержанию](#принципы-паттерны-практики-и-подходы-разработки-по) 38 | 39 | ## Что такое coupling и cohesion? Что из них (или оба) должно быть сильным (высоким) и/или слабым (низким)? 40 | 41 | [Coupling](https://ru.wikipedia.org/wiki/%D0%97%D0%B0%D1%86%D0%B5%D0%BF%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)) (Зацепление) - степень зависимости между программными компонентами. Должна быть *низкой*. 42 | 43 | [Cohesion](https://ru.wikipedia.org/wiki/%D0%A1%D0%B2%D1%8F%D0%B7%D0%BD%D0%BE%D1%81%D1%82%D1%8C_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)) (Связность) - степень сфокусированности методов класса. Должна быть *высокой*. 44 | 45 | Подробнее почитать и посмотреть картинки можно [тут](https://thebojan.ninja/2015/04/08/high-cohesion-loose-coupling/) на английском или [тут](https://medium.com/german-gorelkin/low-coupling-high-cohesion-d36369fb1be9) на русском. 46 | 47 | Тема периодически затрагивается на Хабре в контексте построения хорошей архитектуры и написания качественного кода. Как и всегда, особую ценность составляют комментарии: 48 | - [Создание архитектуры программы или как проектировать табуретку](https://habr.com/ru/post/276593/) 49 | - [Принцип единственной ответственности: глубокое погружение](https://habr.com/ru/post/465507/). Есть раздел, где тема разобрана с примерами кода. 50 | - [Утрата слабой связанности](https://habr.com/ru/post/206684/) 51 | 52 | Также coupling и cohesion часто упоминаются или ведут к обсуждению [GRASP](https://ru.wikipedia.org/wiki/GRASP). Об этом можно почитать на Хабре: [раз](https://habr.com/ru/post/38323/) и [два](https://habr.com/ru/post/92570/). 53 | 54 | [к содержанию](#принципы-паттерны-практики-и-подходы-разработки-по) 55 | 56 | ## Что такое куб масштабирования? 57 | 58 | Куб масштабирования (scale cube, из книги [The Art of Scalability](https://www.oreilly.com/library/view/the-art-of/9780134031408/)) является наглядным изображением трёх ортогональных способов увеличения производительности приложения: sharding, mirrorring и microservices. 59 | 60 | - [Sharding](https://en.wikipedia.org/wiki/Shard_(database_architecture)) (data partioning) - разбиение и размещение однотипных данных по разным узлам. 61 | - [Mirroring](https://www.techopedia.com/definition/30664/database-mirroring) (horizontal duplication) - дублирование или клонирование данных для уменьшения времени отклика. 62 | - [Microservices](https://microservices.io/) - архитекутрный подход, при котором функциональность системы разбивается на отдельные сервисы по бизнес-задачам. 63 | 64 | Наглядно: 65 | ![Куб масштабирования](./images/Cube.png) 66 | 67 | Почитать подробнее: 68 | - Упоминание в [статье](https://habr.com/ru/company/dataart/blog/280083/) на Хабре. 69 | - В [статье](https://microservices.io/articles/scalecube.html) на microservices.io. 70 | - Даже в [wiki](https://en.wikipedia.org/wiki/Scale_cube) есть с pros и cons. 71 | - [SCALING APPLICATIONS : THE SCALE CUBE](https://geeknarrator.com/2018/03/06/scaling-applications-the-scale-cube/). 72 | - И вот [ещё](https://www.instana.com/blog/scaling-microservices-advanced-approaches-with-the-akf-scaling-cube/). 73 | - А [тут](https://akfpartners.com/growth-blog/scale-cube) с картинками. 74 | - Также куб упоминается в книгах [Microservice Patterns and Best Practices](https://www.packtpub.com/application-development/microservice-patterns-and-best-practices) и [Microservices Patterns](https://www.manning.com/books/microservices-patterns) (есть на русском). 75 | 76 | [к содержанию](#принципы-паттерны-практики-и-подходы-разработки-по) 77 | 78 | ## Расскажите о CAP-теореме. Как MongoDB (например) удовлетворяет CAP-теореме? 79 | 80 | [Теорема CAP](https://en.wikipedia.org/wiki/CAP_theorem) - эвристическая теорема, утверждающая, что любая распределённая система может удовлетворять не более двум из трёх свойств: 81 | - [Consistency](https://en.wikipedia.org/wiki/Consistency_model) (согласованность) - во всех вычислительных узлах в один момент времени данные не противоречат друг другу - каждое чтение вернёт самую последнюю запись. Подразумевает под собой [линеаризуемость](http://cs.brown.edu/~mph/HerlihyW90/p463-herlihy.pdf) - если произошла какая-либо операция, то её результат доступен сразу после того, как был получен ответ о её выполнении. 82 | - [Availability](https://en.wikipedia.org/wiki/Availability) (доступность) - любой запрос получает успешный ответ без гарантии, что ответы со всех узлов системы совпадают. 83 | - [Partition tolerance](https://en.wikipedia.org/wiki/Network_partition) (устойчивость к разделению) - система продолжает функционировать, несмотря на потерю (или задержку) произвольного числа сообщений между узлами из-за сетевых проблем (асинхронная сеть). 84 | 85 | MongoDB, по мнению большинства ([например](https://www.ibm.com/cloud/learn/cap-theorem)), это - CP, но вот есть [статья](https://habr.com/ru/post/258145/)... Держим в уме, что теорема эвристическая и носит упрощательный характер. Также вызывает много споров. 86 | 87 | Про большинство БД можно найти ответы в статьях по дополнительным ссылкам ниже. 88 | 89 | Подробности: 90 | - Есть несколько статей на Хабре: [раз](https://habr.com/ru/post/328792/), [два](https://habr.com/ru/post/130577/), [три](https://habr.com/ru/post/258145/), [четыре](https://habr.com/ru/post/231703/), [пять](https://habr.com/ru/post/322276/) 91 | - [Visual Guide to NoSQL Systems](https://blog.nahurst.com/visual-guide-to-nosql-systems) с красивой иллюстрацией треугольника CAP и БД на его сторонах 92 | - [The CAP FAQ](https://www.the-paper-trail.org/page/cap-faq/) 93 | - [Статья](https://www.bigdataschool.ru/wiki/cap) на bigdataschool 94 | - [Споры](https://stackoverflow.com/questions/11292215/where-does-mongodb-stand-in-the-cap-theorem) вокруг MongoDB на stackoverflow 95 | - [CAP Theorem](https://www.ibm.com/cloud/learn/cap-theorem) на портале IBM 96 | - [CAP Theorem and Distributed Database Management Systems](https://towardsdatascience.com/cap-theorem-and-distributed-database-management-systems-5c2be977950e) с картинками 97 | - [What is the CAP Theorem?](https://medium.com/@bikas.katwal10/mongodb-vs-cassandra-vs-rdbms-where-do-they-stand-in-the-cap-theorem-1bae779a7a15) на богомерзком medium 98 | 99 | [к содержанию](#принципы-паттерны-практики-и-подходы-разработки-по) 100 | 101 | ## Чем композиция отличается от агрегации? 102 | 103 | Композиция (composition) - отношение "является частью" (HAS-A Relationship), при котором целое явно контролирует время жизни своей составной части. 104 | 105 | Агрегация (aggregation) - отношение "является частью" (HAS-A Relationship), при котором целое хоть и содержит свою составную часть, время их жизни не связано. 106 | 107 | Подробнее: 108 | - [Наследование vs Композиция vs Агрегация](http://sergeyteplyakov.blogspot.com/2012/12/vs-vs.html#:~:text=%D0%A0%D0%B0%D0%B7%D0%BD%D0%B8%D1%86%D0%B0%20%D0%BC%D0%B5%D0%B6%D0%B4%D1%83%20%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%B7%D0%B8%D1%86%D0%B8%D0%B5%D0%B9%20%D0%B8%20%D0%B0%D0%B3%D1%80%D0%B5%D0%B3%D0%B0%D1%86%D0%B8%D0%B5%D0%B9,%D1%81%D0%BE%D1%81%D1%82%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F%20%D1%87%D0%B0%D1%81%D1%82%D1%8C%20%D0%BF%D0%B5%D1%80%D0%B5%D0%B4%D0%B0%D0%B5%D1%82%D1%81%D1%8F%20%D1%87%D0%B5%D1%80%D0%B5%D0%B7%20%D0%BF%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80%D1%8B) 109 | - [Наследование, композиция, агрегация](https://habr.com/ru/post/354046/) 110 | - [Агрегация и композиция](https://ru.stackoverflow.com/questions/596697/%D0%90%D0%B3%D1%80%D0%B5%D0%B3%D0%B0%D1%86%D0%B8%D1%8F-%D0%B8-%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%B7%D0%B8%D1%86%D0%B8%D1%8F) 111 | 112 | [к содержанию](#принципы-паттерны-практики-и-подходы-разработки-по) 113 | 114 | ## Какие бывают тестовые объекты (заглушки)? Чем стаб отличается от мока? 115 | 116 | Тестовый объект (Test Double) - объекты, которые необходимы в тестах для подмены внешних зависимостей тестируемого кода 117 | Типы тестовых объектов: 118 | - **Dummy** - объекты, которые передаются в методы, но не используются. Например: заполнение списка параметров, часто это просто null 119 | - **Fake** - заглушка, являющаяся рабочей имплементацией, но с урезанной функциональностью и неприменима в production-окружении. Например: in-memory БД (fake database) 120 | - **Stub** - заглушка с жестко заданными ответами на вызовы со стороны тестируемого объекта (system under test - SUT) во время теста 121 | - **Spy** - это разновидность Stub, которая записывает информацию о произошедшем с ней, какие вызовы её методов были выполнены и сколько раз, как изменилось состояние и т.п. 122 | - **Mock** - заглушка с ожиданиями определённого набора вызовов, которые будут на ней выполнены в ходе теста 123 | 124 | Из данного набора заглушек только Mock используется для верификации поведения, остальные - для верификации состояния тестируемого объекта . 125 | 126 | Подробнее: 127 | - В [статье](https://habr.com/ru/post/116372/) на Хабре 128 | - [Mock vs Stub](https://www.maxshulga.ru/2012/03/mock-vs-stub.html) 129 | - [Mocks Aren't Stubs](https://www.martinfowler.com/articles/mocksArentStubs.html) от Мартина Фаулера 130 | - [Test Double](http://xunitpatterns.com/Test%20Double.html) 131 | - [Test Stub](http://xunitpatterns.com/Test%20Stub.html) 132 | - [Test Spy](http://xunitpatterns.com/Test%20Spy.html) 133 | - [Mock Object](http://xunitpatterns.com/Mock%20Object.html) 134 | - [Fake Object](http://xunitpatterns.com/Fake%20Object.html) 135 | - [Interaction Based Testing](http://spockframework.org/spock/docs/##0/interaction_based_testing.html) в Spock Framework 136 | - [Документация](https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html) Mockito 137 | - [Mockito Mock vs. Spy in Spring Boot Tests](https://dzone.com/articles/mockito-mock-vs-spy-in-spring-boot-tests) 138 | - [Tag: Mockito](https://www.baeldung.com/tag/mockito/) на Bealdung 139 | 140 | [к содержанию](#принципы-паттерны-практики-и-подходы-разработки-по) 141 | 142 | ## Дайте определение полиморфизму 143 | 144 | В общем виде определение [полиморфизма](https://en.wikipedia.org/wiki/Polymorphism_(computer_science)) приводит Бенджамин Пирс в своей книге [Типы в языках программирования](https://medium.com/devschacht/polymorphism-207d9f9cd78): 145 | > Термин “полиморфизм” обозначает семейство различных механизмов, позволяющих использовать один и тот же участок программы с различными типами в различных контекстах. 146 | 147 | Полиморфизм бывает следующих видов: 148 | 1. Универсальный полиморфизм. Он подразделяется на: 149 | - [Параметрический полиморфизм](https://ru.wikipedia.org/wiki/%D0%9F%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9_%D0%BF%D0%BE%D0%BB%D0%B8%D0%BC%D0%BE%D1%80%D1%84%D0%B8%D0%B7%D0%BC) - описывает вычисления в общем виде, абстрагируясь от конкретных типов, которые будут использованы. Параметрически полиморфные функции также называются обобщенными ([Generic](https://en.wikipedia.org/wiki/Generic_programming)). 150 | - Полиморфизм включений (inclusive) - описывает вычисления не только для конкретного типа, но для и всех его возможных подтипов. Отражает [принцип подстановки Барбары Лисков](https://en.wikipedia.org/wiki/Liskov_substitution_principle). 151 | 2. [Специальный полиморфизм](https://en.wikipedia.org/wiki/Ad_hoc_polymorphism) (или ad-hoc) - диспетчеризация (перенаправление) к одной или нескольким функциям для конкретного типа аргумента. Из него выделяют подтипы: 152 | - [Перегрузка](https://ru.wikipedia.org/wiki/%D0%9F%D0%B5%D1%80%D0%B5%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B0_%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D0%B4%D1%83%D1%80_%D0%B8_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9) (overloading) позволяет объявлять функции с одним и тем же именем, но с разными типами аргументов и их количеством (арностью). 153 | - Неявное [приведение типов](https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%82%D0%B8%D0%BF%D0%B0) - преобразование одного типа в другой по определённым правилам, описанным в стандарте языка, и выполняемое компилятором. 154 | 155 | Безотносительно к Java полиморфизм хорошо разобран в статье [Полиморфизм простыми словами](https://medium.com/devschacht/polymorphism-207d9f9cd78). 156 | В других источниках: 157 | - [Java Challengers #3: Полиморфизм и наследование](https://habr.com/ru/company/otus/blog/429120/) на Хабре 158 | - [Как полиморфизм реализован внутри JVM](https://habr.com/ru/company/otus/blog/467197/) на Хабре 159 | - [Все о переопределении в Java](https://habr.com/ru/company/otus/blog/347900/) на Хабре 160 | - [Неформальное введение в теорию типов](https://www.youtube.com/watch?v=RzzhKTiDSWQ) 161 | - Несколько глав из Java Virtual Machine Specification: [Invoking Methods](https://docs.oracle.com/javase/specs/jvms/se14/html/jvms-3.html#jvms-3.7), [invokevirtual](https://docs.oracle.com/javase/specs/jvms/se14/html/jvms-6.html#jvms-6.5.invokevirtual), [Linking](https://docs.oracle.com/javase/specs/jvms/se14/html/jvms-5.html#jvms-5.4) 162 | - Несколько глав из Java Language Specification: [Inheritance, Overriding, and Hiding](https://docs.oracle.com/javase/specs/jls/se14/html/jls-8.html#jls-8.4.8), [Conversions and Contexts](https://docs.oracle.com/javase/specs/jls/se14/html/jls-5.html), [Type Inference](https://docs.oracle.com/javase/specs/jls/se14/html/jls-18.html) 163 | 164 | [к содержанию](#принципы-паттерны-практики-и-подходы-разработки-по) 165 | 166 | ## Что такое REST? Какое API является RESTful? Чем REST отличается от SOAP? 167 | 168 | [REST](https://ru.wikipedia.org/wiki/REST) – это архитектурный стиль, который можно применить для реализации взаимодействия web-сервисов. 169 | Вот несколько признаков REST, которые хотят услышать большинство интервьюеров: 170 | - Концентрация на ресурсах 171 | - Ресурс имеет уникальный URI 172 | - Формат передачи - обычно JSON, но можно XML 173 | - Транспортный протокол - HTTP. Строго говоря - это необязательно, но по факту и в большинстве случаев так. Следующие пункты тоже. 174 | - Использование различных методов HTTP в соответствии с их семантикой и предназначением. GET: получить информацию о ресурсе; POST: создать новый ресурс; PUT: обновить существующий ресурс; DELETE: удалить ресурс. Иногда спорят об обновлении - PUT vs PATCH vs POST. 175 | - Использование кодов ответа HTTP в соответствии с их семантикой и предназначением. Хорошая [картинка](https://raw.githubusercontent.com/wiki/webmachine/webmachine/images/http-headers-status-v3.png) по определению HTTP-кода ответа. 176 | - [HATEOAS](https://habr.com/ru/post/483328/) обычно не используют и не спрашивают, но это тоже относится к REST, о чём можно упомянуть 177 | 178 | Чаще всего, на моей практике, спрашивают какой HTTP-метод для чего должен использоваться или как назвать URI, чтобы API было RESTful. Однако никакой спецификации или стандарта под это нет. И вообще, строго говоря, изначально REST - это *архитектурный стиль*, непривязанный ни к каким протоколам. Тема раскрыта в [этой статье](https://habr.com/ru/post/319984/) или в [этой](https://habr.com/ru/company/hexlet/blog/274675/) на Хабре - комментарии сочные. 179 | 180 | Вот принципы REST-архитектуры по Филдингу: 181 | - Модель клиент-сервер (Client–server) 182 | - Отсутствие состояния (Stateless) - у клиента и сервера нет необходимости отслеживать состояние друг друга 183 | - Кэширование (Cacheable) - ответы сервера должны помечаться как кэшируемы и некэшируемые 184 | - Единообразие интерфейса (Uniform interface) - идентификация ресурсов, манипуляция ресурсами через представление, "самодостаточные" сообщения, HATEOAS 185 | - Слои (Layered system) - в системе может быть больше одного слоя, но компоненты системы видит и взаимодействует только с соседним слоем. Кроме клиента и сервера может быть ещё прокси и шлюз 186 | - Код по требованию (необязательное ограничение) (Code on demand (optional)) - отправка сервером исполняемого кода клиенту 187 | 188 | [SOAP](https://ru.wikipedia.org/wiki/SOAP) - стандартизованный протокол обмена данными. 189 | Основные характеристики SOAP: 190 | - Формат сообщений - XML (SOAP-XML - Envelope, Header, Body, Fault) 191 | - SOAP-сервис должен иметь описание на языке [WSDL](https://ru.wikipedia.org/wiki/WSDL)(тоже XML) 192 | - SOAP поддерживает множество протоколов - (TCP, UDP, HTTP, SMTP, FTP и т.д.) 193 | - При использовании HTTP, поддерживаются методы GET и POST 194 | 195 | Тема горячая, интересная всем web-разработчикам, поэтому на Хабре имеется уйма статей на любой вкус. 196 | 197 | Теоритическо-практические: 198 | - Серия постов про REST - [введение](https://habr.com/ru/post/483202/), [REST vs SOAP](https://habr.com/ru/post/483204/), [Contract First](https://habr.com/ru/post/483206/), [Code First](https://habr.com/ru/post/483322/), [HATEOAS](https://habr.com/ru/post/483328/), [Рекомендации и примеры на Java и Spring](https://habr.com/ru/post/483374/) 199 | - [REST vs SOAP. Часть 1. Почувствуйте разницу](https://habr.com/ru/post/131343/) и [REST vs SOAP. Часть 2. Как проще и эффективнее организовать общение платформ?](https://habr.com/ru/post/134303/) 200 | - [Дао Вебсервиса. (Или да хватит же изобретать велосипеды!)](https://habr.com/ru/post/75248/) 201 | - [REST API Best Practices](https://habr.com/ru/post/351890/) 202 | - [Что такое RESTful на самом деле](https://habr.com/ru/company/hexlet/blog/274675/) 203 | - [Важные аспекты RESTful API для вашего проекта](https://habr.com/ru/post/108993/) 204 | - [Как построить REST-like API в крупном проекте](https://habr.com/ru/company/yamoney/blog/347390/) 205 | - [Разработка web API](https://habr.com/ru/post/181988/) 206 | - [RESTful API для сервера – делаем правильно (Часть 1)](https://habr.com/ru/post/144011/) и [RESTful API для сервера – делаем правильно (Часть 2)](https://habr.com/ru/post/144259/) 207 | - [Шпаргалки по безопасности: REST](https://habr.com/ru/company/acribia/blog/453384/) 208 | - [7 вредных советов проектировщику REST API](https://habr.com/ru/post/325884/) 209 | - [Самодокументированный JAX-WS с поддержкой XSD Restrictions](https://habr.com/ru/post/220387/) 210 | - [REST API на Java без фреймворков](https://habr.com/ru/company/otus/blog/480564/) 211 | - [Введение в Spring Boot: создание простого REST API на Java](https://habr.com/ru/post/435144/) 212 | - [Наипростейший RESTful сервис на Kotlin и Spring boot](https://habr.com/ru/post/343364/) 213 | - [SOAP-сервер на Java при участии Apache CXF и Spring](https://habr.com/ru/post/137543/) 214 | - [SOAP Web-сервис средствами Spring-WS](https://habr.com/ru/post/148403/) 215 | 216 | Холиварно-дискусионные: 217 | - [REST — это новый SOAP](https://habr.com/ru/company/mailru/blog/345184/) 218 | - [REST страсти по 200](https://habr.com/ru/post/440900/) 219 | - [REST API должен основываться на гипертексте](https://habr.com/ru/post/483528/) 220 | - [RESTful API — большая ложь](https://habr.com/ru/post/265845/) 221 | 222 | И на всякий случай: 223 | - [Сравнение REST и GraphQL](https://habr.com/ru/post/335158/) 224 | - [REST? Возьмите тупой JSON-RPC](https://habr.com/ru/post/441854/) 225 | 226 | А кроме Хабра: 227 | - [A Brief Introduction to REST](https://www.infoq.com/articles/rest-introduction/) 228 | - [REST CookBook](http://restcookbook.com/) 229 | - [RESTful Web APIs](http://restfulwebapis.org/) 230 | - [Introduction to Spring Data REST](https://www.baeldung.com/spring-data-rest-intro) 231 | - [What is REST](https://restfulapi.net/) 232 | - [Building REST services with Spring](https://spring.io/guides/tutorials/bookmarks/) 233 | - [Создание SOAP Web-сервиса](https://spring-projects.ru/guides/producing-web-service/) 234 | - [Спецификация SOAP](https://www.w3.org/TR/soap/) 235 | 236 | [к содержанию](#принципы-паттерны-практики-и-подходы-разработки-по) -------------------------------------------------------------------------------- /development/images/Cube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmorozov/awesome-java-backend-interview-rus/ef1007e6ae1649973f0511052a896cd7350c6244/development/images/Cube.png -------------------------------------------------------------------------------- /development/microservices.md: -------------------------------------------------------------------------------- 1 | [Оглавление](../README.md) 2 | 3 | # Microservices 4 | 5 | - [Чем сервисная архитектура отличается от микросервисной?](#чем-сервисная-архитектура-отличается-от-микросервисной) 6 | - [Какие есть ограничения у микросервисов? Назовите достоинства и недостатки микросервисной архитектуры.](#какие-есть-ограничения-у-микросервисов-назовите-достоинства-и-недостатки-микросервисной-архитектуры) 7 | - [Какие вы знаете паттерны микросервисов?](#какие-вы-знаете-паттерны-микросервисов) 8 | 9 | ## Чем сервисная архитектура отличается от микросервисной? 10 | 11 | [Сервис-ориентированная архитектура](https://en.wikipedia.org/wiki/Service-oriented_architecture) (SOA) - независимый от технологий, компаний и программных продуктов подход к разработке программного обеспечения на основе распределённых, слабосвязанных заменяемых компонентов с чётко определёнными интерфейсами и протоколами взаимодействия. Область охвата SOA — это всё предприятие, где происходит взаимодействие между приложениями. SOA делает ставку на доступ к бизнес-функциям предприятия через повторно используемые интерфейсы. 12 | 13 | [Сервис](https://web.archive.org/web/20160819141303/http://opengroup.org/soa/source-book/soa/soa.htm) в данной архитектуре: 14 | - представляет бизнес-логику с определённым результатом (много ответственностей, связанных единой бизнес-областью, целью, смыслом и т.п.); 15 | - может состоять из других сервисов или зависеть от них; 16 | - является "чёрным ящиком" для своих клиентов. 17 | Как и все серьёзные подходы к чему-либо имеет свой [манифест](http://www.soa-manifesto.org/default_russian.html) 18 | 19 | [Микросервисная архитектура](https://en.wikipedia.org/wiki/Microservices) (MSA) - частный случай SOA, побуждающий строить взаимодействие насколько это возможно и необходимо небольших, слабосвязанных, легко изменяемых и взаимозаменяемых компонентов (микросервисов). MSA ориентирована, в первую очередь, на структуру и компоненты отдельного приложения. 20 | 21 | Микросервис: 22 | - выполняет только одну достаточно элементарную и определённую функцию (Unix way - единственная ответственность); 23 | - деплоится и разрабатывается независимо от других микросервисов; 24 | - является независимым от других микросервисов (в том числе максимальная минимизация общего кода); 25 | - является "чёрным ящиком" для своих клиентов. 26 | 27 | Можно найти несколько источников, где MSA представляется как нечто новое и хорошее, а SOA - старое и умирающее. Часто это ещё и подаётся под соусом технологий. ИМХО - это больше маркетинговая туфта, чем хорошее сравнение. MSA и SOA не завязаны на технологии и не ограничивают в их использовании. Более того, оба подхода можно совмещать с пользой для бизнеса. 28 | 29 | Подробнее: 30 | - [Стандарты SOA](https://publications.opengroup.org/standards/soa) 31 | - [Микросервисы, SOA и API](https://www.ibm.com/developerworks/ru/library/1601_clark-trs/index.html) на ibm с отличными картинками о различиях SOA и MSA 32 | - [Monolith vs SOA vs MSA](https://medium.com/@leprosus/monolith-vs-soa-vs-msa-8767bfebe00) на medium 33 | - [Microservices vs SOA](https://dzone.com/articles/microservices-vs-soa-whats-the-difference) на DZone 34 | - [Колонка сравнения MSA и SOA](https://martinfowler.com/articles/microservices.html#MicroservicesAndSoa) на сайте Мартина Фаулера 35 | - [SOA и MSA](https://www.opengroup.org/soa/source-book/msawp/p3.htm) 36 | 37 | [к содержанию](#microservices) 38 | 39 | ## Какие есть ограничения у микросервисов? Назовите достоинства и недостатки микросервисной архитектуры. 40 | 41 | Достоинства: 42 | - Меньше кода на программный компонент (микросервис) -> проще и быстрее разрабатывать, поддерживать, тестировать, понимать, выбросить и переписать, реализовывать с помощью наиболее подходящих технологий и инструментов (в том числе на новье) 43 | - Меньше команда -> меньше проблем и конфликтов при мёрже и совместной разработке 44 | - Проще горизонтально масштабировать 45 | - Быстрее и проще как внедрять, так и откатывать 46 | 47 | Недостатки: 48 | - Увеличение накладных расходов на взаимодействие между программными компонентами (микросервисами) - обмен между ними выполняется по сети со всем вытекающим (сериализация/десериализация, задержки и т.д.) 49 | - Возможно появление необходимости распределённых транзакций 50 | - Увеличение объёмов логирования и мониторинга 51 | - Дублирование кода 52 | - Сложнее дебажить и отлавливать ошибки 53 | - Нужно быть готовым и способным продолжить работать, когда любой из микросервисов отвалится 54 | - Общая сложность растёт с количеством микросервисов 55 | 56 | Подробнее: 57 | - На Хабре есть целый [хаб](https://habr.com/ru/hub/microservices/) на тему микросервисов. Отмечу несколько статей по вопросу: [раз](https://habr.com/ru/post/416819/), [два](https://habr.com/ru/post/427215/), [три](https://habr.com/ru/post/311208/), [четыре](https://habr.com/ru/post/303778/), [пять](https://habr.com/ru/company/raiffeisenbank/blog/427953/), [шесть](https://habr.com/ru/post/489912/) и [Смерть микросервисного безумия в 2018 году](https://habr.com/ru/company/flant/blog/347518/) 58 | - Записка программиста [Преимущества и недостатки микросервисной архитектуры](https://eax.me/micro-service-architecture/) 59 | - [Статья](https://en.wikipedia.org/wiki/Microservices) на Wikipedia 60 | - [Microservices - Not A Free Lunch!](http://highscalability.com/blog/2014/4/8/microservices-not-a-free-lunch.html) 61 | - [Микросервисы — за и против](http://devopsru.com/news/2016-05-10-microservice-trade-offs.html) 62 | - [What are microservices?](https://raygun.com/blog/what-are-microservices/) 63 | - [To go or not to go micro: the pros and cons of microservices](https://medium.com/@goodrebels/to-go-or-not-to-go-micro-the-pros-and-cons-of-microservices-7967418ff06) 64 | - [Microservices in a Nutshell. Pros and Cons](https://phauer.com/2015/microservices-nutshell-pros-cons/) 65 | 66 | Посмотреть: 67 | - [Преимущества и недостатки микросервисной архитектуры в HeadHunter](https://www.youtube.com/watch?v=7WT_Rl6m2DU) 68 | - [Микросервисная Архитектура: проблемы и решения](https://www.youtube.com/watch?v=GIslwdE2DWY) 69 | - [Микросервисная архитектура](https://www.youtube.com/watch?v=wXaoKroEnp4) 70 | - [Микросервисная архитектура, подходы и технологии](https://www.youtube.com/watch?v=FF-GZ7iipwc) 71 | 72 | [к содержанию](#microservices) 73 | 74 | ## Какие вы знаете паттерны микросервисов? 75 | 76 | Как и в случае с ООП-паттернами, есть [книжка](https://microservices.io/book) с одноимённым названием. Есть на русском. На Хабре есть [статья-затравочка](https://habr.com/ru/company/piter/blog/462519/) от ИД "Питер". 77 | 78 | И есть другая книжка - [Microservice Patterns and Best Practices](https://www.packtpub.com/application-development/microservice-patterns-and-best-practices). На Medium имеется на неё [обзор](https://medium.com/@alexanderpolomodov/%D0%BE%D0%B1%D0%B7%D0%BE%D1%80-%D0%BA%D0%BD%D0%B8%D0%B3%D0%B8-microservice-patterns-and-best-practices-dce7785b9c45). 79 | 80 | На microservices.io можно найти наглядные и интерактивные схемы паттернов микросервисной архитектуры: [тут](https://microservices.io/patterns/microservices.html) или [здесь](https://microservices.io/patterns/). Каждый блок на схемах - это ссылка на статью по данному паттерну. Строго рекомендую. 81 | 82 | Также на Хабре есть [статья](https://habr.com/ru/company/piter/blog/275633/) по теме. Первым же комментарием к ней советуют тоже интересную книжку - [Enterprise Integration Patterns](https://www.enterpriseintegrationpatterns.com/index.html) и [список](https://www.enterpriseintegrationpatterns.com/patterns/messaging/toc.html) паттернов из неё. 83 | 84 | [к содержанию](#microservices) -------------------------------------------------------------------------------- /hibernate/hibernate.md: -------------------------------------------------------------------------------- 1 | [Оглавление](../README.md) 2 | 3 | # Hibernate 4 | 5 | - [Какие есть кэши в Hibernate и какие работают по умолчанию?](#какие-есть-кэши-в-hibernate-и-какие-работают-по-умолчанию) 6 | - [Чем отличается Lazy от Eager в Hibernate?](#чем-отличается-lazy-от-eager-в-hibernate) 7 | - [Что такое "проблема N+1 запроса" при использовании Hibernate? Когда возникает? Как решить? Как обнаружить?](#что-такое-проблема-n1-запроса-при-использовании-hibernate-когда-возникает-как-решить-как-обнаружить) 8 | - [Как описать составной ключ при использовании Hibernate?](#как-описать-составной-ключ-при-использовании-hibernate) 9 | - [Как можно отобразить наследование на БД с помощью JPA (Hibernate)?](#как-можно-отобразить-наследование-на-бд-с-помощью-jpa-hibernate) 10 | 11 | ## Какие есть кэши в Hibernate и какие работают по умолчанию? 12 | 13 | 3 уровня кеширования: 14 | - Кеш первого уровня (First-level cache). По умолчанию включен. 15 | - Кеш второго уровня (Second-level cache). По умолчанию отключен. 16 | - Кеш запросов (Query cache). По умолчанию отключен. 17 | 18 | Подробнее: 19 | - [Статья](https://habr.com/ru/post/135176/) на Хабре 20 | - [Документация](https://docs.jboss.org/hibernate/stable/orm/userguide/html_single/Hibernate_User_Guide.html#caching) и на Хабре есть [перевод](https://habr.com/ru/post/268747/) 21 | - [Статья](https://www.baeldung.com/hibernate-second-level-cache) на Baeldung 22 | - Статьи с практическими примерами о [First Level Cache](https://howtodoinjava.com/hibernate/understanding-hibernate-first-level-cache-with-example/) и [Second Level Cache](https://howtodoinjava.com/hibernate/how-hibernate-second-level-cache-works/) 23 | 24 | Углубиться в Hibernate нам всегда поможет [Vlad Mihalcea](https://vladmihalcea.com/): 25 | - Конечно же в его книге [High-Performance Java Persistence](https://vladmihalcea.teachable.com/p/high-performance-java-persistence-ebook/?utm_source=blog&utm_medium=banner&utm_campaign=banner): Часть 2, глава 16 - [Caching](https://vladmihalcea.com/high-performance-java-persistence-chapter-16-caching/) 26 | - [How does Hibernate Query Cache work](https://vladmihalcea.com/how-does-hibernate-query-cache-work/) 27 | - [How does Hibernate Collection Cache work](https://vladmihalcea.com/how-does-hibernate-collection-cache-work/) 28 | - [How does Hibernate store second-level cache entries](https://vladmihalcea.com/how-does-hibernate-store-second-level-cache-entries/) 29 | - [How does Hibernate NONSTRICT_READ_WRITE CacheConcurrencyStrategy work](https://vladmihalcea.com/how-does-hibernate-nonstrict_read_write-cacheconcurrencystrategy-work/) 30 | - [How does Hibernate TRANSACTIONAL CacheConcurrencyStrategy work](https://vladmihalcea.com/how-does-hibernate-transactional-cacheconcurrencystrategy-work/) 31 | - [How does Hibernate READ_ONLY CacheConcurrencyStrategy work](https://vladmihalcea.com/how-does-hibernate-read_only-cacheconcurrencystrategy-work/) 32 | - [How does Hibernate READ_WRITE CacheConcurrencyStrategy work](https://vladmihalcea.com/how-does-hibernate-read_write-cacheconcurrencystrategy-work/) 33 | 34 | [к содержанию](#hibernate) 35 | 36 | ## Чем отличается Lazy от Eager в Hibernate? 37 | 38 | - [Eager Loading](https://docs.oracle.com/javaee/7/api/javax/persistence/FetchType.html#EAGER) - стратегия загрузки, при которой подгрузка связанных сущностей происходит сразу. Для применения необходимо в аннотацию отношения (`@OneToOne`, `@ManyToOne`, `@OneToMany`, `@ManyToMany`) передать `fetch = FetchType.EAGER`. Используется по умолчанию для отношений `@OneToOne` и `@ManyToOne`. 39 | - [Lazy Loading](https://docs.oracle.com/javaee/7/api/javax/persistence/FetchType.html#LAZY) - стратегия загрузки, при которой подгрузка связанных сущностей откладывается как можно дольше. Чтобы задать такое поведение, нужно в аннотацию отношения (`@OneToOne`, `@ManyToOne`, `@OneToMany`, `@ManyToMany`) передать `fetch = FetchType.LAZY`. Используется по умолчанию для отношений `@OneToMany`, `@ManyToMany`. До момента загрузки используется proxy-объект, вместо реального. Если обратиться к такому LAZY-полю после закрытия сессии Hibernate, то получим [LazyInitializationException](https://docs.jboss.org/hibernate/orm/5.4/javadocs/org/hibernate/LazyInitializationException.html). 40 | 41 | Вопрос также связан с проблемой "N+1" и может плавно перетечь в её обсуждение. 42 | 43 | Почитать подробнее и с примерами можно в блоге Vlad Mihalcea: [раз](https://vladmihalcea.com/hibernate-facts-the-importance-of-fetch-strategy/), [два](https://vladmihalcea.com/eager-fetching-is-a-code-smell/) и про LazyInitializationException [три](https://vladmihalcea.com/the-best-way-to-handle-the-lazyinitializationexception/). 44 | 45 | [к содержанию](#hibernate) 46 | 47 | ## Что такое "проблема N+1 запроса" при использовании Hibernate? Когда возникает? Как решить? Как обнаружить? 48 | 49 | Проблема N+1 может возникнуть не только при использовании Hibernate, но и других библиотек и фреймворков для доступа к данным. 50 | 51 | В общем случае говорят о проблеме N+1 запроса, когда фреймворк выполняет N дополнительных запросов выборки данных, когда можно было обойтись всего одним. Соответственно от размера N зависит влияние проблемы на время ответа нашего приложения. Эту ситуацию нельзя обнаружить с помощью `slow query log`, ибо сами по себе запросы могут выполняться быстро, но их количество окажется большим или даже огромным. 52 | 53 | На такое можно нарваться даже при использовании plain sql (jdbc, JOOQ), когда у нас одна сущность (и соответственно таблица) связана с другой. И вот мы подгрузили одним запросом просто список из первых, а потом пошли и в цикле для каждой подгрузили связанную по одному запросу. "Да как вы это допустили!?". Да просто по запарке кто-то в цикле начал вызывать метод, у которого в глубине где-то делается запрос и привет. Как исправить? Использовать `JOIN` со связанной таблицей при чтении списка. Тогда понадобиться лишь один запрос. 54 | 55 | Теперь к Hibernate. Если на странице [документации](https://docs.jboss.org/hibernate/stable/core/userguide/html_single/Hibernate_User_Guide.html) поискать "N+1", то можно обнаружить несколько упоминаний данной проблемы. Тут опишу самые явные и распространённые. 56 | 57 | Например, возьмём стратегию выборки `FetchType.EAGER`. Она склонна к порождению N+1. А в отношении `@ManyToOne` по умолчанию используется именно она. Забыли в своём JPQL запросе заиспользовать `JOIN FETCH` и привет. А если нам и не нужны были связанные сущности, то тогда стоит задать стратегию `FetchType.LAZY`. 58 | 59 | Если уж упомянули `FetchType.LAZY`, то сразу стоит сказать, что одно её наличие не гарантирует отсутствие проблемы N+1. При выборке списка сущностей, связанные автоматически не подгрузились. А мы потом пошли в цикле по загруженному списку и стали обращаться к полям связанной сущности - и снова здравствуйте. Всё тот же `JOIN FETCH` нас спасёт и в этой ситуации. 60 | 61 | Но `JOIN FETCH` во многих случаях нас может привести к декартовому произведению, и тогда будет совсем bonjour. Для отношения `@OneToMany` это можно решить с помощью `FetchMode.SUBSELECT` - будет 2 запроса, но во втором запросе на получение списка связанных сущностей в условии выборки будет подзапрос на получение идентификаторов родительских сущностей. Т.е. запрос практически повторяется и он может быть тяжеловесным. 62 | 63 | Есть вариант лучше - вычитывать связанные сущности пачками. Мы можем добавить аннотацию `@BatchSize` и указать размер подгружаемой пачки записей в одном запросе. 64 | 65 | Ещё варианты: 66 | - [JPA EntityGraph](https://www.baeldung.com/jpa-entity-graph) 67 | - [Hibernate FetchProfile](https://docs.jboss.org/hibernate/stable/core/userguide/html_single/Hibernate_User_Guide.html#fetching-strategies-dynamic-fetching-profile-example) 68 | 69 | Чтобы обнаружить проблему N+1, нужно писать тесты с использованием библиотеки [db-util](https://github.com/vladmihalcea/db-util) от Vlad Mihalcea. Подробнее можно прочитать у него же в [блоге](https://vladmihalcea.com/how-to-detect-the-n-plus-one-query-problem-during-testing/). 70 | 71 | А вот JOOQ умеет обнаруживать N+1 автоматически, послушать об этом можно в [17-м эпизоде](https://it.asm0dey.ru/podcast/%d0%bf%d0%b0%d1%88%d0%b0-%d1%81%d0%bb%d0%b0%d0%b2%d0%b0-%d1%8d%d0%bf%d0%b8%d0%b7%d0%be%d0%b4-17/) (01:16:36) подкаста Паша+Слава. Подробнее в [документации](https://www.jooq.org/doc/3.11/manual-single-page/#diagnostics-repeated-statements) JOOQ. 72 | 73 | Углубиться в проблему можно: 74 | - В блоге Vlad Mihalcea: [раз](https://vladmihalcea.com/n-plus-1-query-problem/) и [два](https://vladmihalcea.com/hibernate-query-cache-n-plus-1-issue/) 75 | - На хабре упоминалась в статье [Hibernate — о чем молчат туториалы](https://habr.com/ru/post/416851/) 76 | - На DOU про стратегии загрузки коллекций в [JPA](https://dou.ua/lenta/articles/jpa-fetch-types/) и [Hibernate](https://dou.ua/lenta/articles/hibernate-fetch-types/) 77 | - В видео формате в докладе Николая Алименкова на JPoint ["Сделаем Hibernate снова быстрым"](https://youtu.be/b52Qz6qlic0?t=1224) 78 | 79 | [к содержанию](#hibernate) 80 | 81 | ## Как описать составной ключ при использовании Hibernate? 82 | 83 | На всякий случай: `составной ключ` - первичный ключ, состоящий из двух и более атрибутов. Вообще про ключи есть большая [статья](https://habr.com/ru/company/oleg-bunin/blog/348172/) на Хабре с ценными комментариями. 84 | 85 | Чтобы описать составной ключ при использовании Hibernate, нам необходимо создать под этот ключ отдельный класс с необходимыми полями и добавить ему аннотацию `@Embeddable`. Кроме того, он должен быть `Serializable` и иметь реализацию `equals` и `hashcode`. 86 | 87 | В самой же сущности, для которой мы описываем составной ключ, добавляем поле только что созданного класса ключа и вешаем на него аннотацию `@EmbeddedId`. 88 | 89 | Посмотреть примеры и углубиться в тему можно в [статье](https://vladmihalcea.com/the-best-way-to-map-a-composite-primary-key-with-jpa-and-hibernate/) Vlad Mihalcea или в [документации](https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#identifiers-composite-aggregated) Hibernate. 90 | 91 | [к содержанию](#hibernate) 92 | 93 | ## Как можно отобразить наследование на БД с помощью JPA (Hibernate)? 94 | 95 | Есть 4 способа отобразить наследование на БД с помощью JPA (Hibernate): 96 | - [MappedSuperclass](https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#entity-inheritance-mapped-superclass) - поля родителя содержатся в каждой таблице для каждого дочернего класса. Базовый класс отдельной таблицы не имеет. На базовый класс навешиваем [@MappedSuperClass](https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/MappedSuperclass.html), а вот на дочерние `@Entity`. Если в таблице потомка поле родителя называется не так, как указано в родительском классе, то его нужно смаппить с помощью аннотации [@AttributeOverride](https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/AttributeOverride.html) в классе этого потомка. Родитель не может участвовать в ассоциации. При полиморфных запросах у нас будут отдельные запросы для каждой таблицы. 97 | - [Single table](https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#entity-inheritance-single-table) - вся иерархия классов в одной таблице. Чтобы различать классы, необходимо добавить колонку-дискриминатор. В данной стратегии на родительский `@Entity`-класс навешивается `@Inheritance(strategy = InheritanceType.SINGLE_TABLE)` и `@DiscriminatorColumn(name = "YOUR_DISCRIMINATOR_COLUMN_NAME")` (по умолчанию имя колонки `DTYPE` и тип `VARCHAR`). В каждом подклассе указываем `@DiscriminatorValue("ThisChildName")` со значением, которое будет храниться в колонке-дискриминаторе для данного класса. Если нет возможности добавить колонку, то можно использовать аннотацию [@DiscriminatorFormula](https://docs.jboss.org/hibernate/orm/5.4/javadocs/org/hibernate/annotations/DiscriminatorFormula.html), в которой указать выражение `CASE...WHEN` - это не по JPA, фишка Hibernate. Денормализация. Простые запросы к одной таблице. Возможное нарушение целостности - столбцы подклассов могут содержать `NULL`. 98 | - [Joined table](https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#entity-inheritance-joined-table) - отдельные таблицы для всех классов иерархии, включая родителя. В каждой таблице только свои поля, а в дочерних добавляется внешний (он же первичный) ключ для связи с родительской таблицей. В `@Entity`-класс родителя добавляем `@Inheritance(strategy = InheritanceType.JOINED)`. Для полиморфных запросов используются `JOIN`, а также выражение `CASE...WHEN`, вычисляющее значение поля `_clazz`, которое заполняется литералами (0 (родитель), 1, 2 и т.д.) и помогает Hibernate определить какого класса будет экземпляр. 99 | - [Table per class](https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#entity-inheritance-table-per-class) - также как и в `MappedSuperclass`, имеем отдельные таблицы для каждого подкласса. Базовый класс отдельной таблицы не имеет. По [спецификации](https://download.oracle.com/otn-pub/jcp/persistence-2_2-mrel-spec/JavaPersistence.pdf) JPA 2.2 (раздел 2.12) данная стратегия является опциональной, но в Hibernate реализована, поэтому продолжим. В данном случае на базовый класс мы навешиваем `@Entity` и `@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)`. Поле первичного ключа (`@Id`) обязательно для родительского класса. Также аннотация `@AttributeOverride` в этой стратегии не работает - называйте родительские поля в таблицах сразу единообразно. Полиморфный запрос будет использовать `UNION` для объединения таблиц. Чтобы различить при создании экземпляров подклассы, Hibernate добавляет поле `_clazz` в запросы, содержащие литералы (1, 2 и т.д.). А одинаковый набор столбцов для объединения добирается как `NULL AS some_field`. Родитель может участвовать в ассоциации с другими сущностями. 100 | 101 | Почитать ещё по теме с примерами можно: 102 | - На Хабре: [раз](https://habr.com/ru/post/337488/), [два](https://habr.com/ru/post/416851/) 103 | - В блоге Vlad Mahalcea: [Влад демонстрирует лучшую стратегию](https://vladmihalcea.com/the-best-way-to-use-entity-inheritance-with-jpa-and-hibernate/) и [рассказывает про MappedSuperclass](https://vladmihalcea.com/how-to-inherit-properties-from-a-base-class-entity-using-mappedsuperclass-with-jpa-and-hibernate/) 104 | 105 | Кроме того, можно заглянуть в JavaDoc с аннотациями: 106 | - [JPA](https://docs.jboss.org/hibernate/jpa/2.2/api/javax/persistence/package-summary.html) 107 | - [Hibernate](https://docs.jboss.org/hibernate/orm/5.4/javadocs/org/hibernate/annotations/package-summary.html) 108 | 109 | Или почитать спецификацию [JPA](https://download.oracle.com/otn-pub/jcp/persistence-2_2-mrel-spec/JavaPersistence.pdf) 2.2. Ещё есть [книжка](https://www.amazon.com/Understanding-JPA-2-2-Persistence-fascicle-ebook/dp/B07RWPXPS6) с толкованием данного pdf. 110 | 111 | [к содержанию](#hibernate) -------------------------------------------------------------------------------- /java/collections.md: -------------------------------------------------------------------------------- 1 | [Оглавление](../README.md) 2 | 3 | # Collection Framework 4 | 5 | - [Вопросы про методы `Equals`, `hashcode` и их связь с `HashMap`.](#вопросы-про-методы-equals-hashcode-и-их-связь-с-hashmap) 6 | - [Вопросы про списки: какие есть, алгоритмическая сложность, какой брать для вставки в середину, в конец, в огурец.](#вопросы-про-списки-какие-есть-алгоритмическая-сложность-какой-брать-для-вставки-в-середину-в-конец-в-огурец) 7 | - [Перечислите методы класса `Object`.](#перечислите-методы-класса-object) 8 | - [Что можно положить и достать из `List`, а что с `List`? Что такое ковариантность, контрвариантность, инвариантность?](#что-можно-положить-и-достать-из-list-extends-number-а-что-с-list-super-number-что-такое-ковариантность-контрвариантность-инвариантность) 9 | - [Что внутри и как работают TreeSet/TreeMap? В чем идея Красно-черного дерева?](#что-внутри-и-как-работают-treesettreemap-в-чем-идея-красно-черного-дерева) 10 | 11 | ## Вопросы про методы `Equals`, `hashcode` и их связь с `HashMap`. 12 | 13 | Контракт. Далее разговор переходит к устройству `HashMap`. Как устроена внутри? А происходит в случае возникновения коллизии? Назовите алгоритмические сложности поиска, чтения, удаления из элемента мапы. А что если ключ - это массив байтов? А может быть так, что мы положим элемент в мапу, а потом не найдем? Обсасывают бедную мапу со всех сторон. Самая популярная тема для обсуждения. 14 | 15 | Контракт `equals` и `hashcode`: 16 | 1. Для одного и того же объекта хэшкоды одинаковые. 17 | 1. Если объекты равны по equals, то и хэшкоды одинаковые. 18 | 1. Если же хэшкоды равны, то объекты могут быть не равны по equals (коллизия). 19 | 1. Если хэшкоды разные, то и объекты разные. 20 | 21 | В [статье](https://habr.com/ru/post/168195/) на Хабре это подробно разобрано, если кому-то покажется мало. 22 | 23 | Про `HashMap` и вопросы по ним есть несколько отличных статей на Хабре ([в картинках](https://habr.com/ru/post/128017/), [с дополнениями из Java 8](https://habr.com/ru/post/421179/), [а тут вопросы-ответы про коллекциям](https://habr.com/ru/post/162017/)). Кроме того, можно посмотреть исходный код в вашей любимой IDE. Можете сделать себе конспект и повесить на стену :) 24 | 25 | [к содержанию](#collection-framework) 26 | 27 | ## Вопросы про списки: какие есть, алгоритмическая сложность, какой брать для вставки в середину, в конец, в огурец. 28 | 29 | По сути это вопрос про `ArrayList` vs `LinkedList`. Опять же, заезженная пластинка, разобранная на Хабре - [вопросы-ответы про коллекциям](https://habr.com/ru/post/162017/), [ArrayList в картинках](https://habr.com/ru/post/128269/), [LinkedList в картинках](https://habr.com/ru/post/127864/), [Что «под капотом» у LinkedList](https://habr.com/ru/post/337558/). Посмотреть исходники тоже полезно. Например, можно понтануться тем, что вставка в середину в `ArrayList` выполняется с помощью нативно реализованной функции `System.arraycopy`, поэтому не всё так плохо, как могло бы быть в этом случае. 30 | 31 | [к содержанию](#collection-framework) 32 | 33 | ## Перечислите методы класса `Object`. 34 | 35 | Этот вопрос далее перетекает либо в обсуждение `HashMap`, либо в основы многопоточного программирования на Java. 36 | 37 | Чтобы вы вдруг внезапно не забыли каких-то методов (как это сделал я :D), привожу вам список и [ссылку на JavaDoc](https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/lang/Object.html): 38 | - clone 39 | - equals 40 | - finalize (Deprecated) 41 | - getClass 42 | - hashCode 43 | - toString 44 | - notify 45 | - notifyAll 46 | - wait 47 | 48 | Также можно почитать, что там вообще есть в исходниках `Object` в [статье](https://habr.com/ru/post/265373/) на Хабре. 49 | 50 | [к содержанию](#collection-framework) 51 | 52 | ## Что можно положить и достать из `List`, а что с `List`? Что такое ковариантность, контрвариантность, инвариантность? 53 | 54 | Тут речь пойдёт про PECS - Producer extends, Consumer super (Joshua Bloch, [Effective Java](https://books.google.ru/books?id=ka2VUBqHiWkC&pg=PA136&lpg=PA136&dq=bloch+effective+java+pecs+mnemonic&source=bl&ots=yYKnPjt-P-&sig=JGT8qexAAldJ5xYPepbBQ5uude0&hl=en&sa=X&ei=Cb3GUv-sNIuK5ATM7oD4Dw&ved=0CCgQ6AEwAA#v=onepage&q=bloch%20effective%20java%20pecs%20mnemonic&f=false)). А также вариантность — перенос наследования исходных типов на производные от них типы (контейнеры, делегаты, обобщения). 55 | 56 | Ковариантность (covariance) - перенос наследования исходных типов на производные от них типы в прямом порядке. 57 | Переменной типа __List__ разрешено присвоить экземпляр списка, параметризованного _T_ или его подклассом, но не родительским классом. В список типа __List__ нельзя добавить никакой объект (можно только `null`) - нельзя гарантировать какого именно типа экземпляр списка будет присвоен переменной, поэтому нельзя гарантировать, что добавляемый объект разрешён в таком списке. Однако, из списка можно прочитать объект и он будет типа _T_ и экземпляром либо _T_, либо одного из подклассов _T_. 58 | Соответственно, `List` можно присвоить `ArrayList` или `ArrayList`, но не `ArrayList`. Метод `get` возвращает `Number`, за которым может скрываться экземпляр `Integer` или другого наследника `Number`. 59 | Массивы также ковариантны. 60 | Переопределение методов, начиная с Java 5, ковариантно относительно типа результата и исключений. 61 | 62 | `List` аналогичен `List` со всеми вытекающими. 63 | 64 | Контрвариантность (contravariance) - перенос наследования исходных типов на производные от них типы в обратном порядке. 65 | Переменной типа __List__ разрешено присвоить экземпляр списка, параметризованного _T_ или его родительским классом, но не его подклассом. В список типа __List__ можно добавить экземпляр _T_ или его подкласса, но нельзя добавить экземпляр родительских для _T_ классов. Из такого списка с гарантией можно прочитать только `Object`, за которым может скрываться неизвестно какой его подкласс. 66 | 67 | Соответственно, `List` можно присвоить либо `ArrayList`, либо `ArrayList`, но не список наследников `Number`(т.е. никаких `ArrayList`). Можно добавить экземпляр `Integer` или `Double` (можно было бы `Number`, но он абстрактный), но нельзя - `Object`. Метод `get` возвращает `Object` - точнее сказать нельзя. 68 | 69 | Инвариантность - наследование исходных типов не переносится на производные. 70 | Переменной типа __List__ разрешено присвоить экземпляр списка, параметризованного только _T_. В список можно добавить экземпляр _T_ или его подкласса. Список возвращает _T_, за которым может скрываться экземпляр его подкласса. 71 | 72 | Соответственно, `List` можно присвоить `ArrayList`, но не `ArrayList` или `ArrayList`. Можно добавить экземпляр `Integer` или `Double` (можно было бы `Number`, но он абстрактный), но нельзя - `Object`. Метод `get` возвращает `Number`, за которым может скрываться экземпляр `Integer` или другого наследника `Number`. 73 | 74 | Подробнее: 75 | - На Хабре: [Погружаемся в Generics](https://habr.com/ru/company/sberbank/blog/416413/), [Используем в API](https://habr.com/ru/post/207360/), изучаем [вариантность в программировании](https://habr.com/ru/post/218753/) 76 | - Посмотреть доклад Александра Маторина [Неочевидные Дженерики](https://www.youtube.com/watch?v=_0c9Fd9FacU&feature=youtu.be&t=1204) 77 | - В одном из ответов на вопрос [Generics FAQ](http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ103) 78 | - [Как ограничивается тип generic параметра?](https://itsobes.ru/JavaSobes/kak-ogranichivaetsia-tip-generic-parametra/) 79 | - [Что такое ковариантность и контравариантность?](https://itsobes.ru/JavaSobes/chto-takoe-kovariantnost-i-kontravariantnost/) 80 | - В одном из объяснений на StackOverflow: [раз](https://stackoverflow.com/questions/4343202/difference-between-super-t-and-extends-t-in-java), [два](https://stackoverflow.com/questions/2776975/how-can-i-add-to-list-extends-number-data-structures/2777297#2777297), [три](https://stackoverflow.com/questions/2723397/what-is-pecs-producer-extends-consumer-super) 81 | - [Ковариантность и контравариантность](https://habibutsu.github.io/variance.html) с точки зрения математики, теории категорий и программирования 82 | - [Ковариантность и контравариантность](https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)) в Wikipedia 83 | - [Wildcards](https://docs.oracle.com/javase/tutorial/java/generics/wildcards.html) в официальном туториале Oracle 84 | 85 | [к содержанию](#collection-framework) 86 | 87 | ## Что внутри и как работают TreeSet/TreeMap? В чем идея Красно-черного дерева? 88 | 89 | [TreeMap](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/TreeMap.html) - реализация [NavigableMap](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/NavigableMap.html), основанная на [красно-чёрном дереве](https://en.wikipedia.org/wiki/Red%E2%80%93black_tree). Элементы отсортированы по ключам в [натуральном порядке](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Comparable.html) или с помощью [Comparator](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/Comparator.html), указанного при создании мапы, в зависимости от использовавшегося конструктора. Гарантирует логарифмическое время выполнения методов `containsKey`, `get`, `put` и `remove`. 90 | [TreeSet](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/TreeSet.html) - реализация [NavigableSet](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/NavigableSet.html), основанная на `TreeMap`. Элементы отсортированы в [натуральном порядке](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Comparable.html) или с помощью [Comparator](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/Comparator.html), указанного при создании множества, в зависимости от использовавшегося конструктора. Гарантирует логарифмическое время выполнения методов `add`, `contains` и `remove`. 91 | 92 | Обе коллекции НЕ `synchronized` и итератор по ним может выбросить [ConcurrentModificationException](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/ConcurrentModificationException.html). 93 | 94 | Если в эти коллекции при использовании натурального порядка сортировки в качестве ключа попытаться положить `null`, то получим `NullPointerException`. В случае с компаратором поведение с `null` будет зависеть от реализации компаратора. До 7-й Java с добавлением `null` в `TreeMap` и `TreeSet` был [баг](https://habr.com/ru/post/164027/). 95 | 96 | Самая важная особенность красно-чёрного дерева в том, что оно умеет само себя балансировать, поэтому не важно в каком порядке будут добавляться в него элементы, преимущества этой структуры данных будут сохраняться. Сбалансированность достигается за счёт поддержания правил красно-чёрной раскраски вершин: 97 | - Вершина может быть либо красной, либо чёрной и имеет двух потомков 98 | - Красная вершина не может быть дочерней для красной вершины 99 | - Количество чёрных вершин от корня до листа включительно одинаково для любого листа 100 | - Корень дерева является чёрным 101 | - Все листья — чёрные и не содержат данных 102 | 103 | Подробнее: 104 | - [Статья](https://habr.com/ru/post/66926/) про сбалансированные бинарные деревья на Хабре 105 | - [Java собеседование. Коллекции](https://habr.com/ru/post/162017/) на Хабре 106 | - [Java TreeMap vs HashMap](https://www.baeldung.com/java-treemap-vs-hashmap) 107 | - [10 TreeMap Java Interview Questions](https://javahungry.blogspot.com/2014/06/how-treemap-works-ten-treemap-java-interview-questions.html) и [TreeSet Interview Questions](https://javahungry.blogspot.com/2015/10/how-treeset-works-internally-in-java-interview-questions.html) 108 | - [Internal Working of TreeMap in Java](https://www.dineshonjava.com/internal-working-of-treemap-in-java/) 109 | - [A Guide to TreeMap in Java](https://www.baeldung.com/java-treemap) и [A Guide to TreeSet in Java](https://www.baeldung.com/java-tree-set) на Bealdung 110 | - [Красно-черные деревья: коротко и ясно](https://habr.com/ru/post/330644/) на Хабре 111 | - [Балансировка красно-чёрных деревьев — Три случая](https://habr.com/ru/company/otus/blog/472040/) на Хабре 112 | - [Красно-чёрное дерево](https://neerc.ifmo.ru/wiki/index.php?title=%D0%9A%D1%80%D0%B0%D1%81%D0%BD%D0%BE-%D1%87%D0%B5%D1%80%D0%BD%D0%BE%D0%B5_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE) 113 | - [Визуализация](https://www.cs.usfca.edu/~galles/visualization/RedBlack.html) красно-чёрного дерева. И [ещё](http://www.cs.armstrong.edu/liang/animation/web/RBTree.html). А вот [исходники](https://github.com/nadakamel/RedBlackTree-Visualization) 114 | 115 | [к содержанию](#collection-framework) -------------------------------------------------------------------------------- /java/concurrency.md: -------------------------------------------------------------------------------- 1 | [Оглавление](../README.md) 2 | 3 | # Java Concurrency 4 | 5 | - [Расскажите про методы `wait`, `notify`, `notifyAll` и ключевое слово `synchronized`](#расскажите-про-методы-wait-notify-notifyall-и-ключевое-слово-synchronized) 6 | - [JMM. Зачем нужно volatile. Популярный вопрос](#jmm-зачем-нужно-volatile-популярный-вопрос) 7 | - [Что такое Executor и ExecutorService, Thread pool и зачем нужны?](#что-такое-executor-и-executorservice-thread-pool-и-зачем-нужны) 8 | - [Что внутри параллельных стримов? На каком пуле работают параллельные стримы и в чем его особенность?](#что-внутри-параллельных-стримов-на-каком-пуле-работают-параллельные-стримы-и-в-чем-его-особенность) 9 | - [Как работает ConcurrentHashMap?](#как-работает-concurrenthashmap) 10 | - [Как работают Атомики?](#как-работают-атомики) 11 | - [Что такое ThreadLocal переменные?](#что-такое-threadlocal-переменные) 12 | - [Чем поток отличается от процесса?](#чем-поток-отличается-от-процесса) 13 | 14 | ## Расскажите про методы `wait`, `notify`, `notifyAll` и ключевое слово `synchronized` 15 | 16 | В принципе, статьи на [Baeldung](https://www.baeldung.com/java-wait-notify) должно хватить. Лучше, конечно, пописать код с использованием `wait`, `notify`, `notifyAll` и `synchronized` руками. Также можно почитать [официальный туториал](https://docs.oracle.com/javase/tutorial/essential/concurrency/index.html) от Oracle по Concurrency в Java. 17 | 18 | Но если хотите пойти глубже, то хаброписатели опять спешат на помощь - [тут](https://habr.com/ru/post/143237/). А также Java Language Specification, [раздел 17.1 и 17.2](https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html). 19 | 20 | [к содержанию](#java-concurrency) 21 | 22 | ## JMM. Зачем нужно volatile. Популярный вопрос 23 | 24 | Не знаю как у вас, но у меня при упоминании JMM молниеносно всплывает в голове Алексей Шипилёв и его доклады - [раз](https://www.youtube.com/watch?v=noDnSV7NCtw), [два](https://www.youtube.com/watch?v=Ky1_5mabd18), [три](https://www.youtube.com/watch?v=C6b_dFtujKo). Если вы больше чтец, чем смотрец, то Алексея можно и почитать - [ать](https://shipilev.net/blog/2014/jmm-pragmatics/), [два](https://shipilev.net/blog/2016/close-encounters-of-jmm-kind/). 25 | 26 | Кроме того, абсолютно не будет лишним посмотреть [доклад](https://www.youtube.com/watch?v=hxIRyqHRnjE&list=PLU17dD8nR0m7GusjRbl42KE94a3dlpx_a&index=3&t=0s) Романа Елизарова по теоретическому минимуму JMM. 27 | 28 | Если совсем нет времени, то можно пробежаться по небольшой [статейке](http://www.javaspecialist.ru/2011/06/java-memory-model.html) по JMM. Если есть время и интерес, тогда углубляемся в тему через [статью](https://habr.com/ru/post/440590/) на Хабре. А ещё на Хабре есть неплохой перевод статьи "Многопоточность. Java-модель памяти": [часть 1](https://habr.com/ru/post/510454/) и [часть 2](https://habr.com/ru/post/510618/). 29 | 30 | Несомненным источником истины является Java Language Specification, [раздел 17.4](https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html). 31 | 32 | Также ответ на этот вопрос можно [прочитать](https://itsobes.ru/JavaSobes/chto-delaet-volatile/) на itsobes.ru. 33 | А ещё можно ознакомиться с вопросом на JVM-уровне в статье [How ‘volatile’ works on JVM level?](https://medium.com/@dredwardhyde/how-volatile-works-on-jvm-level-7a250d38435d) на Medium. 34 | 35 | [к содержанию](#java-concurrency) 36 | 37 | ## Что такое Executor и ExecutorService, Thread pool и зачем нужны? 38 | 39 | Создавать и убивать потоки - дорого. Давайте создадим N потоков (Thread pool) и будем их переиспользовать. А давайте. Вот [тут](https://www.ibm.com/developerworks/ru/library/j-jtp0730/index.html) описано развёрнуто. 40 | 41 | [Executor](https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/util/concurrent/Executor.html) (`void execute​(Runnable command)` - вот и весь интерфейс) и [ExecutorService](https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/util/concurrent/ExecutorService.html) (уже покруче, может запускать Callable и не только) - грубо говоря, интерфейсы выполняторов параллельных задач. А реализуют их различные выполняторы на пулах потоков. Экземпляры готовых конкретных выполняторов можно получить с помощью класса [Executors](https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/util/concurrent/Executors.html). Если смелый-умелый и зачем-то надо, то можно и самому реализовать, конечно. 42 | 43 | Также подробнее можно почитать: 44 | - [Cтатью](https://habr.com/ru/post/326146/) на Хабре 45 | - На Baeldung: [раз](https://www.baeldung.com/java-executor-service-tutorial) и [два](https://www.baeldung.com/thread-pool-java-and-guava) 46 | - Официальный [туториал](https://docs.oracle.com/javase/tutorial/essential/concurrency/executors.html) от Oracle 47 | 48 | [к содержанию](#java-concurrency) 49 | 50 | ## Что внутри параллельных стримов? На каком пуле работают параллельные стримы и в чем его особенность? 51 | 52 | По умолчанию parallel stream использует [ForkJoinPool.commonPool](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinPool.html#commonPool--) размером `Runtime.getRuntime().availableProcessors() — 1`. Common pool создаётся статически при первом обращении к `ForkJoinPool` и живёт до `System::exit` (игнорирует `shutdown()` или `shutdownNow()`). Когда некий поток отправляет задачу в common pool, то pool может использовать его же в качестве воркера. Common pool один на всё приложение. Можно запустить stream на [отдельном](https://www.baeldung.com/java-8-parallel-streams-custom-threadpool) `ForkJoinPool` - завернуть параллельный stream в `Callable` и передать на вход методу `submit` созданного `ForkJoinPool`. Этот трюк работает благодаря методу [fork()](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinTask.html#fork--) из `ForkJoinPool` ([тут](https://blog.krecan.net/2014/03/18/how-to-specify-thread-pool-for-java-8-parallel-streams/) подробности). 53 | 54 | Сам по себе [ForkJoinPool](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinPool.html) представляет реализацию [ExecutorService](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html), выполняющую [ForkJoinTask](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinTask.html) ([RecursiveAction](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/RecursiveAction.html) и [RecursiveTask](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/RecursiveTask.html)). Данный pool создан для упрощения распараллеливания рекурсивных задач и утилизации породивших подзадачу потоков. `ForkJoinPool` использует подход [work stealing](https://en.wikipedia.org/wiki/Work_stealing) - у каждого потока есть его локальная очередь задач, из хвоста которой другие потоки могут тырить себе задачи, если у них закончились свои. Украденная задача делится и заполняет очередь задач потока. 55 | 56 | Подробнее: 57 | - В статьях [Stream API & ForkJoinPool](https://habr.com/ru/company/otus/blog/338770/) и [Fork/Join Framework в Java 7](https://habr.com/ru/post/128985/) на Хабре 58 | - Посмотреть доклад Алексея Шипилёва [ForkJoinPool в Java 8](https://www.youtube.com/watch?v=t0dGLFtRR9c) 59 | - В статьях [Guide to the Fork/Join Framework in Java](https://www.baeldung.com/java-fork-join) и [Guide to Work Stealing in Java](https://www.baeldung.com/java-work-stealing) на Baeldung 60 | - JavaDoc к [ForkJoinPool](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinPool.html) 61 | - В статье [Think Twice Before Using Java 8 Parallel Streams](https://dzone.com/articles/think-twice-using-java-8) на DZone 62 | - В статье [Java Parallel Streams Are Bad for Your Health!](https://www.jrebel.com/blog/parallel-java-streams) в блоге JRebel 63 | - С примерами и картинками - [Java Parallel Stream](https://java2blog.com/java-8-parallel-stream/) 64 | - С графиками в [How does the Fork/Join framework act under different configurations?](https://blog.overops.com/forkjoin-framework-vs-parallel-streams-vs-executorservice-the-ultimate-benchmark/) 65 | - [Как работают параллельные стримы?](https://itsobes.ru/JavaSobes/kak-rabotaiut-parallelnye-strimy/) 66 | 67 | [к содержанию](#java-concurrency) 68 | 69 | ## Как работает ConcurrentHashMap? 70 | [ConcurrentHashMap](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/ConcurrentHashMap.html) - это потокобезопасная мапа (карта, словарь, ассоциативный массив, но тут и далее просто "мапа"), у которой отсутствуют блокировки на всю мапу целиком. 71 | 72 | Особенности реализации: 73 | - Поля элемента мапы (`Node`) `val` (значение) и `next`(следующее значение по данному ключу в цепочке или дереве), а также таблица бакетов (`Node[] table`) объявлены как `volatile` 74 | - Для операций вставки первого элемента в бакет используется [CAS](https://en.wikipedia.org/wiki/Compare-and-swap) - алгоритм, а для других операций обновления в этой корзине (insert, delete, replace) блокировки 75 | - Каждый бакет может блокироваться независимо путём блокировки первого элемента в корзине 76 | - Таблице бакетов требуется volatile/atomic чтения, запись и CAS, поэтому используются intrinsics-операции (`jdk.internal.misc.Unsafe`) 77 | - Concurrent resizing таблицы бакетов 78 | - Ленивая инициализация таблицы бакетов 79 | - При подсчёте количества элементов используется специальная реализация [LongAdder](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/LongAdder.html) 80 | 81 | В результате имеем: 82 | - Извлечение значения возвращает последний результат завершенного обновления мапы на момент начала извлечения. Или перефразируя, любой `non-null` результат, возвращаемый `get(key)` связан отношением `happens-before` со вставкой или обновлением по этому ключу 83 | - Итераторы по `ConcurrentHashMap` возвращают элементы отображающие состояние мапы на определённый момент времени - они не бросают `ConcurrentModificationException`, но предназначены для использования одним потоком одновременно 84 | - Нельзя полагаться на точность агрегирующих методов (`size`, `isEmpty`, `containsValue`), если мапа подвергается изменениям в разных потоках 85 | - Не позволяет использовать `null`, который однозначно воспринимается как отсутствие значения 86 | - Поддерживает потокобезопасные, затрагивающие все (или многие) элементы мапы, операции - `forEach`, `search`, `reduce` (bulk operations). Данные операции принимают на вход функции, которые не должны полагаться на какой-либо порядок элементов в мапе и в идеале должны быть чистыми (за исключением `forEach`). На вход данные операции также принимают `parallelismThreshold` - операции будут выполняться последовательно, если текущий размер мапы меньше `parallelismThreshold`. Значение `Long.MAX_VALUE` сделает операцию точно последовательной. Значение `1` максимизирует параллелизм и утилизацию `ForkJoinPool.commonPool()`, который будет использоваться для параллельных вычислений 87 | 88 | На Хабре есть несколько устаревшая [статья](https://habr.com/ru/post/132884/) - будьте внимательны и осторожны с java 8 произошли изменения. Класс `Segment` максимально урезан и сохранён только для обратной совместимости при сериализации, где и используется. `concurrencyLevel` также оставлен лишь для обратной совместимости и теперь служит в конструкторе только для увеличения `initialCapacity` до количества предполагаемых потоков-потребителей мапы: 89 | ```java 90 | if (initialCapacity < concurrencyLevel) // Use at least as many bins 91 | initialCapacity = concurrencyLevel; // as estimated threads 92 | ``` 93 | Есть более современная [статья](https://habr.com/ru/post/327186/) с примером реализации ConcurrentMap. Также можно почитать [гайд](https://www.baeldung.com/java-concurrent-map) по ConcurrentMap на Baeldung. 94 | 95 | [к содержанию](#java-concurrency) 96 | 97 | ## Как работают Атомики? 98 | 99 | Атомарная операция — это операция, которая выполняется полностью или не выполняется совсем, частичное выполнение невозможно. 100 | 101 | Атомики - это классы, которые выполняют операции изменения своего значения атомарно, т.о. они поддерживают lock-free thread-safe использование переменных. Достигается это с помощью алгоритма [compare-and-swap (CAS)](https://en.wikipedia.org/wiki/Compare-and-swap) и работает быстрее, чем аналогичные реализации с блокировками. На уровне инструкций большинства процессоров имеется поддержка CAS. 102 | 103 | В общем случае работу Атомиков можно описать следующим образом. Атомик хранит некоторое `volatile` значение `value`, для изменения которого используется метод `compareAndSet(current, new)`, поэтому предварительно читается текущее значение - `current`. Данный метод с помощью CAS изменяет значение `value` только в том случае, если оно равно ожидаемому значению (т.е. `current`), прочитанному перед запуском `compareAndSet(current, new)`. Если значение `value` было изменено в другом потоке, то оно не будет равно ожидаемому. Следовательно, метод `compareAndSet` вернет значение `false`. Поэтому следует повторять попытки чтения текущего значения и запуска с ним метода `compareAndSet(current, new)` пока `current` не будет равен `value`. 104 | 105 | Условно можно разделить методы Атомиков на: 106 | - `compare-and-set` - принимают `current` на вход и делают одну попытку записи через CAS 107 | - `set-and-get` - самостоятельно читают `current` и пытаются изменить значение с помощью CAS в цикле, как описано выше 108 | 109 | Непосредственно изменение значения `value` делегируется либо [VarHandle](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/invoke/VarHandle.html), либо [Unsafe](https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/jdk/internal/misc/Unsafe.java), которые в свою очередь выполняют его на нативном уровне. VarHandle - это динамически сильно типизированная ссылка на переменную или на параметрически определяемое семейство переменных, включающее статические поля, нестатические поля, элементы массива или компоненты структуры данных нестандартного типа. Доступ к таким переменным поддерживается в различных режимах, включая простой доступ на чтение/запись, `volotile` доступ на чтение/запись и доступ на `compare-and-swap`. 110 | 111 | В [java.util.concurrent.atomic](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/package-summary.html) имеется следующий набор атомиков: 112 | - [AtomicBoolean](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/AtomicBoolean.html), [AtomicInteger](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html), [AtomicLong](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html), [AtomicIntegerArray](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/AtomicIntegerArray.html), [AtomicLongArray](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/AtomicLongArray.html) - представляют атомарные целочисленные, булевы примитивные типы, а также два массива атомарных целых чисел. 113 | - [AtomicReference](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/AtomicReference.html) - класс для атомарных операций со ссылкой на объект. 114 | - [AtomicMarkableReference](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/AtomicMarkableReference.html) - класс для атомарных операций над парой `[reference, boolean]`. 115 | - [AtomicStampedReference](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/AtomicStampedReference.html) - класс для атомарных операций над парой `[reference, int]`. 116 | - [AtomicReferenceArray](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/AtomicReferenceArray.html) - массив атомарных ссылок 117 | - [AtomicIntegerFieldUpdater](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.html), [AtomicLongFieldUpdater](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/AtomicLongFieldUpdater.html), [AtomicReferenceFieldUpdater](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.html) - классы для атомарного обновления полей по их именам через reflection. 118 | - [DoubleAccumulator](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/DoubleAccumulator.html), [LongAccumulator](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/LongAccumulator.html) - классы, представляющие атомарные аккумуляторы, которые принимают на вход чистую функцию-аккумулятор (`BinaryOperator`) и начальное значение. Сохраняет весь набор операндов, а когда необходимо получить значение, то аккумулирует их с помощью функции-аккумулятора. Порядок операндов и применения функции-аккумулятора не гарантируется. Используется, когда записей намного больше, чем чтения. 119 | - [DoubleAdder](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/DoubleAdder.html), [LongAdder](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/atomic/LongAdder.html) - классы, представляющие атомарные счётчики. Являются частным случаем атомарных аккумуляторов, у которых функция-аккумулятор выполняет простое суммирование, а начальным значением является 0. 120 | 121 | С помощью атомиков можно реализовать блокировку, например так: 122 | ```java 123 | public class NonReentrantSpinLock { 124 | 125 | private AtomicReference owner = new AtomicReference<>(); 126 | 127 | public void lock() { 128 | Thread currentThread = Thread.currentThread(); 129 | 130 | while (!owner.compareAndSet(null, currentThread)) {} 131 | } 132 | 133 | public void unlock() { 134 | Thread currentThread = Thread.currentThread(); 135 | owner.compareAndSet(currentThread, null); 136 | } 137 | } 138 | ``` 139 | 140 | Подробнее: 141 | - [Как устроены атомики?](https://itsobes.ru/JavaSobes/kak-ustroeny-atomiki/) 142 | - [Compare and Swap](http://tutorials.jenkov.com/java-concurrency/compare-and-swap.html) 143 | - [Обзор java.util.concurrent.*](https://habr.com/ru/company/luxoft/blog/157273/) на Хабре 144 | - [Разбор основных концепций параллелизма](https://habr.com/ru/company/otus/blog/353414/) на Хабре 145 | - [Книга "Java Concurrency на практике"](https://habr.com/ru/company/piter/blog/489038/) - её отрывок на Хабре 146 | - [JDK concurrent package](https://habr.com/ru/post/187854/) на Хабре 147 | - [Atomic operations](https://habr.com/ru/post/157163/) на Хабре 148 | - [Concurrency: 6 способов жить с shared state](https://habr.com/ru/post/216049/) на Хабре 149 | - [The Art of Multiprocessor Programming](https://www.amazon.com/dp/0123705916) 150 | - [The JSR-133 Cookbook for Compiler Writers](http://gee.cs.oswego.edu/dl/jmm/cookbook.html) 151 | - [AtomicReference: A (Sometimes Easier) Alternative to Synchronized Blocks](https://dzone.com/articles/atomicreference-a-sometimes-easier-alternative-to) 152 | - [An Introduction to Atomic Variables in Java](https://www.baeldung.com/java-atomic-variables) на Bealdung 153 | - [Переход к атомарности](https://www.ibm.com/developerworks/ru/library/j-jtp11234/index.html) 154 | - [Use AtomicReference to implement Reentrant Lock](http://www.java2s.com/example/java/thread/use-atomicreference-to-implement-reentrant-lock.html) 155 | - [A comprehensive understanding of Java atomic variable classes](https://programmer.ink/think/a-comprehensive-understanding-of-java-atomic-variable-classes.html) 156 | - [Faster Atomic*FieldUpdaters for Everyone](https://shipilev.net/blog/2015/faster-atomic-fu/) 157 | - [Алексей Шипилёв — Если не Unsafe, то кто: восход VarHandles](https://www.youtube.com/watch?v=ESs0bZw8hsA) 158 | - [Introduction to nonblocking algorithms](https://www.ibm.com/developerworks/java/library/j-jtp04186/index.html) 159 | 160 | [к содержанию](#java-concurrency) 161 | 162 | ## Что такое ThreadLocal переменные? 163 | 164 | [ThreadLocal](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/ThreadLocal.html) - класс в виде обёртки для хранения отдельной независимой копии значения переменной для каждого использующего её потока, что позволяет сделать работу с такой переменной потокобезопасной. 165 | 166 | Данные `ThreadLocal`-переменных хранятся не в них самих, а непосредственно в объектах `Thread`. У каждого экземпляра класса [Thread](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Thread.html) есть поле `ThreadLocal.ThreadLocalMap threadLocals`, которое инициализируется и используется `ThreadLocal`. `ThreadLocal.ThreadLocalMap` представляет собой специализированную версию `HashMap`, записи которой наследуют от `WeakReference>`, используя ключ мапы как `ref field` слабой ссылки. Ключами такой мапы являются `ThreadLocal`, а значением - `Object`. Если ключ записи равен `null`, то такая запись называется просроченной (`stale`) и будет удалена из мапы. 167 | 168 | Следует обратить внимание, что `ThreadLocal` изолирует именно ссылки на объекты, а не копии их значений. Если изолированные внутри потоков ссылки ведут на один и тот же объект, то возможны коллизии. 169 | 170 | Когда у `ThreadLocal`-переменной запрашивается её значение (например через метод `get`), то она получает текущий поток, извлекает из него мапу `threadLocals`, и получает значение из мапы, используя себя в качестве ключа. Аналогично выполняются методы изменения значения `ThreadLocal`. 171 | 172 | Из этого следует, что значение `ThreadLocal`-переменной должно устанавливаться в том же потоке, в котором оно будет использоваться. 173 | 174 | Подробнее: 175 | - [Зачем используются thread local переменные?](https://itsobes.ru/JavaSobes/zachem-ispolzuiutsia-thread-local-peremennye/) 176 | - [О бедном ThreadLocal замолвите слово](http://samolisov.blogspot.com/2011/04/threadlocal.html) 177 | - [Использование ThreadLocal переменных](https://articles.javatalks.ru/articles/17) 178 | - [An Introduction to ThreadLocal in Java](https://www.baeldung.com/java-threadlocal) 179 | - [Утечка памяти с ThreadLocal](https://habr.com/ru/company/maxifier/blog/218313/) на Хабре 180 | - [5 вещей, которых вы не знали о многопоточности](https://habr.com/ru/post/108016/) на Хабре 181 | - [Разбор основных концепций параллелизма](https://habr.com/ru/company/otus/blog/353414/) на Хабре 182 | 183 | [к содержанию](#java-concurrency) 184 | 185 | ## Чем поток отличается от процесса? 186 | 187 | Ответ на этот вопрос писали в интернете ещё тогда, когда я балду в школе пинал (нулевые), поэтому у читателя есть широкий выбор. 188 | Мне импонирует [заметка](https://www.opennet.ru/docs/RUS/linux_parallel/node42.html) на OpenNET - кратко и чётко, суше Сахары. 189 | Для любителей смотреть в окна есть [статейка](https://docs.microsoft.com/ru-ru/windows/win32/procthread/about-processes-and-threads?redirectedfrom=MSDN) на MSDN. 190 | Вишенка на торте - олдовая [статья](https://habr.com/ru/post/40227/) с Хабра. 191 | 192 | [к содержанию](#java-concurrency) -------------------------------------------------------------------------------- /java/core.md: -------------------------------------------------------------------------------- 1 | [Оглавление](../README.md) 2 | 3 | # Java Core 4 | 5 | - [Какие бывают операции в стримах? Напишите стрим?](#какие-бывают-операции-в-стримах-напишите-стрим) 6 | - [Что поменялось с Java 8 по Java ?](#что-поменялось-с-java-8-по-java-current_version) 7 | - [В какой кодировке строки в Java? Как хранятся строки внутри класса String? Как устроен String?](#в-какой-кодировке-строки-в-java-как-хранятся-строки-внутри-класса-string-как-устроен-string) 8 | - [Сколько в байт занимает каждый из примитивных типов в памяти? А объект?](#сколько-в-байт-занимает-каждый-из-примитивных-типов-в-памяти-а-объект) 9 | - [Какие ссылки бывают в Java?](#какие-ссылки-бывают-в-java) 10 | 11 | ## Какие бывают операции в стримах? Напишите стрим? 12 | 13 | Есть 2 вида операций в Java [`Stream`](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/stream/Stream.html): 14 | - Промежуточные (Intermediate) - `filter`, `map`, `sorted`, `peek` и т.д. Возвращают `Stream`. 15 | - Терминальные (Terminal) - `collect`, `forEach`, `count`, `reduce`, `findFirst`, `anyMatch` и т.д. Возвращают результат стрима и запускают его выполнение. 16 | 17 | Кроме того, будет полезно ознакомиться с содержимым пакета [java.util.stream](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/stream/package-summary.html) и доступными коллекторами из [Collectors](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/stream/Collectors.html). 18 | 19 | Периодически просят написать какой-нибудь стрим, поэтому хорошо бы попрактиковаться. Можно на работе наесться, можно придумать задачи самому себе, можно поискать что-нибудь готовое: 20 | - [Java8 Code Kata](https://github.com/konohiroaki/java8-code-kata/blob/master/readme.md) 21 | - [Experience-Java-8](https://github.com/Elqoo/Experience-Java-8/blob/master/src/main/java/academy/elqoo/java8/stream/Stream8.java) 22 | - Может быть даже курс - [Java. Functional programming](https://stepik.org/course/1595/promo) 23 | 24 | Почитать подробнее про стримы лучше в Java Doc, но можно и в статьях: 25 | - [Java 8 Stream API](https://howtodoinjava.com/java8/java-streams-by-examples/) 26 | - [The Java 8 Stream API Tutorial](https://www.baeldung.com/java-8-streams) 27 | - [Полное руководство по Java 8 Stream API в картинках и примерах](https://annimon.com/article/2778). Тут не просто в картинках, а в анимациях! 28 | - [Шпаргалка Java программиста 4. Java Stream API](https://habr.com/ru/company/luxoft/blog/270383/) 29 | - [Java Stream API: что делает хорошо, а что не очень](https://habr.com/ru/company/jugru/blog/307938/) 30 | - [Пишем свой Spliterator](https://habr.com/ru/post/256905/) 31 | 32 | Посмотреть: 33 | - На letsCode - [Java Stream API: функционально, модно, молодёжно!](https://www.youtube.com/watch?v=RzEiCguFZiY) 34 | - Лекция в CSCenter от Тагира Валеева - [Лекция 8. Stream API](https://www.youtube.com/watch?v=Pk7atYm8bX0) 35 | - Доклад Тагира Валеева на Joker 2016 - [Причуды Stream API](https://www.youtube.com/watch?v=1_Zj3gS_a3E) 36 | 37 | [к содержанию](#java-core) 38 | 39 | ## Что поменялось с Java 8 по Java ? 40 | 41 | Java имеет [богатую историю](https://en.wikipedia.org/wiki/Java_version_history). На данный момент проекты чаще всего разделяются на: 42 | - legacy-проекты с версией Java меньше 8 43 | - проекты на Java 8, самая распрастранённая и популярная 44 | - проекты на Java 9+ (точнее либо 11 LTS, либо последние полугодовые релизы) 45 | 46 | Между 8 и 9 версиями случился небольшой разлом с частичной потерей обратной совместимости, а потом [приколы лицензирования](https://www.oracle.com/technetwork/java/javase/overview/oracle-jdk-faqs.html) подъехали, поэтому миграция и в без того консервативном мире Java-приложений идёт медленно. Однако идёт, и если вы собеседуетесь в компанию, где этот переход уже осуществили, то, вероятно, у вас поинтересуются, что же там с Java 8 поменялось, чем живёт и дышит современная Java. 47 | 48 | На момент выхода статьи, имеем: 49 | - [9](https://www.oracle.com/java/technologies/javase/9all-relnotes.html): [Project Jigsaw aka Модули](http://openjdk.java.net/projects/jigsaw/), [HTTP/2 Client (Incubator)](http://openjdk.java.net/jeps/110), [jshell](http://openjdk.java.net/jeps/222), [G1 GC по умолчанию](http://openjdk.java.net/jeps/248), [Compact Strings](https://openjdk.java.net/jeps/254) и [другие](https://openjdk.java.net/projects/jdk9/). 50 | - [10](https://www.oracle.com/java/technologies/javase/10-relnote-issues.html): [Local-Variable Type Inference (var)](http://openjdk.java.net/jeps/286), [Parallel Full GC для G1](http://openjdk.java.net/jeps/307), [Graal можно использовать как основной JIT-компилятор](http://openjdk.java.net/jeps/317) и [другие](https://openjdk.java.net/projects/jdk/10/). 51 | - [11 LTS](https://www.oracle.com/java/technologies/javase/jdk-11-relnote.html): [var в лямбдах](http://openjdk.java.net/jeps/323), [компиляция и запуск single-file программ через java](https://habr.com/ru/post/424683/), [новые методы для String](https://habr.com/ru/post/424539/), [Epsilon GC (Experimental)](http://openjdk.java.net/jeps/318), [ZGC (Experimental)](http://openjdk.java.net/jeps/333) и [другие](https://openjdk.java.net/projects/jdk/11/). 52 | - [12](https://www.oracle.com/technetwork/java/javase/12-relnote-issues-5211422.html): [Switch Expressions (Preview)](https://openjdk.java.net/jeps/325), [Shenandoah (Experimental)](https://openjdk.java.net/jeps/189), улучшения в G1, [JMH](https://openjdk.java.net/jeps/230) и [другие](https://openjdk.java.net/projects/jdk/12/) 53 | - [13](https://www.oracle.com/java/technologies/javase/13-relnote-issues.html): [Text Blocks (Preview)](https://openjdk.java.net/jeps/355) и [другое](https://openjdk.java.net/projects/jdk/13/) 54 | - [14](https://www.oracle.com/technetwork/java/javase/14-relnote-issues-5809570.html): [Pattern Matching для instanceof (Preview)](https://openjdk.java.net/jeps/305), [Packaging Tool (Incubator)](https://openjdk.java.net/jeps/343), [улучшили сообщение для NullPointerExceptions](https://openjdk.java.net/jeps/358), [Records (Preview)](https://openjdk.java.net/jeps/359) и [другие](https://openjdk.java.net/projects/jdk/14/). 55 | - [15](http://jdk.java.net/15/release-notes): [Sealed Classes (Preview)](https://openjdk.java.net/jeps/360), [Hidden Classes](https://openjdk.java.net/jeps/371), [удаление Nashorn JavaScript Engine из JDK](https://openjdk.java.net/jeps/372) и [другие](https://openjdk.java.net/projects/jdk/15/). 56 | 57 | Найти ссылки на документацию к API, языку и виртуальной машине, release notes и сравнить API между версиями можно в [Java-альманахе](https://javaalmanac.io/). 58 | 59 | Кроме всего прочего, есть ряд проектов, в рамках которых развиваются большие и ожидаемые сообществом изменения Java: 60 | - [Amber](https://openjdk.java.net/projects/amber/) - проект по реализации маленьких, но продуктивных улучшений языка Java. В рамках данного проекта постепенно реализуется и независимо выходит целый набор JEP: [var](https://openjdk.java.net/jeps/286) (JDK 10), [Switch Expressions](https://openjdk.java.net/jeps/361), [Sealed Types](https://openjdk.java.net/jeps/360), [Records](https://openjdk.java.net/jeps/359), [Text Blocks](https://openjdk.java.net/jeps/368), [Pattern Matching для instanceof](https://openjdk.java.net/jeps/375) и другие. 61 | - [Panama](https://openjdk.java.net/projects/panama/) - проект по улучшению взаимодействия между JVM и нативным кодом. На Хабре есть [статья](https://habr.com/ru/company/leader-id/blog/505072/) с разъяснениями и [интервью](https://habr.com/ru/company/jugru/blog/310014/) с Владимиром Ивановым на эту тему. 62 | - [Loom](https://wiki.openjdk.java.net/display/loom/Main) - проект по внедрению в Java легковесных потоков. На Хабре есть две прекрасные статьи с разъяснениями: [раз](https://habr.com/ru/company/jugru/blog/422519/) и [два](https://habr.com/ru/post/503412/). 63 | - [Valhalla](https://wiki.openjdk.java.net/display/valhalla/Main) - это проект по созданию нескольких больших и сложных улучшений языка и VM. В него входят: [Inline types](http://openjdk.java.net/jeps/169), [Generics over Primitive Types](http://openjdk.java.net/jeps/218), [Enhanced volatiles](http://openjdk.java.net/jeps/193) и другие возможные или необходимые в рамках проекта улучшения. 64 | - [Lanai](https://wiki.openjdk.java.net/display/lanai/Main) - проект по улучшению рендеринга настольных Java-приложений на MacOS путём использования [Metal](https://developer.apple.com/metal/) Apple platform API. C 14 мая 2020 появились [Early-Access сборки](https://jdk.java.net/lanai/). 65 | - и другие 66 | 67 | Отдельно нужно упомянуть [GraalVM](https://www.graalvm.org/) - это JDK и виртуальная машина Java, которая создана, чтобы [объединить необъединяемое](https://habr.com/ru/company/haulmont/blog/433432/): 68 | - быстрое выполнение Java 69 | - уменьшение времени старта и потребления памяти для Java 70 | - комбинирование и исполнение программ, написанных на различных ЯП, в том числе на платформо-зависимых 71 | - общие инструменты для всех ЯП 72 | - поддержка JIT и AOT-компиляции 73 | - и т.п. 74 | 75 | Послушать на тему: 76 | - Два выпуска подкаста Javaswag: [раз](https://soundcloud.com/javaswag/8-evgeniy-kozlov-pochemu-ne-c-var-zlo-ili-net-novye-fichi-java-9-12) и [два](https://soundcloud.com/javaswag/9-evgeniy-kozlov-den-rozhdeniya-java-i-novye-fichi-java-12-14) 77 | - [Выпуск 172 Java](https://podlodka.io/172) подкаста Подлодка, в гости к которому пришёл Тагир Валеев 78 | 79 | Почитать на Хабре: 80 | - [Руководство по возможностям Java версий 8-14](https://habr.com/ru/post/500468/) 81 | - [API, ради которых наконец-то стоит обновиться с Java 8. Часть 1](https://habr.com/ru/post/485750/) 82 | - [JAVA 9. Что нового?](https://habr.com/ru/company/otus/blog/341058/) 83 | - [Обзор Java 9](https://habr.com/ru/post/342170/) 84 | - [Модульность в Java 9](https://habr.com/ru/post/499872/) 85 | - [Компактные строки в Java 9](https://habr.com/ru/company/otus/blog/426621/) 86 | - [Java 10 General Availability](https://habr.com/ru/company/jugru/blog/351694/) 87 | - [Изменения в стандартной библиотеке Java 10](https://habr.com/ru/post/349868/) 88 | - [Записки о миграции на Java 10](https://habr.com/ru/post/354114/) 89 | - [Как Java 10 изменяет способ использования анонимных внутренних классов](https://habr.com/ru/company/otus/blog/456010/) 90 | - ["Жизнь после Java 10": какие изменения принесет Java 11](https://habr.com/ru/company/it-grad/blog/358810/) 91 | - [90 новых фич (и API) в JDK 11](https://habr.com/ru/post/424683/) 92 | - [Java 11: новое в String](https://habr.com/ru/post/424539/) 93 | - [Java 11 / JDK 11: General Availability](https://habr.com/ru/company/jugru/blog/424543/) 94 | - [39 новых фич, которые будут доступны в Java 12](https://habr.com/ru/post/446590/) 95 | - [Пришло время Java 12! Обзор горячих JEP-ов](https://habr.com/ru/company/jugru/blog/444434/) 96 | - [Новое в Java 12: The Teeing Collector](https://habr.com/ru/post/445622/) 97 | - [Только что вышла Java 13](https://habr.com/ru/company/jugru/blog/467789/) 98 | - [В Java 13 хотят добавить "текстовые блоки"](https://habr.com/ru/post/454144/) 99 | - [Introducing Java 13: Let's dive Into JDK's New Features](https://habr.com/ru/post/483186/) 100 | - [Что нового будет в Java 14](https://habr.com/ru/company/alconost/news/t/491378/) 101 | - [Java 14 is coming](https://habr.com/ru/post/491546/) 102 | - [Java 14: Record, более лаконичный instanceof, упаковщик jpackage, switch-лямбды и текстовые блоки](https://habr.com/ru/post/491564/) 103 | - [Исследуем записи в Java 14](https://habr.com/ru/post/482300/) 104 | - [Пробуем улучшенный оператор instanceof в Java 14](https://habr.com/ru/post/477654/) 105 | - [Исследуем sealed классы в Java 15](https://habr.com/ru/post/505696/) 106 | - [Sealed classes. Semantics vs performance](https://habr.com/ru/post/430014/) 107 | - [Sealed типы в Java](https://habr.com/ru/post/490298/) 108 | - [Что нового в Java 15?](https://habr.com/ru/post/518794/) 109 | - [Вышла Java 15](https://habr.com/ru/post/519270/) 110 | - [Project Panama: как сделать Java "ближе к железу"?](https://habr.com/ru/company/leader-id/blog/505072/) 111 | - [Раздача халявы: нетормозящие треды в Java. Project Loom](https://habr.com/ru/company/jugru/blog/422519/) 112 | - [Project Loom: виртуальные потоки в Java уже близко](https://habr.com/ru/post/503412/) 113 | - [Десять вещей, которые можно делать с GraalVM](https://habr.com/ru/company/haulmont/blog/433432/) 114 | - [Как работает Graal — JIT-компилятор JVM на Java](https://habr.com/ru/post/419637/) 115 | - [Graal: как использовать новый JIT-компилятор JVM в реальной жизни](https://habr.com/ru/company/billing/blog/351682/) 116 | - [Разрабатываем утилиту на GraalVM](https://habr.com/ru/post/451574/) 117 | - [Скрещиваем ужа с ежом: OpenJDK-11 + GraalVM](https://habr.com/ru/post/445978/) 118 | - [JavaScript, Java, какая теперь разница?](https://habr.com/ru/company/jugru/blog/353624/) 119 | - [Что под капотом компиляторных оптимизаций GraalVM?](https://habr.com/ru/company/jugru/blog/485024/) 120 | 121 | И не только: 122 | - [Java-альманах](https://javaalmanac.io/) 123 | - State of Loom: [часть 1](http://cr.openjdk.java.net/~rpressler/loom/loom/sol1_part1.html) и [часть 2](http://cr.openjdk.java.net/~rpressler/loom/loom/sol1_part2.html) 124 | - [GraalVM](https://www.graalvm.org/) 125 | 126 | Посмотреть: 127 | - [Cay Horstmann — Feature evolution in Java 13 and beyond](https://www.youtube.com/watch?v=Gvs-nGUiqFA) 128 | - [Тагир Валеев — Java 9-14: Маленькие оптимизации](https://www.youtube.com/watch?v=5Y0Alqb9H_I) 129 | - [Никита Липский — Java 9 Модули. Почему не OSGi?](https://www.youtube.com/watch?v=hEnvRXNyDgI) 130 | - [Cay Horstmann — Java 9: the good parts (not modules)](https://www.youtube.com/watch?v=_cvgg9szPH8) 131 | - [Владимир Иванов - Project Panama: как сделать Java “ближе к железу”?](https://www.youtube.com/watch?v=4vHMmLqF09Y) 132 | - [Олег Чирухин — GraalVM Всемогущий](https://www.youtube.com/watch?v=lH4H0LEAo9g) 133 | - [Олег Чирухин — Graal, Value Types, Loom и прочие ништяки](https://www.youtube.com/watch?v=hnadkXBIC1k) 134 | - [Олег Шелаев — Компилируем Java ahead of time с GraalVM](https://www.youtube.com/watch?v=tPezgDSD1Bk) 135 | - [Олег Шелаев — Суперкомпиляция, partial evaluation, проекции Футамуры и как GraalVM спасет мир](https://www.youtube.com/watch?v=C5fATKdVxZ0) 136 | - [Project Loom](https://www.youtube.com/watch?v=wWAxD7STTFQ) и [Новое в JDK 14](https://www.youtube.com/watch?v=qN8x-aIrhxk) на letsCode 137 | - [GOTO 2019 • Life After Java 8 • Trisha Gee](https://www.youtube.com/watch?v=eBuFzQeiGe0) 138 | - [Dalia Abo Sheasha — Migrating beyond Java 8](https://www.youtube.com/watch?v=NeYYmIup5nY) 139 | - [Project Loom: Helping Write Concurrent Applications on the Java Platform by Ron Pressler](https://www.youtube.com/watch?v=lIq-x_iI-kc) 140 | 141 | [к содержанию](#java-core) 142 | 143 | ## В какой кодировке строки в Java? Как хранятся строки внутри класса String? Как устроен String? 144 | 145 | До Java 9 все строки имели кодировку `UTF-16` (2 байта на символ) и хранились в массиве `char`. 146 | 147 | С Java 9 пришло такое изменение как [Compact String](https://openjdk.java.net/jeps/254). Если все символы строки входят в множество символов `Latin-1` (а это подавляющее большинство строк), то каждый из них может поместиться в 1 байт, поэтому в этом случае массив `char` избыточен. В результате было принято решение заменить массив `char` на массив `byte`, что позволяет строкам `Latin-1` расходовать меньше памяти. Кодировка строки хранится в отдельном поле `byte coder`, значение которого представляет `Latin-1` или `UTF-16`. 148 | 149 | Также интересной особенностью является кеширование классом `String` своего `hashcode`. 150 | 151 | Строки являются неизменяемыми, наследоваться от строк запрещено (`final class`). Все операции по изменении строки возвращают её новый экземпляр, в том числе и конкатенация строк. Компилятор [умеет оптимизировать конкатенацию](https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.18.1) и превращать её в объект [StringBuilder](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/StringBuilder.html) и совокупность вызовов методов `append`. ОДНАКО! В Java 9 вошёл [JEP 280: Indify String Concatenation](https://openjdk.java.net/jeps/280), который изменил эту оптимизацию и пошёл ещё дальше. Теперь вместо `StringBuilder` генерируется bytecode для вызова [StringConcatFactory](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/invoke/StringConcatFactory.html) через [invokedynamic](https://www.infoq.com/articles/Invokedynamic-Javas-secret-weapon/), поэтому стоит расслабиться и чаще выбирать `+`. 152 | 153 | Ещё можно упомянуть про `String pool` - это выделяемое в `heap` пространство, которое используется для оптимизации потребления памяти при хранении строк. Благодаря ему одинаковые строковые литералы могут ссылаться на один и тот же объект. 154 | 155 | Стоит помнить, что с помощью [String.intern()](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/String.html#intern()) производительности особой не добиться, а можно наоборот пустить всё по миру. Лучше напишите свою реализацию. Подоробнее читайте в статье Алексея Шипилёва - [JVM Anatomy Quark #10: String.intern()](https://shipilev.net/jvm/anatomy-quarks/10-string-intern/). 156 | 157 | Кроме того, [equals](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/String.html#equals(java.lang.Object)) и методы поиска (например [indexOf](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/String.html#indexOf(int))) [оптимизируются JIT компилятором](https://habr.com/ru/post/352086/) на нативном уровне. 158 | 159 | Посмотреть доклады Алексея Шипилёва на тему строк: [Катехизис java.lang.String](https://www.youtube.com/watch?v=SZFe3m1DV1A) и [The Lord of the Strings: Two Scours](https://www.youtube.com/watch?v=HWkVJkoo1_Q). 160 | 161 | Подробнее: 162 | - [String javadoc](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/String.html) 163 | - [Как обойти строчку?](https://itsobes.ru/JavaSobes/kak-oboiti-strochku/) 164 | - [Из чего состоит String?](https://itsobes.ru/JavaSobes/iz-chego-sostoit-string/) 165 | - [JDK 9/JEP 280: конкатенация строк никогда больше не будет прежней](https://habr.com/ru/company/otus/blog/444822/) на Хабре 166 | - [Компактные строки в Java 9](https://habr.com/ru/company/otus/blog/426621/) на Хабре 167 | - [Guide to Java String Pool](https://www.baeldung.com/java-string-pool) на Baeldung 168 | - [Compact Strings in Java 9](https://www.baeldung.com/java-9-compact-string) 169 | - [Владимир Иванов — Глубокое погружение в invokedynamic](https://www.youtube.com/watch?v=DgshYDTpS9I) 170 | - [Charles Nutter — Let's Talk About Invokedynamic](https://www.youtube.com/watch?v=0vfFHMGESVQ) 171 | - [Что там с JEP-303 или изобретаем invokedynamic](https://habr.com/ru/post/328240/) 172 | 173 | [к содержанию](#java-core) 174 | 175 | ## Сколько в байт занимает каждый из примитивных типов в памяти? А объект? 176 | 177 | Казалось бы: 178 | - `byte` - 1 байт 179 | - `short` - 2 байта 180 | - `int` - 4 байта 181 | - `long` - 8 байт 182 | - `char` - 2 байта 183 | - `float` - 4 байта 184 | - `double` - 8 байт 185 | 186 | А размер boolean не упоминается в спецификации вовсе. Однако также спецификация не запрещает использовать для хранения примитива больше памяти - главное, чтобы размер был достаточным для всех значений. Конкретный объём таки зависит от реализации JVM. Не последнюю роль в этом играет [выравнивание данных](https://en.wikipedia.org/wiki/Data_structure_alignment) в памяти. 187 | 188 | Похожая ситуация и со ссылочными типами - спецификация JVM не требует какой-то определённой структуры для объектов и отдаёт её на откуп реализации. Все тонкости и секреты занимаемой объектами памяти раскрывает Алексей Шипилёв в своей статье [Java Objects Inside Out](https://shipilev.net/jvm/objects-inside-out/). 189 | 190 | Подробнее: 191 | - [The Java Virtual Machine Specification](https://docs.oracle.com/javase/specs/jvms/se15/html/jvms-2.html#jvms-2.2) 192 | - [Какие существуют примитивы?](https://itsobes.ru/JavaSobes/kakie-sushchestvuiut-primitivy/) 193 | - [Сколько памяти занимает объект?](https://itsobes.ru/JavaSobes/skolko-pamiati-zanimaet-obekt/) 194 | - [Какие существуют примитивы?](https://itsobes.ru/JavaSobes/kakie-sushchestvuiut-primitivy/) 195 | - [Размер Java объектов](https://habr.com/ru/post/134102/) на Хабре 196 | - [Java Objects Inside Out](https://shipilev.net/jvm/objects-inside-out/) 197 | - [jol](https://github.com/openjdk/jol) 198 | - [Как JVM аллоцирует объекты?](https://habr.com/ru/post/332708/) на Хабре 199 | - [Сжатие указателей в Java](https://habr.com/ru/post/440166/) на Хабре 200 | - [Measuring Object Sizes in the JVM](https://www.baeldung.com/jvm-measuring-object-sizes) на Bealdung 201 | 202 | Если вас заинтересовало представление объектов в jvm и их реализация (и вы умеете-могёте читать C++), то можно пойти посмотреть исходники openjdk. Начать, например, отсюда: 203 | - [instanceOop.hpp](https://github.com/openjdk/jdk/blob/master/src/hotspot/share/oops/instanceOop.hpp) 204 | - [klass.hpp](https://github.com/openjdk/jdk/blob/master/src/hotspot/share/oops/klass.hpp) 205 | - [instanceKlass.hpp](https://github.com/openjdk/jdk/blob/master/src/hotspot/share/oops/instanceKlass.hpp) 206 | - [objArrayKlass.hpp](https://github.com/openjdk/jdk/blob/master/src/hotspot/share/oops/objArrayKlass.hpp) 207 | - [objArrayOop.hpp](https://github.com/openjdk/jdk/blob/master/src/hotspot/share/oops/objArrayOop.hpp) 208 | - [oopFactory.hpp](https://github.com/openjdk/jdk/blob/master/src/hotspot/share/memory/oopFactory.hpp) 209 | 210 | [к содержанию](#java-core) 211 | 212 | ## Какие ссылки бывают в Java? 213 | 214 | Типы ссылок в Java: 215 | - `Strong reference` - обычная переменная ссылочного типа в Java. Объект такой ссылки очищается GC не раньше, чем станет неиспользуемым (никто нигде на него больше не ссылается). 216 | - [Слабые ссылки](https://en.wikipedia.org/wiki/Weak_reference) - сборщик мусора тем или иным образом не учитывает связь ссылки и объекта в куче при выявлении объектов, подлежащих удалению. Объект будет удалён даже при наличии слабой ссылки на него: 217 | - `Soft reference` - мягкая ссылка, экземпляр класса [SoftReference](https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/ref/SoftReference.html). Объект гарантированно будет собран GC до возникновения [OutOfMemoryError](https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/OutOfMemoryError.html). Может использоваться для реализации кэшей, увеличивающихся без риска `OutOfMemoryError` для приложения. 218 | - `Weak reference` - слабая ссылка, экземпляр класса [WeakReference](https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/ref/WeakReference.html). Не препятствует утилизации объекта и игнорируется GC при сборке мусора. Может использоваться для хранения некоторой связанной с объектом информации до момента его смерти. Также стоит обратить внимание на [WeakHashMap](https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/util/WeakHashMap.html). 219 | - `Phantom reference` - фантомная ссылка, экземпляр класса [PhantomReference](https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/ref/PhantomReference.html). Не препятствует утилизации объекта и игнорируется GC при сборке мусора и имеет ряд особенностей, описанных ниже. Может быть применена для получения уведомления, что объект стал неиспользуемым и можно освободить связанные с ним ресурсы (как более надёжный вариант, чем `finalize()`, вызов которого не гарантируется, может проводить сеансы воскрешения и вообще deprecated). 220 | 221 | Чтобы достать объект из слабых ссылок, необходимо вызывать метод `get()`. Если объект недостижим, то метод вернёт `null`. Для фантомных ссылок всегда возвращается `null`. 222 | 223 | При создании слабой ссылки в конструктор можно, а для `PhantomReference` необходимо, передать экземпляр [ReferenceQueue](https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/ref/ReferenceQueue.html) - в очереди будет сообщение, когда ссылка протухнет. Для `SoftReference` и `WeakReference` это будет ДО финализации объекта, а для `PhantomReference` ПОСЛЕ. Однако фактическое удаление объекта фантомной ссылки из памяти не производится до момента её очистки. 224 | 225 | Подробнее: 226 | - [Мягкие ссылки на страже доступной памяти или как экономить память правильно](https://habr.com/ru/post/169883/) на Хабре 227 | - [Использование PhantomReferences в Java](http://samolisov.blogspot.com/2011/09/phantomreferences-java.html) 228 | 229 | [к содержанию](#java-core) -------------------------------------------------------------------------------- /java/jvm.md: -------------------------------------------------------------------------------- 1 | [Оглавление](../README.md) 2 | 3 | # JVM 4 | 5 | - [Сборка мусора. Как работает? Какие сборщики знаете? Какие есть области памяти в JVM? Что будет с двумя или более объектами, которые ссылаются только друг на друга, но больше не на кого и никому не нужны - как с ними поступит сборщик и как именно это будет делать?](#сборка-мусора-как-работает-какие-сборщики-знаете-какие-есть-области-памяти-в-jvm-что-будет-с-двумя-или-более-объектами-которые-ссылаются-только-друг-на-друга-но-больше-не-на-кого-и-никому-не-нужны---как-с-ними-поступит-сборщик-и-как-именно-это-будет-делать) 6 | 7 | ## Сборка мусора. Как работает? Какие сборщики знаете? Какие есть области памяти в JVM? Что будет с двумя или более объектами, которые ссылаются только друг на друга, но больше не на кого и никому не нужны - как с ними поступит сборщик и как именно это будет делать? 8 | 9 | Память в Java делится на Stack и Heap. 10 | 11 | Stack - это область памяти, доступ к которой организован в порядке LIFO. Сюда помещается frame - локальные переменные и параметры вызываемого метода. Здесь можно сразу уточнить, что примитивы хранятся на стеке, а вот у объектов тут хранится только ссылка, а сами объекты в Heap. НО, благодаря Escape Analysis и скаляризации из Java 6, объекты, которые являются исключительно локальными и не возвращаются за пределы выполняемого метода, также сохраняются в стеке. Про Escape Analysis и скаляризацию есть доклад ([видео](https://www.youtube.com/watch?v=K6c3W6vhQOA) или [текст](https://habr.com/ru/company/jugru/blog/322348/)) Руслана Черемина, или ещё [тут](https://www.beyondjava.net/escape-analysis-java). 12 | 13 | Frame создаётся и кладётся на Stack при вызове метода. Frame уничтожается, когда завершается его вызов метода, как в случае нормального завершения, так и в результате выброса неперехваченного исключения. У каждого потока есть свой Stack и он имеет ограниченный размер. Подробности можно посмотреть в [JVM Specification](https://docs.oracle.com/javase/specs/jvms/se13/html/jvms-2.html#jvms-2.5.5). 14 | 15 | Теперь про Heap и сборку мусора. Тут большинство просто хочет услышать то, что написано в одном из [сообщений](https://t.me/seniorsITBlog/61) telegram-канала Senior's Blog. Процитирую основную часть здесь: 16 | 17 |
18 | Heap делится на два поколения: 19 | 20 |
    21 |
  1. Young Generation 22 |
      23 |
    1. Eden
    2. 24 |
    3. Survivor 0 и Survivor 1
    4. 25 |
    26 |
  2. 27 |
  3. Old Generation 28 |
    1. Tenured
    29 |
  4. 30 |
31 | 32 | Young разделен на три части: Eden, Survivor 0 и Survivor 1. В Eden создаются все новые объекты. Один из Survivor регионов всегда пустой. При полном заполнении региона Eden запускается малая сборка мусора, и все живые объекты из Eden и Survivor перемещаются в пустой Survivor, а Eden и использующийся Survivor полностью очищается. Это делается для уменьшения фрагментации памяти. Объекты, которые несколько раз перемещаются между Survivor, затем помещаются в Tenured. 33 | 34 | В случае, когда места для новых объектов не хватает уже в Tenured, в дело вступает полная сборка мусора, работающая с объектами из обоих поколений. При этом старшее поколение не делится на подрегионы по аналогии с младшим, а представляет собой один большой кусок памяти. Поэтому после удаления мертвых объектов из Tenured производится не перенос данных (переносить уже некуда), а их уплотнение, то есть размещение последовательно, без фрагментации. Такой механизм очистки называется Mark-Sweep-Compact по названию его шагов (пометить выжившие объекты, очистить память от мертвых объектов, уплотнить выжившие объекты). 35 | 36 | Бывают еще объекты-акселераты, размер которых настолько велик, что создавать их в Eden, а потом таскать за собой по Survivor’ам слишком накладно. В этом случае они размещаются сразу в Tenured. 37 | 38 | Младшее поколение занимает одну треть всей кучи, а старшее, соответственно, две трети. При этом каждый регион Survivor занимает одну десятую младшего поколения, то есть Eden занимает восемь десятых. 39 |
40 | 41 | Существуют следующие реализации GC: 42 | - [Serial Garbage Collector](https://docs.oracle.com/en/java/javase/13/gctuning/available-collectors.html#GUID-45794DA6-AB96-4856-A96D-FDE5F7DEE498) 43 | - [Parallel Garbage Collector](https://docs.oracle.com/en/java/javase/13/gctuning/parallel-collector1.html#GUID-DCDD6E46-0406-41D1-AB49-FB96A50EB9CE). По умолчанию в Java 8. 44 | - [Concurrent Mark Sweep](https://docs.oracle.com/en/java/javase/13/gctuning/concurrent-mark-sweep-cms-collector.html#GUID-FF8150AC-73D9-4780-91DD-148E63FA1BFF) (CMS). Deprecated с Java 9. 45 | - [Garbage-First](https://www.oracle.com/technetwork/tutorials/tutorials-1876574.html) (G1). [По умолчанию](http://openjdk.java.net/jeps/248) с Java 9. Есть [видео](https://www.youtube.com/watch?v=iGRfyhE02lA) от Владимира Иванова. Ещё можно почитать о G1 в [туториале](https://docs.oracle.com/en/java/javase/13/gctuning/garbage-first-garbage-collector.html#GUID-ED3AB6D3-FD9B-4447-9EDF-983ED2F7A573) по настройке от Oracle. 46 | - [Z Garbage Collector](http://openjdk.java.net/jeps/333) (ZGC) 47 | - [Shenandoah](https://wiki.openjdk.java.net/display/shenandoah/Main) Garbage Collector. Есть в наличии с Java 12. Тут, конечно же, нужно смотреть доклады Алексея Шипилёва - [раз](https://www.youtube.com/watch?v=JBaZ4lK6OBk), [два](https://www.youtube.com/watch?v=HBWaffsl7fo) 48 | 49 | Если совсем кратко, то можно ознакомиться [тут](http://java-online.ru/garbage-collection.xhtml) и вот [тут](https://dzone.com/articles/jvm-architecture-explained). 50 | 51 | Почитать на Хабре подробнее про сборку мусора в Java можно в серии статей "Дюк, вынеси мусор!" от @alygin - [раз](https://habr.com/ru/post/269621/), [два](https://habr.com/ru/post/269707/), [три](https://habr.com/ru/post/269863/). 52 | 53 | Послушать про работу с памятью и сборщиках мусора можно в [выпуске 74](http://podlodka.io/74) подкаста Podlodka с Алексеем Шипилёвом в гостях. Обязательно загляните в полезные ссылки к выпуску. 54 | 55 | Ещё можно вспомнить про: 56 | - [Method Area](https://javapapers.com/core-java/java-jvm-run-time-data-areas/#Method_Area) - область памяти с информацией о классах, включая статические поля. Одна на всю JVM. 57 | - [Program Counter (PC) Register](https://javapapers.com/core-java/java-jvm-run-time-data-areas/#Program_Counter_PC_Register) - отдельный на каждый поток регистр для хранения адреса текущей выполняемой инструкции. 58 | - [Run-time Constant Pool](https://javapapers.com/core-java/java-jvm-run-time-data-areas/#Java_Virtual_Machine_Stacks) - выделяется из Method Area для каждого класса или интерфейса. Грубо говоря, хранит литералы. [Подробнее](https://blog.jamesdbloom.com/JVMInternals.html#constant_pool). 59 | - [Native Method Stack](https://javapapers.com/core-java/java-jvm-run-time-data-areas/#Java_Virtual_Machine_Stacks) - собственно Stack для работы нативных методов. 60 | 61 | Дополнительно про gc и саму JVM (ох, бохатая и животрепещущая тема): 62 | - [На богомерзком medium](https://medium.com/datadriveninvestor/how-does-garbage-collection-work-in-java-da8f75ec6899) в картинках 63 | - [Перевод](https://habr.com/ru/company/jugru/blog/443250/) [статьи](https://shipilev.net/jvm/diy-gc/) Алексея Шипилёва на Хабре - Самодельный сборщик мусора для OpenJDK 64 | - [Отрывок](https://plumbr.io/handbook/garbage-collection-algorithms/marking-reachable-objects) из Java Garbage Collection Handbook про reachability algorithm 65 | - [Статейка](https://en.wikipedia.org/wiki/Tracing_garbage_collection) на Википедии про Tracing garbage collection 66 | - [Доклад](https://www.youtube.com/watch?v=e2lXj_t7ZBc) Simone Bordet про ZGC и Shenandoah 67 | - [JVM Anatomy Quarks](https://shipilev.net/jvm/anatomy-quarks/) - серия постов от Алексея Шипилёва про устройство JVM. Это просто клад, за который будут воевать пришельцы на постапокалиптическую Землю, чтобы разгадать, как работает эта чёртва шайтан-виртуал-машина и промышленный код почивших человеков. 68 | 69 | [к содержанию](#jvm) -------------------------------------------------------------------------------- /libraries/libraries.md: -------------------------------------------------------------------------------- 1 | [Оглавление](../README.md) 2 | 3 | # Популярные библиотеки 4 | 5 | - [Стоит ли использовать Lombok?](#стоит-ли-использовать-lombok) 6 | 7 | ## Стоит ли использовать Lombok? 8 | 9 | Осторожно, холиворный вопрос! Возможны ожоги и прочие неприятности! 10 | 11 | На Хабре [найдётся много больше одной статьи](https://habr.com/ru/search/?q=Lombok#h) демонстрирующей народную любовь к Lombok - ведь он знаменитый победитель бойлерплейтов, сократитель кода, ускорятель кодонабора, любимый сундучок исцеляющих костылей и прочее, и прочее. О прелести Lombok вам расскажут из любого утюга. 12 | 13 | Но как там с подводными камнями? Что с надводными вилами? Этот вопрос на собеседовании о том, как хорошо вы знаете недостатки своего любимого инструмента. И на сдачу - тест на совместимость. 14 | 15 | А ответ на вопрос стоит начать с переворота стрелочки - с хитрым ленинским прищуром спросите у интервьюера: "А как в вашем стайл-гайде написано?". Заодно узнаете о его ~~отсутствии~~ наличии. Ибо холиварные вопросы решить нужно однажды на сходе Архитектурного Синода и на весь простор компании сии решения распространить, увековечив их в стайл-гайде, дабы раскола избежать и не соблазнять неокрепшие умы неофитов спорами на рабочем месте посреди спринта горящего. 16 | 17 | Самая лайтовая и, возможно, притянутая за уши причина не использовать Lombok - плагин постоянно отваливается с выходом новой версии IDEA. А если отваливается плагин, то работа летит коту под хвост. Но это уже уходит в прошлое! С версии 2020.3 Lombok-плагин [будет поставляться вместе с IDEA](https://blog.jetbrains.com/idea/2020/10/intellij-idea-2020-3-eap5/). 18 | 19 | Большинство из проблем с Lombok связаны с особенностями и нюансами реализации как самих аннотаций библиотеки, так и сторонних фреймворков и библиотек. Например, эксперты по Hibernate советуют (например [тут](https://thorben-janssen.com/lombok-hibernate-how-to-avoid-common-pitfalls/)) избегать использования Lombok в entity-классах. Хотя бы исключить использование [@EqualsAndHashCode](https://projectlombok.org/features/EqualsAndHashCode), [@ToString](https://projectlombok.org/features/ToString) и [@Data](https://projectlombok.org/features/Data), потому что генерируемый ими код для методов `equals`, `hashCode` и `toString` может либо отработать неверно, либо привести к потере производительности или исключениям в некоторых определённых случаях для entities. А как нужно правильно реализовывать данные методы для entities написано [тут](https://vladmihalcea.com/the-best-way-to-implement-equals-hashcode-and-tostring-with-jpa-and-hibernate/) или [тут](https://thorben-janssen.com/ultimate-guide-to-implementing-equals-and-hashcode-with-hibernate/). 20 | 21 | Интересная дискуссия, затянувшаяся на два дня, была по данному вопросу в [чатике](https://t.me/pspodcast_group) подкаста "Паша+Слава" 7-8 марта - начало [тут](https://t.me/pspodcast_group/10280). В ней @asm0dey задаёт каверзные вопросы по использованию Lombok и рассказывает почему он забанил Lombok как тимлид. Например: "Что произойдёт если библиотека, которую ты используешь, использует [@SneakyThrows](https://projectlombok.org/features/SneakyThrows) и ты её вызываешь в рамках транзакции?" (об этом можно почитать [тут](https://blog.pchudzik.com/201911/transactional-errors/)), "Тебе наверное нравится аннотация [@Data](https://projectlombok.org/features/Data). Как она строит equals для коллекций и для массивов?", "Знаешь ли ты что [@EqualsAndHashCode](https://projectlombok.org/features/EqualsAndHashCode) может вызвать StackOverflowException и тебе даже нечего будет дебажить?". 22 | 23 | Главная проблема Lombok - простота хуже воровства - его волшебная лёгкость провоцирует не читать документацию, что потом может повлечь за собой горе и страдания. Но может и не повлечь - тут как задача в джиру ляжет. Недаром не заросла к Lombok народная тропа - можно ограничиться использованием некоторого минимального джентельменского набора из Lombok, следить за собой. Но всё-таки ~~мойте руки, предохраняйтесь~~ читайте документацию перед активным использованием ваших инструментов, ведь они могут иметь неочевидные нюансы и сюрпризы в реализации. 24 | 25 | P.S. У Lombok есть занятная экспериментальная фича [onX](https://projectlombok.org/features/experimental/onX) - у неё интересный синтаксис (`@__` правда только для Java 7) и его описание в документации. А вот [тут](https://www.baeldung.com/spring-injection-lombok) рассказывается зачем оно вам может понадобиться, например в Spring-приложении. 26 | 27 | Подробнее: 28 | - [Project Lombok](https://projectlombok.org/) 29 | - [Who Needs Lombok Anyhow](http://gregorriegler.com/2019/08/10/who-needs-lombok-anyhow.html) 30 | - [Be Careful With Lombok](https://levelup.gitconnected.com/be-careful-with-lombok-2e2edfc01110) 31 | - [Don’t use Lombok](https://medium.com/@vgonzalo/dont-use-lombok-672418daa819) 32 | - [Lombok & Hibernate: How to Avoid Common Pitfalls](https://thorben-janssen.com/lombok-hibernate-how-to-avoid-common-pitfalls/) 33 | - [Error handling with @Transactional and @SneakyThrows](https://blog.pchudzik.com/201911/transactional-errors/) 34 | - [Lombok, sources.jar и удобный дебаг](https://habr.com/ru/company/sberbank/blog/438548/) 35 | - [Some Dangers of Using Lombok](https://medium.com/@gabor.liptak/some-dangers-of-using-lombok-d759fc8f701f) 36 | 37 | [к содержанию](#популярные-библиотеки) -------------------------------------------------------------------------------- /maintenance/maintenance.md: -------------------------------------------------------------------------------- 1 | [Оглавление](../README.md) 2 | 3 | # Сопровождение, поддержка, эксплуатация 4 | 5 | - [Могут ли быть в Java утечки памяти и когда? Как обнаружить причину? Как снять heap-dump?](#могут-ли-быть-в-java-утечки-памяти-и-когда-как-обнаружить-причину-как-снять-heap-dump) 6 | - [Что такое Xmx и Xms, Xss?](#что-такое-xmx-и-xms-xss) 7 | - [Какие инструменты для нагрузочного тестирования вы знаете?](#какие-инструменты-для-нагрузочного-тестирования-вы-знаете) 8 | - [Чем докер отличается от виртуалки? Что лежит в его основе? Как работает Docker?](#чем-докер-отличается-от-виртуалки-что-лежит-в-его-основе-как-работает-docker) 9 | - [Чем контейнер сервлетов отличается от сервера приложений? Какие знаете?](#чем-контейнер-сервлетов-отличается-от-сервера-приложений-какие-знаете) 10 | 11 | ## Могут ли быть в Java утечки памяти и когда? Как обнаружить причину? Как снять heap-dump? 12 | 13 | Могут. Профилировать. Снимать heap-dump, например с помощью [jmap](https://docs.oracle.com/en/java/javase/14/docs/specs/man/jmap.html), загружать в memory profiler (например в [VisualVM](https://visualvm.github.io/)) 14 | 15 | Подробнее: 16 | - Доступно изложено на [Baeldung](https://www.baeldung.com/java-memory-leaks) или то же самое [тут](https://topjava.ru/blog/java-memory-leaks), но на языке родных осин. 17 | - Ещё [тут](https://www.toptal.com/java/hunting-memory-leaks-in-java) 18 | - [здесь](https://dzone.com/articles/memory-leak-andjava-code) 19 | - Старенькая [статья](https://habr.com/ru/post/132500/) на Хабре про типичные случаи утечки памяти в Java 20 | - [Диагностика утечек памяти в Java](https://habr.com/ru/post/324144/) на Хабре 21 | - [Ищем утечки памяти с помощью Eclipse MAT](https://habr.com/ru/post/519830/) на Хабре 22 | - [Устранение утечек памяти посредством слабых ссылок](https://www.ibm.com/developerworks/ru/library/j-jtp11225/index.html) 23 | - [Устранение утечек памяти посредством гибких ссылок](https://www.ibm.com/developerworks/ru/library/j-jtp01246/index.html) 24 | - [Бывают ли в Java утечки памяти?](https://itsobes.ru/JavaSobes/byvaiut-li-v-java-utechki-pamiati/) 25 | - [Диагностика OutOfMemoryError подручными средствами](http://bazhenov.me/blog/2009/12/20/out-of-memory-error.html) 26 | - [Java VisualVM - Browsing a Heap Dump](https://docs.oracle.com/javase/8/docs/technotes/guides/visualvm/heapdump.html) 27 | - [VisualVM: мониторинг, профилировка и диагностика Java-приложений](https://shipilev.net/blog/archive/visualvm/) 28 | - Доклад Андрея Паньгина [Всё, что вы хотели знать о стек-трейсах и хип-дампах](https://www.youtube.com/watch?v=0pyZERLBZvQ&feature=emb_logo) 29 | - [Different Ways to Capture Java Heap Dumps](https://www.baeldung.com/java-heap-dump-capture) 30 | - [Analyze memory snapshots](https://www.jetbrains.com/help/idea/analyze-hprof-memory-snapshots.html) с помощью IntelliJ IDEA 31 | - [Analyze objects in the JVM heap](https://www.jetbrains.com/help/idea/analyze-objects-in-the-jvm-heap.html) с помощью IntelliJ IDEA 32 | 33 | [к содержанию](#сопровождение-поддержка-эксплуатация) 34 | 35 | ## Что такое Xmx и Xms, Xss? 36 | 37 | JVM стартует с `Xms` количеством выделенной под heap памяти и максимально может увеличить её до значения `Xmx`. 38 | `Xss` флаг определяет размер выделенной под стек памяти. 39 | 40 | Общий вид: 41 | ``` 42 | java -Xmx<количество><единица измерения> 43 | ``` 44 | 45 | Можно использовать различные единицы измерения, например килобайты (`k`), мегабайты (`m`) или гигабайты (`g`). 46 | 47 | Пример: 48 | ```bash 49 | java -jar my.jar -Xms256m -Xmx2048m 50 | ``` 51 | 52 | Подробнее: 53 | - В [статье](https://mkyong.com/java/java-what-is-xms-and-xmx-parameter/) на Mkyong 54 | - В [статье](https://docs.oracle.com/cd/E21764_01/web.1111/e13814/jvm_tuning.htm#PERFM150) Tuning JVM от Orcale 55 | - В [статье](https://docs.oracle.com/en/java/javase/14/gctuning/factors-affecting-garbage-collection-performance.html) Factors Affecting Garbage Collection Performance от Oracle 56 | - [Список](https://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/jrdocs/refman/optionX.html) всех X опций CLI 57 | 58 | [к содержанию](#сопровождение-поддержка-эксплуатация) 59 | 60 | ## Какие инструменты для нагрузочного тестирования вы знаете? 61 | 62 | Благодаря нагрузочному тестированию появляется возможность оценить производительность приложения при различных нагрузках от действий определённого количества пользователей приложения. 63 | 64 | Существует несколько решений для проведения подобного рода тестирования: 65 | - [Apache JMeter](https://jmeter.apache.org/) - самый известный, opensource, поддерживает работу с различными сетевыми протоколами разных уровней HTTP, HTTPS, FTP, LDAP, SOAP, TCP, почтовых протоколов и shell-скриптов. Он, как java-based инструмент, предоставляет возможности по работе с JDBC, Message-oriented middleware (MOM) через JMS и Java Objects. 66 | - [LoadRunner](https://www.microfocus.com/en-us/products/loadrunner-professional/overview) - это сложный и универсальный инструмент для нагрузочного тестирования различных платформ. Платный, ориентирован в первую очередь на Enterprise. 67 | - [LoadNinja](https://loadninja.com/) - платный, позволяет пользователям создавать нагрузочные тесты без использования каких-либо скриптов. Средствами браузера собирает метрики, которые позволяют оценить производительность приложения. 68 | - [WebLOAD](https://www.radview.com/) - коммерческий комплексный инструмент. Предоставляет пользователям расширенные функции, такие как анализ производительности и интеллектуальная аналитика, а также интеграцию с рядом инструментов, начиная от мониторинга производительности до конвейеров CI/CD. 69 | - [LoadUI Pro](https://www.soapui.org/tools/loadui-pro/) - коммерческий инструмент от создателей [SOAP UI](https://www.soapui.org/), тесты которого можно использовать как сценарии нагрузочного тестирования. Предназначен для веб-сервисов и позволяет пользователям оценивать масштабируемость, скорость и производительность API. 70 | - [K6](https://k6.io/) - opensource инструмент, ориентированный на разработчиков и тестирования производительности сайтов. Скрипты пишутся на JavaScript. Запуск тестов происходит в консольном режиме, результаты тестирования по умолчанию также выводятся в консоль, однако доступна поддержка таких плагинов для вывода результатов, как Kafka, Datadog, InfluxDB, JSON и StatsD. Доступна интеграция с CI-инструментами. 71 | - [Яндекс.Танк](https://yandex.ru/dev/tank/) - инструмент от Яндекс с модульной архитектурой, которая позволяет использовать различные генераторы нагрузок - высокопроизводительный асинхронный hit-based-генератор HTTP-запросов Phantom и сценарный инструмент jMeter. Встроенный мониторинг ресурсов, автоматическая остановка теста по заданным условиям, вывод результатов в консоль и в виде графиков, подключение пользовательских модулей. 72 | - [Gatling](https://gatling.io/) - opensource инструмент на Scala с использованием [Netty](https://netty.io/) и [Akka](https://akka.io/). Скрипты пишутся на Scala, есть возможность интеграции с [Jenkins](https://www.jenkins.io/). 73 | 74 | Подробнее: 75 | - [Обзор инструментария для нагрузочного и перформанс-тестирования](https://habr.com/ru/company/jugru/blog/337928/) на Хабре 76 | - [Нагрузочное тестирование: с чего начать и куда смотреть](https://habr.com/ru/company/jugru/blog/329174/) на Хабре 77 | - [Нагрузочное тестирование на Gatling](https://habr.com/ru/company/tinkoff/blog/323316/) на Хабре 78 | - [Top 10 лучших инструментов для нагрузочного тестирования](https://www.performance-lab.ru/blog/luchshie-instrumenty-dlya-nagruzochnogo-testirovaniya) 79 | - [9 этапов тестирования производительности](https://www.a1qa.ru/blog/9-etapov-testirovaniya-proizvoditelnosti/) 80 | - [10 шагов для запуска тестирования производительности с Apache JMeter](https://medium.com/effective-developers/10-steps-to-run-first-performance-test-with-apache-jmeter-52867c12b0a4) 81 | - [jMeter — Краткое руководство](https://coderlessons.com/tutorials/java-tekhnologii/vyuchi-jmeter/jmeter-kratkoe-rukovodstvo) 82 | - [Rest API Load testing with Apache JMeter](https://medium.com/@chamikakasun/rest-api-load-testing-with-apache-jmeter-a4d25ea2b7b6) 83 | - [Load Testing with Gatling - The Complete Guide](https://www.james-willett.com/gatling-load-testing-complete-guide/) 84 | - [Открытые бенчмарки для нагрузочного тестирования серверов и веб-приложений](https://habr.com/ru/company/1cloud/blog/474474/) 85 | 86 | [к содержанию](#сопровождение-поддержка-эксплуатация) 87 | 88 | ## Чем докер отличается от виртуалки? Что лежит в его основе? Как работает Docker? 89 | 90 | [Виртуальная машина](https://en.wikipedia.org/wiki/Virtual_machine) (Virtual Machine - VM) - программная и/или аппаратная система, эмулирующая аппаратное обеспечение и исполняющее приложения некоторой целевой платформы на платформе хоста. Иными словами - это виртуальный компьютер с виртуальными устройствами и независимой операционной системой, управлением памятью и другими компонентами. Т.о. на одном реальном компьютере может существовать несколько виртуальных, изолированных друг от друга, со своими ОС. Запускаемые внутри виртуальной машины приложения не имеют понятия о её виртуальности и взаимодействуют с ней как с реальной. Хотя VM изолирована от реального хоста, она может иметь доступ к его диску и периферийным устройствам. Существует возможность сделать backup'ы VM в виде текущего состояния системы и содержимого дисков для возможности последующего восстановления системы в исходное состояние. 91 | 92 | Каждая VM несёт дополнительные расходы на эмуляцию оборудования и работу своей ОС. 93 | 94 | Управляет виртуальными машинами на реальном железе [гипервизор](https://en.wikipedia.org/wiki/Hypervisor) - это программное и/или аппаратное решение, процесс, который отделяет операционную систему компьютера и приложения от базового физического оборудования. 95 | 96 | Самими популярными решениями виртуализации являются [KVM](https://www.linux-kvm.org/page/Main_Page) с [QEMU](https://www.qemu.org/), [XEN](https://xenproject.org/), решения от [VMWare](https://www.vmware.com/) и [Hyper-V](https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/about/). 97 | 98 | [Docker](https://www.docker.com/get-started) - программное решение, использующее [виртуализацию на уровне операционной системы](https://en.wikipedia.org/wiki/OS-level_virtualization) для доставки, развёртывания, изоляции и упаковки приложения со всеми его зависимостями в т.н. [контейнер](https://www.docker.com/resources/what-container). 99 | 100 | Контейнеры расходуют меньше места на диске и ресурсов хоста, потому что переиспользуют большее количество общих ресурсов хоста и обеспечивает виртуализацию на уровне ОС. Каждый из контейнеров работает как отдельный процесс основной ОС, у которого есть своё собственное виртуальное адресное пространство. Изоляция контейнеров достигается с помощью [linux namespaces](https://en.wikipedia.org/wiki/Linux_namespaces). Ограничить потребление системных ресурсов контейнером можно через [cgroups](https://en.wikipedia.org/wiki/Cgroups). 101 | 102 | Контейнер создаётся из образа, который в свою очередь основан на `Dockerfile` проекта, и представляет собой набор файловых систем (слоёв) наслоённых друг на друга и сгруппированных вместе, доступных только для чтения. Контейнеры всегда создаются из образов, добавляя свой собственный доступный для записи верхний слой, в который вносятся необходимые для контейнера в процессе работы изменения. Это позволяет нескольким контейнерам переиспользовать один образ. 103 | 104 | Docker-контейнеры используются различными системами оркестрации и CI/CD. 105 | 106 | У Docker есть большой репозиторий образов - [Docker-Hub](https://www.docker.com/products/docker-hub) 107 | 108 | Кроме Docker, существуют и [другие контейнеры](https://en.wikipedia.org/wiki/List_of_Linux_containers). 109 | 110 | На Хабре есть множество статей на тему Docker: 111 | - [VM или Docker?](https://habr.com/ru/post/474068/) 112 | - Серия статей "Изучаем Docker": [част 1](https://habr.com/ru/company/ruvds/blog/438796/), [часть 2](https://habr.com/ru/company/ruvds/blog/439978/), [часть 3](https://habr.com/ru/company/ruvds/blog/439980/), [часть 4](https://habr.com/ru/company/ruvds/blog/440658/), [часть 5](https://habr.com/ru/company/ruvds/blog/440660/), [часть 6](https://habr.com/ru/company/ruvds/blog/441574/) 113 | - [Docker. Начало](https://habr.com/ru/post/353238/) 114 | - [Как устроен процесс создания docker-контейнера (от docker run до runc)](https://habr.com/ru/company/otus/blog/511414/) 115 | - [Полное практическое руководство по Docker: с нуля до кластера на AWS](https://habr.com/ru/post/310460/) 116 | - [Лабораторная работа: введение в Docker с нуля. Ваш первый микросервис](https://habr.com/ru/post/346634/) 117 | - [Исповедь docker хейтера](https://habr.com/ru/post/467607/) 118 | - [Глубокое погружение в Linux namespaces](https://habr.com/ru/post/458462/) 119 | - [Как я запускал Докер внутри Докера и что из этого получилось](https://habr.com/ru/post/477464/) 120 | - [Понимая Docker](https://habr.com/ru/post/253877/) 121 | - [Поняв Docker](https://habr.com/ru/post/277699/) 122 | - [Основы Docker за Х часов и Y дней](https://habr.com/ru/post/337306/) 123 | - [Docker и все, все, все](https://habr.com/ru/company/southbridge/blog/512246/) 124 | - [Безопасность для Docker-контейнеров](https://habr.com/ru/company/flant/blog/474012/) 125 | - [Методики уменьшения размеров образов Docker](https://habr.com/ru/company/ruvds/blog/485650/) 126 | - 10 практических рекомендаций по безопасности образов Docker: [часть 1](https://habr.com/ru/company/otus/blog/480970/), [часть 2](https://habr.com/ru/company/otus/blog/482044/) 127 | - [Docker: вредные советы](https://habr.com/ru/company/southbridge/blog/449944/) 128 | - [Docker: невредные советы](https://habr.com/ru/company/southbridge/blog/452108/) 129 | - [Зачем нужен containerd и почему его отделили от Docker](https://habr.com/ru/company/flant/blog/325358/) 130 | - [Зрелая исполняемая среда для контейнеров: containerd стал "выпускником" CNCF](https://habr.com/ru/company/flant/blog/442036/) 131 | 132 | А также на тему виртуализации: 133 | - [Гипервизоры. Что же это и как работает виртуальный сервер?](https://habr.com/ru/company/vps_house/blog/349788/) 134 | - [Автоматизация Для Самых Маленьких. Часть 1.1. Основы виртуализации](https://habr.com/ru/post/467801/) 135 | - [Архитектура Hyper-V: Глубокое погружение](https://habr.com/ru/post/98580/) 136 | - [Hyper-V для разработчиков под Windows 10](https://habr.com/ru/company/microsoft/blog/481248/) 137 | - [Общие принципы работы QEMU-KVM](https://habr.com/ru/post/466549/) 138 | - [Работа с виртуальными машинами KVM. Введение](https://habr.com/ru/post/120432/) 139 | - [Показатели эффективности: KVM vs. Xen](https://habr.com/ru/company/cloud4y/blog/282918/) 140 | - [Hyper-V или KVM?](https://habr.com/ru/company/ruvds/blog/308350/) 141 | 142 | Кроме того, можно углубиться в других источниках: 143 | - [Containers vs. virtual machines](https://docs.microsoft.com/en-us/virtualization/windowscontainers/about/containers-vs-vm) 144 | - [Play with Docker](https://www.docker.com/play-with-docker) 145 | - [Документация Docker](https://docs.docker.com/get-started/overview/) 146 | - [The Docker EcoSystem](https://legacy.gitbook.com/book/washraf/the-docker-ecosystem/details) 147 | - [Hardware-assisted virtualization](https://en.wikipedia.org/wiki/Hardware-assisted_virtualization) 148 | - [Full virtualization](https://en.wikipedia.org/wiki/Full_virtualization) 149 | - [Сравнение гипервизоров: KVM, Hyper-V или VMware?](https://www.xelent.ru/blog/sravnenie-gipervizorov-kvm-hyper-v-ili-vmware/) 150 | - [Вся правда о гипервизорах](https://www.sim-networks.com/blog/hypervisors-vmware-kvm-xen-openvz) 151 | - [Перестаем бояться виртуализации при помощи KVM](https://eax.me/kvm/) 152 | - [Основы виртуализации и введение в KVM](https://mkdev.me/posts/osnovy-virtualizatsii-i-vvedenie-v-kvm) 153 | - [Виртуализация в Unix. Часть 1: Kernel-based Virtual Machine (KVM)](https://medium.com/@alexander.bazhenov/%D0%B2%D0%B8%D1%80%D1%82%D1%83%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F-%D0%B2-linux-%D1%87%D0%B0%D1%81%D1%82%D1%8C-1-kernel-based-virtual-machine-kvm-55f989880dbf) 154 | - [Настольная книга по Linux/Cgroups](https://ru.wikibooks.org/wiki/%D0%9D%D0%B0%D1%81%D1%82%D0%BE%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%BA%D0%BD%D0%B8%D0%B3%D0%B0_%D0%BF%D0%BE_Linux/Cgroups) 155 | - [Механизмы контейнеризации: cgroups](https://selectel.ru/blog/mexanizmy-kontejnerizacii-cgroups/) 156 | - [Введение в контейнеры, VM и Docker для новичков](http://falbar.ru/article/vvedenie-v-kontejnery-vm-i-docker-dlya-novichkov) 157 | - [containerd](https://containerd.io/) 158 | - [awesome-compose](https://github.com/docker/awesome-compose) 159 | - [Learn Docker & Containers using Interactive Browser-Based Scenarios](https://www.katacoda.com/courses/docker) 160 | - [What Is Docker & Docker Container? A Deep Dive Into Docker!](https://www.edureka.co/blog/what-is-docker-container) 161 | - [Docker for beginners](https://docker-curriculum.com/) 162 | 163 | [к содержанию](#сопровождение-поддержка-эксплуатация) 164 | 165 | ## Чем контейнер сервлетов отличается от сервера приложений? Какие знаете? 166 | 167 | [Контейнер сервлетов](https://en.wikipedia.org/wiki/Web_container) - это компонент веб-сервера для взаимодействия с [Java-сервлетами](https://en.wikipedia.org/wiki/Java_servlet) - обеспечивает их жизненный цикл, сопоставление URL-адреса к определённому сервлету и имеет ли отправитель запроса по данному URL необходимые права доступа и т.п. 168 | 169 | Примеры (также являются самостоятельными веб-серверами, но НЕ серверами приложений (реализуют неполный стек Java EE)): 170 | - Самый известный - [Apache Tomcat](https://en.wikipedia.org/wiki/Apache_Tomcat). Есть несколько вариаций: от простого контейнера до полноценного сервера приложений (TomEE) 171 | - [Jetty](https://en.wikipedia.org/wiki/Jetty_(web_server)) 172 | - [Undertow](http://undertow.io/) 173 | 174 | [Сервер приложений](https://en.wikipedia.org/wiki/Application_server) - сервер, который включает в себя контейнер сервлетов и реализует весь стек [Java EE](https://ru.wikipedia.org/wiki/Jakarta_EE) (ныне Jakarta EE). 175 | 176 | Примеры: 177 | - [Wildfly](https://wildfly.org/about/) 178 | - [Apache TomEE](https://tomee.apache.org/) 179 | - [IBM WebSphere](https://www.ibm.com/ru-ru/marketplace/java-ee-runtime) 180 | - [Eclipse GlassFish](https://eclipse-ee4j.github.io/glassfish/) 181 | - [Сводная таблица](https://en.wikipedia.org/wiki/List_of_application_servers) 182 | 183 | Исчерпывающий ответ на вопрос "Зачем нужны сервера приложений, если есть Tomcat" можно найти в одноимённой [статье](https://itsobes.ru/JavaSobes/chem-otlichaetsia-servlet-container-ot-application-server/). 184 | 185 | [к содержанию](#сопровождение-поддержка-эксплуатация) -------------------------------------------------------------------------------- /misc/usefulness.md: -------------------------------------------------------------------------------- 1 | [Оглавление](../README.md) 2 | 3 | # Полезные ссылки 4 | 5 | - [Every Programmer Should Know](https://github.com/mtdvio/every-programmer-should-know) 6 | - Работа не волк: [часть 1](https://habr.com/ru/company/ruvds/blog/473762/), [часть 2](https://habr.com/ru/company/ruvds/blog/475002/), [часть 3](https://habr.com/ru/company/ruvds/blog/476954/) 7 | - [50 вопросов по Docker, которые задают на собеседованиях, и ответы на них](https://habr.com/ru/company/southbridge/blog/528206/) -------------------------------------------------------------------------------- /spring/spring.md: -------------------------------------------------------------------------------- 1 | [Оглавление](../README.md) 2 | 3 | # Spring 4 | 5 | - [Какие есть `scope` в Spring? Какой по умолчанию? Чем `singleton` отличается от `prototype`? Можно ли сделать свой `scope` и как? Плавно переходит в вопрос "Как заинжектить `prototype` в `singleton`?"](#какие-есть-scope-в-spring-какой-по-умолчанию-чем-singleton-отличается-от-prototype-можно-ли-сделать-свой-scope-и-как-плавно-переходит-в-вопрос-как-заинжектить-prototype-в-singleton) 6 | - [Часто спрашивают о циклических зависимостях бинов в Spring. Проблема ли это или что получим в результате? Если проблема, то как её решить?](#часто-спрашивают-о-циклических-зависимостях-бинов-в-spring-проблема-ли-это-или-что-получим-в-результате-если-проблема-то-как-её-решить) 7 | - [Бывают вопросы про жизненный цикл бина, этапы инициализации контекста, про устройство спринга внутри, про DI и как он работает](#бывают-вопросы-про-жизненный-цикл-бина-этапы-инициализации-контекста-про-устройство-спринга-внутри-про-di-и-как-он-работает) 8 | - [Расскажите про прокси и про `@Transactional`. Как работает и зачем? Какие могут быть проблемы? Можно ли навесить `@Transactional` на приватный метод? А если вызывать метод с `@Transactional` внутри другого метода с `@Transactional` одного класса - будет работать?](#расскажите-про-прокси-и-про-transactional-как-работает-и-зачем-какие-могут-быть-проблемы-можно-ли-навесить-transactional-на-приватный-метод-а-если-вызывать-метод-с-transactional-внутри-другого-метода-с-transactional-одного-класса---будет-работать) 9 | - [Где у обычного (НЕ Boot) Spring-приложения main-класс?](#где-у-обычного-не-boot-spring-приложения-main-класс) 10 | - [Как работает Spring Boot и его стартеры?](#как-работает-spring-boot-и-его-стартеры) 11 | - [Как выполняется http-запрос в Spring?](#как-выполняется-http-запрос-в-spring) 12 | 13 | ## Какие есть `scope` в Spring? Какой по умолчанию? Чем `singleton` отличается от `prototype`? Можно ли сделать свой `scope` и как? Плавно переходит в вопрос "Как заинжектить `prototype` в `singleton`?" 14 | 15 | Spring scope: 16 | - `singleton` (по умолчанию) 17 | - `prototype` 18 | - `request` 19 | - `session` 20 | - `application` 21 | - `websocket` 22 | 23 | Про `scope` подробнее можно прочитать в [документации](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-scopes), [Bealdung](https://www.baeldung.com/spring-bean-scopes). И, конечно же, надо посмотреть [Spring-потрошитель Ч. 2](https://www.youtube.com/watch?v=cou_qomYLNU&t=2s). 24 | 25 | Про `prototype` в `singleton` можно вспомнить несколько вариантов: 26 | - `@Lookup` 27 | - Фабрика для создания экземпляров `prototype`-бинов 28 | - `ProxyMod = ScopedProxyMode.TARGET_CLASS` 29 | 30 | Подробнее о каждом варианте есть в [Bealdung](https://www.baeldung.com/spring-inject-prototype-bean-into-singleton) и смотрим [Spring-потрошитель Ч. 2](https://www.youtube.com/watch?v=cou_qomYLNU&t=2s). 31 | 32 | [к содержанию](#spring) 33 | 34 | ## Часто спрашивают о циклических зависимостях бинов в Spring. Проблема ли это или что получим в результате? Если проблема, то как её решить? 35 | 36 | Да, это проблема - будет выброшено исключение `BeanCurrentlyInCreationException` (при внедрении зависимостей через конструктор). 37 | 38 | Варианты решения: 39 | - Ещё раз подумать, той ли дорогой мы держим путь - может не поздно сделать редизайн и избавиться от циклических зависимостей 40 | - Инициализировать один из бинов лениво с помощью `@Lazy` 41 | - Внедрение зависимостей в setter-метод, а не в конструктор 42 | 43 | Подробнее есть в [документации](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-dependency-resolution) и в [Bealdung](https://www.baeldung.com/circular-dependencies-in-spring) 44 | 45 | [к содержанию](#spring) 46 | 47 | ## Бывают вопросы про жизненный цикл бина, этапы инициализации контекста, про устройство спринга внутри, про DI и как он работает 48 | 49 | Тут однозначно надо смотреть Spring-потрошитель [часть 1](https://www.youtube.com/watch?v=BmBr5diz8WA) и [часть 2](https://www.youtube.com/watch?v=cou_qomYLNU&t=2s). Также благое дело - это почитать [документацию](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#spring-core). 50 | 51 | Также по этапам инициализации контекста есть [статья](https://habr.com/ru/post/222579/) с красивыми картинками на хабре. 52 | 53 | [к содержанию](#spring) 54 | 55 | ## Расскажите про прокси и про `@Transactional`. Как работает и зачем? Какие могут быть проблемы? Можно ли навесить `@Transactional` на приватный метод? А если вызывать метод с `@Transactional` внутри другого метода с `@Transactional` одного класса - будет работать? 56 | 57 | Для начала, если вы не знали или случайно забыли про паттерн Proxy в общем виде, то можно освежиться [здесь](https://refactoring.guru/ru/design-patterns/proxy). 58 | 59 | Допустим, что наш сервис `MyServiceImpl` имеет 2 публичных метода, аннотированных `@Transactional` - `method1` и `method2`(он с `Propagation.REQUIRES_NEW`). В `method1` вызываем `method2`. "В связи с тем, что для поддержки транзакций через аннотации используется Spring AOP, в момент вызова `method1()` на самом деле вызывается метод прокси объекта. Создается новая транзакция и далее происходит вызов `method1()` класса `MyServiceImpl`. А когда из `method1()` вызовем `method2()`, обращения к прокси нет, вызывается уже сразу метод нашего класса и, соответственно, никаких новых транзакций создаваться не будет" - это цитата и краткий ответ на вопрос приведена из [статьи](https://habr.com/ru/post/347752/) на хабре, где можно ознакомиться с подробностями. 60 | 61 | Что тут можно ещё посоветовать? Spring-потрошитель опять и снова - [часть 1](https://www.youtube.com/watch?v=BmBr5diz8WA) и [часть 2](https://www.youtube.com/watch?v=cou_qomYLNU&t=2s). А также документация является несомненным и любимым первоисточником информации о [Proxy](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#aop-proxying) и [управление транзакциями](https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html). 62 | 63 | [к содержанию](#spring) 64 | 65 | ## Где у обычного (НЕ Boot) Spring-приложения main-класс? 66 | 67 | Старое доброе обычное Spring-приложение деплоится в [контейнер сервлетов](https://en.wikipedia.org/wiki/Web_container) (или [сервер приложений](https://en.wikipedia.org/wiki/List_of_application_servers#Java)), где и расположен main-класс. При этом оно собирается в [war-архив](https://en.wikipedia.org/wiki/WAR_(file_format)). Когда war-файл разворачивается в контейнере, контейнер обычно распаковывает его для доступа к файлам, а затем запускает приложение. Spring Boot приложение также можно собрать как war и задеплоить его таким же образом. 68 | 69 | Подробнее: 70 | - [Понимание WAR](http://spring-projects.ru/understanding/war/) 71 | - [В чём разница между jar и war?](https://itsobes.ru/JavaSobes/v-chiom-raznitsa-mezhdu-jar-i-war/) 72 | - Конвертация Spring Boot JAR приложения в WAR на [RUS](https://spring-projects.ru/guides/convert-jar-to-war-maven/) или [ENG](https://spring.io/guides/gs/convert-jar-to-war/) 73 | 74 | [к содержанию](#spring) 75 | 76 | ## Как работает Spring Boot и его стартеры? 77 | 78 | Во-первых, благодаря [spring-boot-starter-parent](https://www.baeldung.com/spring-boot-starter-parent), у которого родителем является [spring-boot-dependencies](https://docs.spring.io/spring-boot/docs/2.3.1.RELEASE/maven-plugin/reference/html/#using-import), можно особо не париться о зависимостях и их версиях - [большинство](https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-dependency-versions.html) версии того, что может потребоваться прописано и согласовано в [dependencyManagement](https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#dependency-management) родительского [`pom`](https://maven.apache.org/pom.html#Inheritance). Или можно заимпортировать [BOM](https://www.baeldung.com/spring-maven-bom). 79 | 80 | Spring Boot черпает свою мощь из [стартеров](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-starter) - наборов сконфигурированных бинов со всеми необходимыми зависимостями, готовых к использованию и доступных для тонкой настройки через properties-файлы. 81 | 82 | Для Spring Boot приложения создаётся main-класс с аннотацией [@SpringBootApplication](https://docs.spring.io/spring-boot/docs/2.0.x/reference/html/using-boot-using-springbootapplication-annotation.html) и запуском метода [run](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/SpringApplication.html#run-java.lang.Class:A-java.lang.String:A-) класса [SpringApplication](https://docs.spring.io/spring-boot/docs/2.1.10.RELEASE/reference/html/boot-features-spring-application.html), который возвращает [ApplicationContext](http://spring-projects.ru/understanding/application-context/). 83 | 84 | ```java 85 | @SpringBootApplication 86 | public class MyApplication { 87 | 88 | public static void main(String[] args) { 89 | SpringApplication.run(MyApplication.class, args); 90 | } 91 | } 92 | ``` 93 | 94 | Аннотация `@SpringBootApplication` просто скрывает за собой аннотации [@EnableAutoConfiguration](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/EnableAutoConfiguration.html), [@ComponentScan](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/ComponentScan.html) и [@Configuration](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html). 95 | 96 | `SpringBootApplication` создаёт либо [WebApplicationContext](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/context/WebApplicationContext.html) (если в classpath есть [Servlet](https://docs.oracle.com/javaee/7/api/javax/servlet/Servlet.html) и [ConfigurableWebApplicationContext](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/context/ConfigurableWebApplicationContext.html)), либо [GenericApplicationContext](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/support/GenericApplicationContext.html). 97 | 98 | При создании стартера используется файл [META-INF/spring.factories](https://docs.spring.io/autorepo/docs/spring-boot/2.0.0.M3/reference/html/boot-features-developing-auto-configuration.html) - в нём ключу `org.springframework.boot.autoconfigure.EnableAutoConfiguration` приравнивается список из полных имён всех классов-конфигураций (а в них бины, `@ComponentScan`, `@Import` и т.п.) стартера через запятую. 99 | 100 | Аннотация `@EnableAutoConfiguration` импортирует [AutoConfigurationImportSelector](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.html), который и отвечает за поиск необходимых классов конфигурации. Вызов метода `getCandidateConfigurations` обращается к [SpringFactoriesLoader](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/io/support/SpringFactoriesLoader.html) и его методу `loadFactoryNames`, чтобы просканировать classpath на наличие файлов `META-INF/spring.factories` и имен классов-конфигураций в них, а затем загрузить их в контекст. 101 | 102 | Также у Spring boot есть модуль `spring-boot-autoconfigure` со своим файлом [META-INF/spring.factories](https://github.com/spring-projects/spring-boot/blob/v2.0.0.M3/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories). Чтобы не создавать все-все бины из конфигураций, у бинов используется аннотация [@Conditional](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Conditional.html) (или её вариации) с каким-либо условием. 103 | 104 | Чтобы упаковать Spring boot в jar используется [spring-boot-maven-plugin](https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/html/). У такого jar в `META-INF/MANIFEST.MF` будет прописан `Main-Class` - [org.springframework.boot.loader.JarLauncher](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/loader/JarLauncher.html), а в `Start-Class` будет уже main-класс нашего приложения. `JarLauncher` формирует class path (в начале в нём только `org.springframework.boot`), который находится в `BOOT-INF`(там `lib` с зависимостями и `class` с классами приложения), а затем запускает `Start-Class`. 105 | 106 | Посмотреть: 107 | - Доклад Евгения Борисова и Кирилла Толкачёва Boot yourself, Spring is coming: [часть 1](https://www.youtube.com/watch?v=yy43NOreJG4&t=1s), [часть 2](https://www.youtube.com/watch?v=7Cq5zEm2wq0). На Хабре есть текстовая расшифровка: [часть 1](https://habr.com/ru/company/jugru/blog/424503/), [часть 2](https://habr.com/ru/company/jugru/blog/425333/). 108 | - Доклад Кирилла Толкачёва и Максима Гореликова [Spring Boot Starter — как и зачем?](https://www.youtube.com/watch?v=2_iE7jZWl3U) 109 | - Доклад Кирилла Толкачёва и Александра Тарасова — [Твой личный Spring Boot Starter](https://www.youtube.com/watch?v=5WdzD15xE-4) 110 | 111 | Почитать: 112 | - На Хабре: [Как работает Spring Boot Auto-Configuration](https://habr.com/ru/post/487980/), [Пишем свой spring-boot-starter](https://habr.com/ru/post/275337/) и [Использование Conditional в Spring](https://habr.com/ru/post/462541/) 113 | - Hа Baeldung: [A Comparison Between Spring and Spring Boot](https://www.baeldung.com/spring-vs-spring-boot), [Create a Custom Auto-Configuration with Spring Boot](https://www.baeldung.com/spring-boot-custom-auto-configuration), [Intro to Spring Boot Starters](https://www.baeldung.com/spring-boot-starters), [Spring Boot: Configuring a Main Class](https://www.baeldung.com/spring-boot-main-class) 114 | - [What is Spring Boot? Autoconfigurations In-Depth](https://www.marcobehler.com/guides/spring-boot) 115 | - [Spring Boot for beginners](https://github.com/in28minutes/SpringBootForBeginners) 116 | - [Spring Boot Documentation](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-documentation) 117 | - [Список](https://github.com/spring-projects/spring-boot/tree/master/spring-boot-project/spring-boot-starters) готовых стартеров 118 | 119 | [к содержанию](#spring) 120 | 121 | ## Как выполняется http-запрос в Spring? 122 | 123 | В современном Spring есть два подхода к построению веб-приложений: 124 | - Spring MVC 125 | - Spring WebFlux 126 | 127 | Работа Spring MVC строится вокруг [DispatcherServlet](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/DispatcherServlet.html), который является обычным `Servlet`'ом и реализует паттерн [Front Controller](http://design-pattern.ru/patterns/front-controller.html): принимает Http-запросы и координирует их с требуемыми обработчиками. Для своей конфигурации `DispatcherServlet` [использует](https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-servlet-context-hierarchy) [WebApplicationContext](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/context/WebApplicationContext.html). `DispatcherServlet` в обработке запроса помогают несколько ["специальных бинов"](https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-servlet-special-bean-types) [следующим образом](https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-servlet-sequence): 128 | 1. После получения HTTP-запроса `DispatcherServlet` перебирает доступные ему (предварительно найденные в контексте) экземпляры [HandlerMapping](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/HandlerMapping.html), один из которых определит, метод какого `Controller` должен быть вызван. Реализации `HandlerMapping`, использующиеся по умолчанию: [BeanNameUrlHandlerMapping](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/handler/BeanNameUrlHandlerMapping.html) и [RequestMappingHandlerMapping](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.html) (создаёт экземпляры [RequestMappingInfo](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/RequestMappingInfo.html) по методам аннотированным [@RequestMapping](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html) в классах с аннотацией [@Controller](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/stereotype/Controller.html)). `HandlerMapping` по [HttpServletRequest](https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletRequest.html?is-external=true) находит соответствующий обработчик - handler-объект (например, [HandlerMethod](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/method/HandlerMethod.html)). Каждый `HandlerMapping` может иметь несколько реализаций [HandlerInterceptor](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/HandlerInterceptor.html) - интерфейса для кастомизации [пред- и постобработки](https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-handlermapping-interceptor) запроса. Список из `HandlerInterceptor`'ов и handler-объекта образуют экземпляр класса [HandlerExecutionChain](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/HandlerExecutionChain.html), который возвращается в `DispatcherServlet`. 129 | 2. Для выбранного обработчика определяется соответствующий [HandlerAdapter](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/HandlerAdapter.html) из предварительно найденных в контексте. По умолчанию используются [HttpRequestHandlerAdapter](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/HttpRequestHandlerAdapter.html) (поддерживает классы, реализующие интерфейс [HttpRequestHandler](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/HttpRequestHandler.html)), [SimpleControllerHandlerAdapter](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/SimpleControllerHandlerAdapter.html) (поддерживает классы, реализующие интерфейс [Controller](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/mvc/Controller.html)) или [RequestMappingHandlerAdapter](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.html) (поддерживает контроллеры с аннотацией `@RequestMapping`). 130 | 3. Происходит вызов метода `applyPreHandle` объекта `HandlerExecutionChain`. Если он вернёт `true`, то значит все `HandlerInterceptor` выполнили свою предобработку и можно перейти к вызову основного обработчика. `false` будет означать, что один из `HandlerInterceptor` взял обработку ответа на себя в обход основного обработчика. 131 | 4. Выбранный `HandlerAdapter` извлекается из `HandlerExecutionChain` и с помощью метода `handle` принимает объекты запроса и ответа, а также найденный метод-обработчик запроса. 132 | 5. Метод-обработчик запроса из `Controller` (вызванный через `handle`) выполняется и возвращает в `DispatcherServlet` [ModelAndView](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/ModelAndView.html). При помощи интерфейса [ViewResolver](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/ViewResolver.html) `DispatcherServlet` [определяет](https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-viewresolver), какой [View](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/View.html) нужно использовать на основании полученного имени. 133 | Если мы имеем дело с REST-Controller или RESTful-методом контроллера, то вместо `ModelAndView` в `DispatcherServlet` из `Controller` вернётся `null` и, соответственно, никакой `ViewResolver` задействован не будет - ответ сразу будет полностью содержаться в теле [HttpServletResponse](https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletResponse.html) после выполнения `handle`. Чтобы определить RESTful-методы, достаточно аннотировать их [@ResponseBody](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ResponseBody.html) либо вместо `@Controller` у класса поставить [@RestController](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RestController.html), если все методы котроллера будут RESTful. 134 | 6. Перед завершением обработки запроса у объекта `HandlerExecutionChain` вызывается метод `applyPostHandle` для постобработки с помощью `HandlerInterceptor`ов. 135 | 7. Если в процессе обработки запроса выбрасывается исключение, то оно [обрабатывается](https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-exceptionhandlers) с помощью одной из реализаций интерфейса [HandlerExceptionResolver](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/HandlerExceptionResolver.html). По умолчанию используются [ExceptionHandlerExceptionResolver](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.html) (обрабатывает исключени из методов, аннотированных [@ExceptionHandler](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/ExceptionHandler.html)), [ResponseStatusExceptionResolver](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/annotation/ResponseStatusExceptionResolver.html) (используется для отображения исключений аннотированных [@ResponseStatus](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ResponseStatus.html) в коды HTTP-статусов) и [DefaultHandlerExceptionResolver](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.html) (отображает стандартные исключения Spring MVC в коды HTTP-статусов). 136 | 8. В случае с классическим `Controller` после того, как `View` создан, `DispatcherServlet` отправляет данные в виде атрибутов в `View`, который в конечном итоге записывается в `HttpServletResponse`. Для REST-Controller ответ данная логика не вызывается, ведь ответ уже в `HttpServletResponse`. 137 | 138 | Когда HTTP запрос приходит с указанным заголовком Accept, Spring MVC перебирает доступные [HttpMessageConverter](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/http/converter/HttpMessageConverter.html) до тех пор, пока не найдет того, кто сможет конвертировать из типов POJO доменной модели в указанный тип заголовка Accept. `HttpMessageConverter` работает в обоих направлениях: тела входящих запросов конвертируются в Java объекты, а Java объекты конвертируются в тела HTTP ответов. 139 | 140 | По умолчанию, Spring Boot определяет довольно обширный набор реализаций `HttpMessageConverter`, подходящие для использования широкого круга задач, но также можно добавить поддержку и для других форматов в виде собственной или сторонней реализации `HttpMessageConverter` или переопределить существующие. 141 | 142 | Также стоит упомянуть, что как и в случае любого другого сервлета, к обработке запроса в Spring MVC может быть применена одна из реализаций интерфейса [javax.servlet.Filter](https://docs.oracle.com/javaee/7/api/javax/servlet/Filter.html?is-external=true) как до выполнения запроса, так и после. Sring MVC предоставляет несколько уже [готовых реализаций](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/filter/package-summary.html). 143 | 144 | Отдельного разговора заслуживает путь запроса по внутренностям Spring Security, где используется множество различных фильтров. На хабре есть [статья](https://habr.com/ru/post/346628/) об этом. 145 | 146 | Подробнее: 147 | - [Spring MVC — основные принципы](https://habr.com/ru/post/336816/) на Хабре 148 | - [Путь запроса по внутренностям Spring Security](https://habr.com/ru/post/346628/) на Хабре 149 | - [An Intro to the Spring DispatcherServlet](https://www.baeldung.com/spring-dispatcherservlet) на Bealdung 150 | - [HandlerAdapters in Spring MVC](https://www.baeldung.com/spring-mvc-handler-adapters) на Bealdung 151 | - [Quick Guide to Spring Controllers](https://www.baeldung.com/spring-controllers) на Bealdung 152 | - [Spring RequestMapping](https://www.baeldung.com/spring-requestmapping) на Bealdung 153 | - [Http Message Converters with the Spring Framework](https://www.baeldung.com/spring-httpmessageconverter-rest) на Bealdung 154 | - [How to Define a Spring Boot Filter?](https://www.baeldung.com/spring-boot-add-filter) на Bealdung 155 | - [Spring Professional Study Notes](https://jakubstas.com/spring-professional-study-notes/#.WUaMx2jytzo) 156 | - [Spring Security Architecture](https://spring.io/guides/topicals/spring-security-architecture/) 157 | - [Схематично](https://terasolunaorg.github.io/guideline/1.0.1.RELEASE/en/Overview/SpringMVCOverview.html#id1) 158 | 159 | Документация: 160 | - [Spring Web MVC](https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc) 161 | - [Spring MVC Auto-configuration в Spring Boot](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-spring-mvc-auto-configuration) 162 | 163 | Spring WebFlux - это реактивный веб-фреймворк, который появился в Spring Framework 5.0. Он не требует Servlet API (но может использовать Servlet 3.1+containers, хотя чаще это [Netty](https://netty.io/) (по умолчанию в Spring Boot) или [Undertow](https://undertow.io/)), полностью асинхронный и неблокирующий, реализует спецификацию [Reactive Streams](https://www.reactive-streams.org/) при помощи [проекта Reactor](https://projectreactor.io/). 164 | 165 | В Spring WebFlux используется большинство аннотаций из Spring MVC (RestController, RequestMapping и другие) для определения [аннотированных контроллеров](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-controller). Однако представляет новую возможность создания [функциональных котроллеров](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-fn), основанных на [HandlerFunction](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-fn-handler-functions). 166 | 167 | В Spring WebFlux обработка запроса на стороне сервера строится в два уровня: 168 | - [HttpHandler](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/server/reactive/HttpHandler.html) - это базовый интерфейс обработки HTTP-запросов с использованием неблокирующего I/O, Reactive Streams back pressure через адаптеры для Reactor Netty, Undertow и т.д. 169 | - [WebHandler](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/server/WebHandler.html) - интерфейс, который предоставляет верхнеуровневое API для обработки HTTP-запросов поверх аннотированных или функциональных контроллеров. 170 | 171 | Контракт `HttpHandler` представляет обработку HTTP-запроса, как его прохождение через цепочку множества [WebExceptionHandler](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/server/WebExceptionHandler.html), множества [WebFilter](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/server/WebFilter.html) и одного единственного [WebHandler](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/server/WebHandler.html). Сборкой цепочки занимается [WebHttpHandlerBuilder](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/server/adapter/WebHttpHandlerBuilder.html) при помощи [ApplicationContext](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContext.html). 172 | 173 | Диспетчеризация запросов в Spring WebFlux выполняется [DispatcherHandler](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/DispatcherHandler.html), который является имплементацией интерфейса [WebHandler](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/server/WebHandler.html) и также реализует паттерн [Front Controller](http://design-pattern.ru/patterns/front-controller.html): принимает Http-запросы и координирует их с требуемыми обработчиками. `DispatcherHandler` - это Spring bean, имплементирующий [ApplicationContextAware](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContextAware.html) для доступа к контексту, с которым он был запущен. `DispatcherHandler` с бин-именем `webHandler` обнаруживает `WebHttpHandlerBuilder` и помещает в цепочку в качестве `WebHandler`. 174 | 175 | `DispatcherHandler` в ходе обработки http-запроса и ответа делегирует часть работы ["специальным бинам"](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-special-bean-types), которые могут быть подвержены кастомизации, расширению и замене пользователем. Сам процесс обработки выглядит следующим образом: 176 | 177 | ```java 178 | @Override 179 | public Mono handle(ServerWebExchange exchange) { 180 | if (this.handlerMappings == null) { 181 | return createNotFoundError(); 182 | } 183 | return Flux.fromIterable(this.handlerMappings) 184 | .concatMap(mapping -> mapping.getHandler(exchange)) 185 | .next() 186 | .switchIfEmpty(createNotFoundError()) 187 | .flatMap(handler -> invokeHandler(exchange, handler)) 188 | .flatMap(result -> handleResult(exchange, result)); 189 | } 190 | ``` 191 | 192 | 1. Каждый из экземпляров [HandlerMapping](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/HandlerMapping.html) пытается найти подобающий обработчик для данного запроса (какой-то метод, какого-то контроллера). В итоге выбирается первый найденный обработчик (`handler`). Основными доступными реализациями `HandlerMapping` являются: 193 | - [RequestMappingHandlerMapping](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerMapping.html) для методов-обработчиков, аннотированных `@RequestMapping` 194 | - [RouterFunctionMapping](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/reactive/function/server/support/RouterFunctionMapping.html) для функциональных обработчиков 195 | - [SimpleUrlHandlerMapping](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/handler/SimpleUrlHandlerMapping.html) для маппинга URL-ов на бины-обработчики запросов 196 | 2. Если обработчик найден, то для него (в `invokeHandler`) выбирается подходящий [HandlerAdapter](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/HandlerAdapter.html), вызывается его метод `handle` для непосредственной обработки запроса выбранным обработчиком. Результат обработки упаковывается в [HandlerResult](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/HandlerResult.html), который возвращается в `DispatcherHandler`. Главная задача `HandlerAdapter` - скрыть детали и способ непосредственного вызова метода-обработчика от `DispatcherHandler`. Примерами доступных реализаций `HandlerAdapter` являются: 197 | - [RequestMappingHandlerAdapter](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerAdapter.html) - для вызова методов, аннотированных `@RequestMapping` 198 | - [HandlerFunctionAdapter](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/function/server/support/HandlerFunctionAdapter.html) - для вызова [HandlerFunctions](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/function/server/HandlerFunction.html) 199 | 3. Полученный `HandlerResult` обрабатывается (в `handleResult`) необходимым для него [HandlerResultHandler](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/HandlerResultHandler.html). Здесь обработка завершается формированием ответа на запрос требуемым образом. По умолчанию [доступно](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-resulthandling) несколько реализаций `HandlerResultHandler`: 200 | - [ResponseEntityResultHandler](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandler.html) - обрабатывает [ResponseEntity](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/http/ResponseEntity.html), обычно из `@Controller` 201 | - [ServerResponseResultHandler](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/function/server/support/ServerResponseResultHandler.html) - обрабатывает [ServerResponse](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/function/server/ServerResponse.html), обычно из функциональных контроллеров 202 | - [ResponseBodyResultHandler](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/reactive/result/method/annotation/ResponseBodyResultHandler.html) - обрабатывает возвращаемые значения из методов, аннотированных `@ResponseBody`, или методов класса `@RestController` 203 | - [ViewResolutionResultHandler](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/result/view/ViewResolutionResultHandler.html) - инкапсулирует в себе алгоритм [View Resolution](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-viewresolution) и обработку поддерживаемых данным алгоритмом типов результатов 204 | 205 | Документация: 206 | - [Spring WebFlux](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux) 207 | - [Spring WebFlux Auto-configuration в Spring Boot](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-webflux-auto-configuration) 208 | 209 | [к содержанию](#spring) --------------------------------------------------------------------------------