Как вы попали на собеседование на текущее место работы?
Anonymous Poll
27%
Откликнулся на HeadHunter
11%
Откликнулся на сайте компании
30%
Пришёл по рекомендации
33%
HR меня нашёл и позвал на собеседование
👍2
Хочешь хорошую работу? Закрой HH
Популярный способ найти работу — открыть HeadHunter и откликнуться на подходящие вакансии. Способ простой, но поиск растянется на недели и маловероятно, что вы найдёте вакансию мечты.
Почему так происходит? HR Арина написала прекрасный лонгрид на эту тему: Найти работу и не впасть в отчаяние.
Краткий пересказ:
На вакансию средних и крупных компанию откликается 100-1000 человек. Даже если вы идеально подходите на должность, резюме могут:
🔸Пропустить
🔸Невнимательно посмотреть
🔸Отбросить за малейший недочёт
Попробуйте другие стратегии — целевой поиск и рекомендации.
1️⃣ Целевой поиск
Cоставить список интересных компаний и общаться с ними напрямую. В составлении списка поможет HH.
Зайдите на сайт каждой компании в списке, найдите вкладку Jobs/Careers и отправьте резюме и сопроводительное письмо.
Зафиксируйте в списке контакты, открытые позиции, вопросы с собеседований, обратную связь работодателей.
✅ Рекрутёр оценит вашу инициативность.
✅ Отклик попадает на почту рекрутёру или во внутреннюю систему компании. Шанс, что письмо прочитают, в разы выше, чем на HH.
2️⃣ Рекомендации
Напишите бывшим коллегам и начальникам: спросите о текущих проектах в компании. Расскажите, что ищете работу и попросите порекомендовать вас.
✅ Заранее узнаете информацию о проектах и требованиях.
✅ Собеседование скорее всего будет проще.
Мои дополнения:
🔹В IT за рекомендацию кандидатов часто выдают бонусы, поэтому бывшие коллеги вам с радостью помогут.
🔹Для джуниор-мидл разработчиков целевой поиск обязателен. Если вам нравится компания, но на сайте нет подходящей по уровню вакансии, то попробуйте следующий способ:
На контакт из вкладки Careers отправьте резюме и примерно такое мотивационное письмо:
Здравствуйте, меня зовут ...
Я давно слежу за компанией Х, и мне очень нравится направление её работы. Ваша платформа помогает сотням интернет-магазинов с бухгалтерией, вы делаете ценный вклад в развитие малого бизнеса.
Подскажите, пожалуйста, как можно присоединиться к вашей команде?
Я — начинающий java разработчик. Моё резюме - в приложении к письму.
С уважением, ...
Вы не навязываетесь, всего лишь просите совет. Такие формулировки встречаются редко и увеличивают шанс получить обратную связь или приглашение на собеседование😌
Популярный способ найти работу — открыть HeadHunter и откликнуться на подходящие вакансии. Способ простой, но поиск растянется на недели и маловероятно, что вы найдёте вакансию мечты.
Почему так происходит? HR Арина написала прекрасный лонгрид на эту тему: Найти работу и не впасть в отчаяние.
Краткий пересказ:
На вакансию средних и крупных компанию откликается 100-1000 человек. Даже если вы идеально подходите на должность, резюме могут:
🔸Пропустить
🔸Невнимательно посмотреть
🔸Отбросить за малейший недочёт
Попробуйте другие стратегии — целевой поиск и рекомендации.
1️⃣ Целевой поиск
Cоставить список интересных компаний и общаться с ними напрямую. В составлении списка поможет HH.
Зайдите на сайт каждой компании в списке, найдите вкладку Jobs/Careers и отправьте резюме и сопроводительное письмо.
Зафиксируйте в списке контакты, открытые позиции, вопросы с собеседований, обратную связь работодателей.
✅ Рекрутёр оценит вашу инициативность.
✅ Отклик попадает на почту рекрутёру или во внутреннюю систему компании. Шанс, что письмо прочитают, в разы выше, чем на HH.
2️⃣ Рекомендации
Напишите бывшим коллегам и начальникам: спросите о текущих проектах в компании. Расскажите, что ищете работу и попросите порекомендовать вас.
✅ Заранее узнаете информацию о проектах и требованиях.
✅ Собеседование скорее всего будет проще.
Мои дополнения:
🔹В IT за рекомендацию кандидатов часто выдают бонусы, поэтому бывшие коллеги вам с радостью помогут.
🔹Для джуниор-мидл разработчиков целевой поиск обязателен. Если вам нравится компания, но на сайте нет подходящей по уровню вакансии, то попробуйте следующий способ:
На контакт из вкладки Careers отправьте резюме и примерно такое мотивационное письмо:
Здравствуйте, меня зовут ...
Я давно слежу за компанией Х, и мне очень нравится направление её работы. Ваша платформа помогает сотням интернет-магазинов с бухгалтерией, вы делаете ценный вклад в развитие малого бизнеса.
Подскажите, пожалуйста, как можно присоединиться к вашей команде?
Я — начинающий java разработчик. Моё резюме - в приложении к письму.
С уважением, ...
Вы не навязываетесь, всего лишь просите совет. Такие формулировки встречаются редко и увеличивают шанс получить обратную связь или приглашение на собеседование😌
👍3❤1
🍃Spring: статистика использования
Есть ли в java мире более популярный фреймворк, чем Spring?
Кажется, что нет. Spring упоминается в половине вакансий на HeadHunter и используется в большинстве веб-сервиcов на java.
Spring— огромная экосистема из 24 проектов. Все освоить невозможно, да и не нужно. Лучше сфокусироваться на самых актуальных. Компания VMWare занимается виртуализацией и недавно провела опрос более тысячи разработчиков: как и с чем они используют Spring. Результаты опроса собрались в доклад State of Spring 2020:
Какие модули Spring используются чаще всего?
▫️>75% - MVC, Security, Data
▫️56% - Cloud
▫️30-40% - Batch, Integration, Kafka
Spring Boot на пике популярности:
🔸82% разработчиков пишут на нём новые проекты
🔸53% планируют перевести на Spring Boot легаси проекты
Что нравится в Spring Boot:
🔹70% - Готовые конфигурации
🔹64% - Стабильность, безопасность, масштабируемость
🔹61% - Удобство разработки
Что вызывает вопросы:
▪️39% - Непонятно, как это работает😅
▪️34% - Долгий запуск приложений
▪️25% - Высокое потребление памяти
*В апреле у Spring появилась поддержка GraalVM. С ним время запуска и расход памяти будут ниже.
Какая архитектура встречается в приложениях Spring Boot?
▫️83% - Микросервисы
▫️33% - Реактивная (Project Reactor, Webflux)
▫️12% - Serverless (Spring Cloud Function)
Где Spring Boot, там и Docker:
🔸65% уже запускают приложения в контейнерах
🔸30% планируют начать в этом году
Где Docker, там и Kubernetes:
▪️44% уже используют Kubernetes для развёртывания
▪️31% планируют перейти в течение 12 месяцев
Люблю такие опросы: видно, куда движется разработка бэкенда. Начинающим разработчикам полезно вдвойне - понятно, что и в каком порядке изучать.
#статистика
Есть ли в java мире более популярный фреймворк, чем Spring?
Кажется, что нет. Spring упоминается в половине вакансий на HeadHunter и используется в большинстве веб-сервиcов на java.
Spring— огромная экосистема из 24 проектов. Все освоить невозможно, да и не нужно. Лучше сфокусироваться на самых актуальных. Компания VMWare занимается виртуализацией и недавно провела опрос более тысячи разработчиков: как и с чем они используют Spring. Результаты опроса собрались в доклад State of Spring 2020:
Какие модули Spring используются чаще всего?
▫️>75% - MVC, Security, Data
▫️56% - Cloud
▫️30-40% - Batch, Integration, Kafka
Spring Boot на пике популярности:
🔸82% разработчиков пишут на нём новые проекты
🔸53% планируют перевести на Spring Boot легаси проекты
Что нравится в Spring Boot:
🔹70% - Готовые конфигурации
🔹64% - Стабильность, безопасность, масштабируемость
🔹61% - Удобство разработки
Что вызывает вопросы:
▪️39% - Непонятно, как это работает😅
▪️34% - Долгий запуск приложений
▪️25% - Высокое потребление памяти
*В апреле у Spring появилась поддержка GraalVM. С ним время запуска и расход памяти будут ниже.
Какая архитектура встречается в приложениях Spring Boot?
▫️83% - Микросервисы
▫️33% - Реактивная (Project Reactor, Webflux)
▫️12% - Serverless (Spring Cloud Function)
Где Spring Boot, там и Docker:
🔸65% уже запускают приложения в контейнерах
🔸30% планируют начать в этом году
Где Docker, там и Kubernetes:
▪️44% уже используют Kubernetes для развёртывания
▪️31% планируют перейти в течение 12 месяцев
Люблю такие опросы: видно, куда движется разработка бэкенда. Начинающим разработчикам полезно вдвойне - понятно, что и в каком порядке изучать.
#статистика
👍5
В java 15 в продакшн стадию вошли 2 новых сборщика мусора — Shenandoah и ZGC. Возникает логичный вопрос — зачем они нужны? В java 8 и так 4 сборщика, что с ними не так?
Кратко ответить не получилось, поэтому на этой неделе выйдет роман в трёх частях:
🔸Часть 1: обзор и принцип работы
🔸Часть 2: Serial, Parallel, CMS, G1
🔸Часть 3: Shenandoah, ZGC, Epsilon
Кратко ответить не получилось, поэтому на этой неделе выйдет роман в трёх частях:
🔸Часть 1: обзор и принцип работы
🔸Часть 2: Serial, Parallel, CMS, G1
🔸Часть 3: Shenandoah, ZGC, Epsilon
Сборщики мусора: часть 1. Обзор
Сборка мусора — фоновый процесс в JVM, который удаляет уже ненужные объекты. В основном каждая реализация балансирует между двумя параметрами:
🔹Latency: максимальное время обработки запроса
🔹Пропускная способность: сколько запросов обработается в минуту
"Запрос" здесь - взаимодействие приложения с памятью: создание, обновление и удаление объектов.
Приоритет зависит от приложения:
▪️Для веб-сервисов большие задержки недопустимы. Лучше в среднем ответ будет на четверть секунды дольше, но не будет подвисших запросов.
▪️Приложение работает в фоновом режиме. Например, архивирует записи. Не критично, если каждая сотая запись будет архивироваться 5 секунд, если за час обработается больше данных.
Алгоритм коллектора везде один и тот же:
🔸Отмечаем объекты, которые нужны
🔸Помечаем остальные объекты на удаление
🔸Удаляем ненужные объекты
🔸Группируем выжившие
Чтобы понять, какие объекты нужны приложению, строится граф достижимых объектов. Самостоятельные объекты называются roots и существуют без привязки к другим. Это локальные и статические переменные, потоки и т.д.
Смотрим, на какие объекты ссылаются roots. Идём дальше по ссылкам и получаем граф живых объектов.
⚠️Но есть проблема: объекты в памяти постоянно меняются. Есть две крайности:
1️⃣ Когда памяти останется мало, целиком остановить приложение и убрать мусор. Будет большая пауза, но в остальное время сборщик не будет тормозить основное приложение.
2️⃣ Следить за статусом объектов и ссылок, вести таблицы использования. Так ненужные объекты легко найти, но сам сборщик будет занимать много процессорного времени.
Разные коллекторы балансируют между этими крайностями: некоторые фазы происходят параллельно, а для некоторых нужна полная остановка.
Универсального сборщика нет, на выбор влияет количество процессоров, памяти, тип нагрузки и так далее.
В части 2 мы подробно рассмотрим сборщики мусора в java 8
#jvm
Сборка мусора — фоновый процесс в JVM, который удаляет уже ненужные объекты. В основном каждая реализация балансирует между двумя параметрами:
🔹Latency: максимальное время обработки запроса
🔹Пропускная способность: сколько запросов обработается в минуту
"Запрос" здесь - взаимодействие приложения с памятью: создание, обновление и удаление объектов.
Приоритет зависит от приложения:
▪️Для веб-сервисов большие задержки недопустимы. Лучше в среднем ответ будет на четверть секунды дольше, но не будет подвисших запросов.
▪️Приложение работает в фоновом режиме. Например, архивирует записи. Не критично, если каждая сотая запись будет архивироваться 5 секунд, если за час обработается больше данных.
Алгоритм коллектора везде один и тот же:
🔸Отмечаем объекты, которые нужны
🔸Помечаем остальные объекты на удаление
🔸Удаляем ненужные объекты
🔸Группируем выжившие
Чтобы понять, какие объекты нужны приложению, строится граф достижимых объектов. Самостоятельные объекты называются roots и существуют без привязки к другим. Это локальные и статические переменные, потоки и т.д.
Смотрим, на какие объекты ссылаются roots. Идём дальше по ссылкам и получаем граф живых объектов.
⚠️Но есть проблема: объекты в памяти постоянно меняются. Есть две крайности:
1️⃣ Когда памяти останется мало, целиком остановить приложение и убрать мусор. Будет большая пауза, но в остальное время сборщик не будет тормозить основное приложение.
2️⃣ Следить за статусом объектов и ссылок, вести таблицы использования. Так ненужные объекты легко найти, но сам сборщик будет занимать много процессорного времени.
Разные коллекторы балансируют между этими крайностями: некоторые фазы происходят параллельно, а для некоторых нужна полная остановка.
Универсального сборщика нет, на выбор влияет количество процессоров, памяти, тип нагрузки и так далее.
В части 2 мы подробно рассмотрим сборщики мусора в java 8
#jvm
👍3❤1
Сборщики мусора, часть 2. Java 8
В команде java 8 четыре участника: Serial GC, Parallel GC, CMS, G1.
Прежде, чем разобрать разницу между ними, повторим теорию. Базовый алгоритм сборки мусора такой:
🔸Построить граф живых объектов
🔸Пометить те, что остались, на удаление
🔸Удалить ненужные объекты
🔸Сгруппировать выжившие
*Сборщики в java 8 пропускают последнюю фазу
Обходить каждый раз всю память - долго и нерационально. Выгоднее всего убирать локальные переменные и промежуточные объекты. Это суть гипотезы поколений:
Память делится на регионы. Новые объекты помещаются в область «новое поколение». Там сборщик будет работать чаще всего. Объекты, которые пережили несколько сборок, считаются «старыми» и переносятся в другую область памяти. Их проверяют реже.
Сборка может быть трёх типов:
▫️Minor - обойти только молодое поколение
▫️Major - только старое
▫️Full - память целиком
Перейдём к практике. Я опустила 90% деталей, чтобы наглядно показать разницу между коллекторами.
Serial GC
При любом типе сборки коллектор останавливает потоки основного приложения. Один поток коллектора выполняет все этапы.
✅ Минимум действий при работе приложения
❌ Долгие паузы
Когда ок: память до 100 МБ, одно ядро, остановки не критичны
Parallel GC
Тоже останавливает работу приложения, но запускает несколько потоков для сборки мусора. Сборщик по умолчанию в java 8.
✅ Работает почти незаметно — не более 1% процессорного времени
❌ Чем больше памяти — тем дольше паузы.
CMS - Concurrent Mark Sweep
Старое и новое поколение обрабатывается по-разному.
▫️Чистка нового поколения как в Parallel GC: основное приложение останавливается, и запускаются несколько потоков коллектора.
▫️Старшее поколение собирается по-другому:
Большая часть графа объектов строится параллельно с основным приложением. Объекты удаляются тоже параллельно. Поэтому сборщик и называется Concurrent Mark Sweep - параллельная разметка и удаление.
⛔️ Помечен Deprecated в Java 9, потому что по всем фронтам уступает G1
G1 - Garbage First
Предыдущие сборщики делили память на 3-4 большие области — одно для старого поколения и 2-3 для нового. Суть G1 — деление памяти на 2048 регионов, которым присваивается тип - свободный, young, survivor или old.
Что это даёт:
▪️Сборщик обрабатывает только несколько регионов, а не всё поколение за раз.
▪️Можно менять количество регионов и регулировать время паузы.
▪️Приложения с большой памятью не тормозят, тк память обрабатывается по частям.
▪️Если регион однородный, можно сразу поменять его тип. Был молодой — стал свободный. Был молодой — стал выживший.
▪️Каждый регион мониторится отдельно. Так G1 выбирает перспективные регионы, куда недавно добавилось много объектов. Отсюда и название - Garbage First.
В остальном G1 похож на предыдущие сборщики:
🔹Уборка в молодом поколении останавливает потоки приложения.
🔹Общая проходит как у CMS — некоторые фазы тормозят работу приложения, некоторые работают параллельно
✅ Есть настройка длины паузы и других параметров. Гайд по тюнингу G1
✅ Работает с большой памятью
✅ Анализирует статистику сборок, хорошо работает с настройками по умолчанию.
❌ Занимает до 10% процессорного времени
G1 показывает отличные результаты в энтерпрайзе. В java 9 стал сборщиком мусора по умолчанию.
В следующей части посмотрим на новые сборщики — Shenandoah, ZGC и Epsilon GC.
#jvm
В команде java 8 четыре участника: Serial GC, Parallel GC, CMS, G1.
Прежде, чем разобрать разницу между ними, повторим теорию. Базовый алгоритм сборки мусора такой:
🔸Построить граф живых объектов
🔸Пометить те, что остались, на удаление
🔸Удалить ненужные объекты
🔸Сгруппировать выжившие
*Сборщики в java 8 пропускают последнюю фазу
Обходить каждый раз всю память - долго и нерационально. Выгоднее всего убирать локальные переменные и промежуточные объекты. Это суть гипотезы поколений:
Память делится на регионы. Новые объекты помещаются в область «новое поколение». Там сборщик будет работать чаще всего. Объекты, которые пережили несколько сборок, считаются «старыми» и переносятся в другую область памяти. Их проверяют реже.
Сборка может быть трёх типов:
▫️Minor - обойти только молодое поколение
▫️Major - только старое
▫️Full - память целиком
Перейдём к практике. Я опустила 90% деталей, чтобы наглядно показать разницу между коллекторами.
Serial GC
При любом типе сборки коллектор останавливает потоки основного приложения. Один поток коллектора выполняет все этапы.
✅ Минимум действий при работе приложения
❌ Долгие паузы
Когда ок: память до 100 МБ, одно ядро, остановки не критичны
Parallel GC
Тоже останавливает работу приложения, но запускает несколько потоков для сборки мусора. Сборщик по умолчанию в java 8.
✅ Работает почти незаметно — не более 1% процессорного времени
❌ Чем больше памяти — тем дольше паузы.
CMS - Concurrent Mark Sweep
Старое и новое поколение обрабатывается по-разному.
▫️Чистка нового поколения как в Parallel GC: основное приложение останавливается, и запускаются несколько потоков коллектора.
▫️Старшее поколение собирается по-другому:
Большая часть графа объектов строится параллельно с основным приложением. Объекты удаляются тоже параллельно. Поэтому сборщик и называется Concurrent Mark Sweep - параллельная разметка и удаление.
⛔️ Помечен Deprecated в Java 9, потому что по всем фронтам уступает G1
G1 - Garbage First
Предыдущие сборщики делили память на 3-4 большие области — одно для старого поколения и 2-3 для нового. Суть G1 — деление памяти на 2048 регионов, которым присваивается тип - свободный, young, survivor или old.
Что это даёт:
▪️Сборщик обрабатывает только несколько регионов, а не всё поколение за раз.
▪️Можно менять количество регионов и регулировать время паузы.
▪️Приложения с большой памятью не тормозят, тк память обрабатывается по частям.
▪️Если регион однородный, можно сразу поменять его тип. Был молодой — стал свободный. Был молодой — стал выживший.
▪️Каждый регион мониторится отдельно. Так G1 выбирает перспективные регионы, куда недавно добавилось много объектов. Отсюда и название - Garbage First.
В остальном G1 похож на предыдущие сборщики:
🔹Уборка в молодом поколении останавливает потоки приложения.
🔹Общая проходит как у CMS — некоторые фазы тормозят работу приложения, некоторые работают параллельно
✅ Есть настройка длины паузы и других параметров. Гайд по тюнингу G1
✅ Работает с большой памятью
✅ Анализирует статистику сборок, хорошо работает с настройками по умолчанию.
❌ Занимает до 10% процессорного времени
G1 показывает отличные результаты в энтерпрайзе. В java 9 стал сборщиком мусора по умолчанию.
В следующей части посмотрим на новые сборщики — Shenandoah, ZGC и Epsilon GC.
#jvm
❤1
Сборщики мусора, часть 3. Java 15
В java 15 в продакшн стадию вошли 2 новых сборщика мусора — Shenandoah и ZGC.
Они подойдут для приложений с памятью до 4 ТБ, где нежелательны длинные задержки. Среднее время паузы не превышает 1 миллисекунду. За такие короткие паузы придётся платить накладными расходами — сборщики занимают до 15% процессорного времени.
❓Как они работают и как получаются такие результаты?
Как и в прошлой статье, пропустим 90% деталей и посмотрим на главное. У новых коллекторов 2 особенности:
1️⃣ Расширенные ссылки
Обычно в ссылках на объект находится только адрес памяти, где этот объект лежит. Размер поля под ссылку — 64 бита, поэтому в теории можно хранить адрес в пределах 128 ТБ.
Это много, поэтому диапазон адресов сокращён до 4 ТБ, а в свободные биты коллектор записывает нужную для себя информацию. Ссылки читаются и обновляются атомарно. Сборщику нужно меньше доп.структур и синхронизации и можно работать почти параллельно с основным приложением.
2️⃣ Load barriers
При загрузке объекта сначала читается дополнительная информация из ссылки. Поток приложения или коллектора что-нибудь делает и только потом возвращает адрес в памяти.
Что еще. Оба сборщика:
✅ Не используют поколения, работают со всеми объектами
✅ Делят память на множество регионов
✅ Группируют объекты. Дефрагментация помогает быстрее работать с памятью
Теперь о разнице между Shenandoah и ZGC:
Главное отличие в том, что конкретно записывается в ссылку, и как коллектор с этой информацией работает:
🔹Указатели в Shenandoah используют концепт brook pointers. В ссылке записан адрес объекта и, если объект был перемещён, новый адрес.
Допустим, есть объект Х, ссылки на который есть у десятка других объектов. При перемещении Х ссылки станут недействительны и должны быть обновлены. Но поскольку в brook pointers помещается два адреса, старые ссылки можно сразу не трогать. При чтении объекта поток увидит, что есть новая ссылка и сам перезапишет её.
🔹В ZGC у ссылок другой формат – colored pointers. В них коллектор записывает служебную информацию: был ли уже посещён объект, нужно ли его удалить или переместить, есть ли у него финалайзер и т.д
Ещё одно отличие — поддержка в JDK. Она зависит от производителя JDK, версии java и ОС.
🔸Shenandoah разрабатывает компания Red Hat. Сборщик доступен в OpenJDK для java 15, сделана поддержка для java 8(!!!) и 11. Oracle отказалась поддерживать Shenandoah, поэтому в OracleJDK его нет.
🔸Разработку ZGC ведёт Oracle. Коллектор включен везде: и в OracleJDK и OpenJDK. В 11 версии есть поддержка Linux, в 14 — Windows.
Epsilon GC
С java 11 доступен ещё один экспериментальный сборщик —Epsilon GC. С ним приложение работает максимально быстро, потому что сборки мусора как таковой нет. Заканчивается память — JVM завершает работу.
Где пригодится:
✅ Короткие разовые задачи
Быстро сделал — быстро завершился
✅ Тестирование и эксперименты
Без фоновой работы коллектора легче оценить производительность и занимаемую память.
#jvm
В java 15 в продакшн стадию вошли 2 новых сборщика мусора — Shenandoah и ZGC.
Они подойдут для приложений с памятью до 4 ТБ, где нежелательны длинные задержки. Среднее время паузы не превышает 1 миллисекунду. За такие короткие паузы придётся платить накладными расходами — сборщики занимают до 15% процессорного времени.
❓Как они работают и как получаются такие результаты?
Как и в прошлой статье, пропустим 90% деталей и посмотрим на главное. У новых коллекторов 2 особенности:
1️⃣ Расширенные ссылки
Обычно в ссылках на объект находится только адрес памяти, где этот объект лежит. Размер поля под ссылку — 64 бита, поэтому в теории можно хранить адрес в пределах 128 ТБ.
Это много, поэтому диапазон адресов сокращён до 4 ТБ, а в свободные биты коллектор записывает нужную для себя информацию. Ссылки читаются и обновляются атомарно. Сборщику нужно меньше доп.структур и синхронизации и можно работать почти параллельно с основным приложением.
2️⃣ Load barriers
При загрузке объекта сначала читается дополнительная информация из ссылки. Поток приложения или коллектора что-нибудь делает и только потом возвращает адрес в памяти.
Что еще. Оба сборщика:
✅ Не используют поколения, работают со всеми объектами
✅ Делят память на множество регионов
✅ Группируют объекты. Дефрагментация помогает быстрее работать с памятью
Теперь о разнице между Shenandoah и ZGC:
Главное отличие в том, что конкретно записывается в ссылку, и как коллектор с этой информацией работает:
🔹Указатели в Shenandoah используют концепт brook pointers. В ссылке записан адрес объекта и, если объект был перемещён, новый адрес.
Допустим, есть объект Х, ссылки на который есть у десятка других объектов. При перемещении Х ссылки станут недействительны и должны быть обновлены. Но поскольку в brook pointers помещается два адреса, старые ссылки можно сразу не трогать. При чтении объекта поток увидит, что есть новая ссылка и сам перезапишет её.
🔹В ZGC у ссылок другой формат – colored pointers. В них коллектор записывает служебную информацию: был ли уже посещён объект, нужно ли его удалить или переместить, есть ли у него финалайзер и т.д
Ещё одно отличие — поддержка в JDK. Она зависит от производителя JDK, версии java и ОС.
🔸Shenandoah разрабатывает компания Red Hat. Сборщик доступен в OpenJDK для java 15, сделана поддержка для java 8(!!!) и 11. Oracle отказалась поддерживать Shenandoah, поэтому в OracleJDK его нет.
🔸Разработку ZGC ведёт Oracle. Коллектор включен везде: и в OracleJDK и OpenJDK. В 11 версии есть поддержка Linux, в 14 — Windows.
Epsilon GC
С java 11 доступен ещё один экспериментальный сборщик —Epsilon GC. С ним приложение работает максимально быстро, потому что сборки мусора как таковой нет. Заканчивается память — JVM завершает работу.
Где пригодится:
✅ Короткие разовые задачи
Быстро сделал — быстро завершился
✅ Тестирование и эксперименты
Без фоновой работы коллектора легче оценить производительность и занимаемую память.
#jvm
❤1
Спасибо всем за обратную связь и лайки❤️ Поняла, что зря волновалась
По поводу применимости - сборщики действительно нужны больше для общего понимания работы JVM. Возможно, вам никогда не придётся выбирать коллектор и тюнить его.
Но! Shenandoah совместим с java 8, и многие проекты сейчас с ним экспериментируют. Вот 2 статьи (первая, вторая) с бенчмарками - при включении Shenandoah в кластерах Cassandra задержки снизились на 25-80%. Кто знает, может новые коллекторы пригодятся и на вашем проекте
По поводу применимости - сборщики действительно нужны больше для общего понимания работы JVM. Возможно, вам никогда не придётся выбирать коллектор и тюнить его.
Но! Shenandoah совместим с java 8, и многие проекты сейчас с ним экспериментируют. Вот 2 статьи (первая, вторая) с бенчмарками - при включении Shenandoah в кластерах Cassandra задержки снизились на 25-80%. Кто знает, может новые коллекторы пригодятся и на вашем проекте
❤1
Новые методы интерфейса List
Сегодня разберём вопрос с собеседований по новым методам интерфейса List. Подробно рассмотрим каждый вариант ответа, потому что методы не экзотичные и пригодятся в ежедневной работе.
В посте много кода, поэтому для удобства чтения он тут: https://teletype.in/@java_fillthegaps/QN39vs6K0
В конце небольшое лирическое отступление на тему трендов и дизайна методов.
#собеседование
Сегодня разберём вопрос с собеседований по новым методам интерфейса List. Подробно рассмотрим каждый вариант ответа, потому что методы не экзотичные и пригодятся в ежедневной работе.
В посте много кода, поэтому для удобства чтения он тут: https://teletype.in/@java_fillthegaps/QN39vs6K0
В конце небольшое лирическое отступление на тему трендов и дизайна методов.
#собеседование
❤1
Вакансии HeadHunter: Москва
Четыре месяца назад был пост про вакансии java разработчиков в Петербурге. Следим за ситуацией на рынке, и сегодня обзор вакансий для города Москва.
Вакансий в 2 раза больше — 719 против 309 в Петербурге. Интересно, что в Москве разработчиков без опыта ждут в три раза охотнее — таких вакансий 9% против 3% в Спб. BigData и noSQL упоминаются реже, и не попали ни в один топ-10.
Тройка лидеров как в Петербурге — Spring, SQL, git.
Технологии в списках находятся либо в требованиях, либо в описании проекта. Статистика собрана для разработчиков с разным уровнем опыта. Где-то не совсем технологии, например, библиотека JUnit или протокол SOAP.
Разработчики без опыта
Вакансий: 66 (9%)
🔸Spring (MVC, Security, Boot, Data)
🔸SQL (Oracle, Hibernate, Postgre)
🔸git
🔸Maven
🔸Jenkins
🔸OpenShift
🔸Docker
🔸Kafka
🔸JUnit
🔸JavaScript
Опыт от года до 3х лет
Вакансий: 303 (42%)
▪️Spring (Boot, Data, Cloud)
▪️SQL (Hibernate, Postgre, Oracle)
▪️git
▪️Maven
▪️Kafka
▪️Docker
▪️SOAP
▪️JUnit
▪️Jenkins
Опыт от 3х до 6 лет
Вакансий: 325 (45%)
🔹Spring (Boot, Data, Cloud, Security)
🔹SQL (Postgre, Hibernate)
🔹git
🔹Docker
🔹Maven
🔹Kafka
🔹JUnit
🔹Kubernetes
🔹Gradle
🔹Kotlin
🔹Jenkins
Опыт более 6 лет
Вакансий: 25 (4%)
▫️Spring (Boot. Data, Cloud)
▫️SQL (Postgre, Hibernate, mySql)
▫️git
▫️Docker
▫️Kubernetes
▫️Kafka
▫️Cloud провайдеры (AWS, GCP)
▫️Scala
▫️Jenkins
#статистика
Четыре месяца назад был пост про вакансии java разработчиков в Петербурге. Следим за ситуацией на рынке, и сегодня обзор вакансий для города Москва.
Вакансий в 2 раза больше — 719 против 309 в Петербурге. Интересно, что в Москве разработчиков без опыта ждут в три раза охотнее — таких вакансий 9% против 3% в Спб. BigData и noSQL упоминаются реже, и не попали ни в один топ-10.
Тройка лидеров как в Петербурге — Spring, SQL, git.
Технологии в списках находятся либо в требованиях, либо в описании проекта. Статистика собрана для разработчиков с разным уровнем опыта. Где-то не совсем технологии, например, библиотека JUnit или протокол SOAP.
Разработчики без опыта
Вакансий: 66 (9%)
🔸Spring (MVC, Security, Boot, Data)
🔸SQL (Oracle, Hibernate, Postgre)
🔸git
🔸Maven
🔸Jenkins
🔸OpenShift
🔸Docker
🔸Kafka
🔸JUnit
🔸JavaScript
Опыт от года до 3х лет
Вакансий: 303 (42%)
▪️Spring (Boot, Data, Cloud)
▪️SQL (Hibernate, Postgre, Oracle)
▪️git
▪️Maven
▪️Kafka
▪️Docker
▪️SOAP
▪️JUnit
▪️Jenkins
Опыт от 3х до 6 лет
Вакансий: 325 (45%)
🔹Spring (Boot, Data, Cloud, Security)
🔹SQL (Postgre, Hibernate)
🔹git
🔹Docker
🔹Maven
🔹Kafka
🔹JUnit
🔹Kubernetes
🔹Gradle
🔹Kotlin
🔹Jenkins
Опыт более 6 лет
Вакансий: 25 (4%)
▫️Spring (Boot. Data, Cloud)
▫️SQL (Postgre, Hibernate, mySql)
▫️git
▫️Docker
▫️Kubernetes
▫️Kafka
▫️Cloud провайдеры (AWS, GCP)
▫️Scala
▫️Jenkins
#статистика
👍4
Ребята, приходите на онлайн java конференцию jLove 4-5 декабря!
Участие БЕСПЛАТНОЕ, нужно только зарегистрироваться
Будут стримы для всех - от джуниоров до экспертов.
Много звёздных спикеров:
⭐️Trisha Gee - Developer Advocate в JetBrains
⭐️Josh Long - тоже Developer Advocate, только в Spring
⭐️Grace Jansen - развивает облачную архитектуру в IBM
⭐️Emily Jiang, Adam Bien - эксперты в Java EE
И другие ребята из Red Hat, Microsoft, jFrog, Oracle, Confluent и VMware.
Общение со спикерами в чате, группы по интересам, афтепати, призы и подарки.
Регистрация и остальная информация: jlove.konfy.care
Участие БЕСПЛАТНОЕ, нужно только зарегистрироваться
Будут стримы для всех - от джуниоров до экспертов.
Много звёздных спикеров:
⭐️Trisha Gee - Developer Advocate в JetBrains
⭐️Josh Long - тоже Developer Advocate, только в Spring
⭐️Grace Jansen - развивает облачную архитектуру в IBM
⭐️Emily Jiang, Adam Bien - эксперты в Java EE
И другие ребята из Red Hat, Microsoft, jFrog, Oracle, Confluent и VMware.
Общение со спикерами в чате, группы по интересам, афтепати, призы и подарки.
Регистрация и остальная информация: jlove.konfy.care
👍2
Что можно сказать про инкапсуляцию этого класса? (2/2)
Anonymous Poll
28%
Всё ок: все поля объявлены private, доступ к ним только через методы
21%
Не очень: не для всех полей есть set метод
24%
Так себе: внутреннее состояние можно поменять
28%
Плохо: можно создать несколько аккаунтов с одним ID
Что такое инкапсуляция?
Разберём популярный вопрос на собеседовании джуниор разработчика.
В 2013 году я отвечала, что инкапсуляция - это сокрытие деталей реализации. Обращаемся к объекту через методы и получаем ожидаемый результат, не погружаясь в лишние детали. Что там творится внутри метода - неважно.
Это верный ответ, но не полный.
Выделить часть кода в отдельный метод - это ещё не инкапсуляция. Такое можно провернуть в любом языке, это не делает его объекто-ориентированным.
❓Что же такое инкапсуляция?
У каждого объекта есть состояние - внутренние поля.
Иногда с ограничениями:
▪️Возраст - целое число меньше 120
▪️Имя - хотя бы одна буква
Иногда поля связаны между собой:
▪️Статус пользователя зависит от количества заказов
▪️Коэффициент ОСАГО зависит от города
Инкапсуляция - это когда состояние объекта нельзя поменять напрямую, только через методы класса. При этом важно защитить внутреннее состояние от нежелательных изменений. Это ответ на первый вопрос перед постом.
На практике решение обычно простое: сделать поля private и добавить методы get и set. Но иногда этого недостаточно.
❓Что не так с инкапсуляцией в классе Account?
Метод getOrders отдаёт список заказов List<Order>. Подразумевается, что клиент добавит ещё один заказ или обработает список.
По факту возможностей гораздо больше:
❌Удалить элементы
❌Отредактировать текущие заказы
В сложных системах не поможет комментарий "этот список только для добавления". Надёжный способ избежать ошибок - это понятный и ограниченный API.
Правильный ответ на вопрос 2:
Инкапсуляция так себе: внутреннее состояние (список заказов) не защищено.
Возможность создать два аккаунта с одним ID - вопрос дизайна и сценариев работы. С точки зрения инкапсуляции всё ок - ID нельзя поменять.
❓Как исправить ситуацию и защитить список заказов?
1️⃣ Хранить заказы отдельно
2️⃣ Поменять класс:
▫️Добавить orders модификатор final
▫️Добавить метод addOrder
▫️Метод getOrders пусть возвращает неизменяемый список
(возможны другие варианты, зависит от контекста)
#core
Разберём популярный вопрос на собеседовании джуниор разработчика.
В 2013 году я отвечала, что инкапсуляция - это сокрытие деталей реализации. Обращаемся к объекту через методы и получаем ожидаемый результат, не погружаясь в лишние детали. Что там творится внутри метода - неважно.
Это верный ответ, но не полный.
Выделить часть кода в отдельный метод - это ещё не инкапсуляция. Такое можно провернуть в любом языке, это не делает его объекто-ориентированным.
❓Что же такое инкапсуляция?
У каждого объекта есть состояние - внутренние поля.
Иногда с ограничениями:
▪️Возраст - целое число меньше 120
▪️Имя - хотя бы одна буква
Иногда поля связаны между собой:
▪️Статус пользователя зависит от количества заказов
▪️Коэффициент ОСАГО зависит от города
Инкапсуляция - это когда состояние объекта нельзя поменять напрямую, только через методы класса. При этом важно защитить внутреннее состояние от нежелательных изменений. Это ответ на первый вопрос перед постом.
На практике решение обычно простое: сделать поля private и добавить методы get и set. Но иногда этого недостаточно.
❓Что не так с инкапсуляцией в классе Account?
Метод getOrders отдаёт список заказов List<Order>. Подразумевается, что клиент добавит ещё один заказ или обработает список.
По факту возможностей гораздо больше:
❌Удалить элементы
❌Отредактировать текущие заказы
В сложных системах не поможет комментарий "этот список только для добавления". Надёжный способ избежать ошибок - это понятный и ограниченный API.
Правильный ответ на вопрос 2:
Инкапсуляция так себе: внутреннее состояние (список заказов) не защищено.
Возможность создать два аккаунта с одним ID - вопрос дизайна и сценариев работы. С точки зрения инкапсуляции всё ок - ID нельзя поменять.
❓Как исправить ситуацию и защитить список заказов?
1️⃣ Хранить заказы отдельно
2️⃣ Поменять класс:
▫️Добавить orders модификатор final
▫️Добавить метод addOrder
▫️Метод getOrders пусть возвращает неизменяемый список
(возможны другие варианты, зависит от контекста)
#core
❤1
Default методы: неудачный кейс
В чём ценность опытного разработчика? Способность видеть возможные проблемы. Интуиция, чуйка, "что-то мне здесь не нравится, давайте разберёмся".
Чтобы развить этот навык, нужно совершить много ошибок самому и изучать чужие ошибки. Прямо или косвенно, это всё идёт на пользу, и сегодня хочу поделиться одним неудачным случаем.
Default методы появились в java 8, чтобы упростить добавление методов в интерфейс. Подробный обзор можно прочитать в этом посте.
✅ Легко добавить новый метод
✅ Нет ошибок компиляции
✅ Методы при желании переопределяются
C java 8 в интерфейсе Collection появились методы по умолчанию spliterator(), stream(), parallelStream(), removeIf(…).
Какие могут быть проблемы?
❌ Реализация по умолчанию не подходит
❌ Разработчики не узнают, что добавился новый метод, который нужно переопределить. Ошибок компиляции нет, предупреждений тоже
❌ Нет тестов нового метода и интеграционных тестов
От этих проблем пострадали пользователи SynchronizedCollection из библиотеки Apache Commons.
Что произошло?
В SynchronizedCollection каждый метод синхронизирован по объекту lock:
Что делает дефолтный метод removeIf? Берёт итератор, проверяет каждый элемент на соответствие условию и удаляет, если нужно.
Переложим на методы SynchronizedCollection. Синхронизация по lock берётся, отпускается, берётся, отпускается, и так несколько раз. При большой нагрузке управление перехватит другой поток, и произойдёт коллизия. Дефолтный метод не выполнит гарантий, заданных классом.
Ошибку легко исправить - переопределить метод removeIf:
5 лет! Может новым методом никто не пользовался. Может поток данных через коллекцию был небольшим. Может никаких последствий не было. А может были, неизвестно.
Даже такая безобидная фича как "методы по умолчанию" привела к ошибке. Мы можем вынести из неё пару best practices:
▫️Если интерфейс используется только внутри системы, достаточно написать тесты для всех реализаций.
▫️Для общедоступных библиотек по возможности избегать методов по умолчанию.
#core
В чём ценность опытного разработчика? Способность видеть возможные проблемы. Интуиция, чуйка, "что-то мне здесь не нравится, давайте разберёмся".
Чтобы развить этот навык, нужно совершить много ошибок самому и изучать чужие ошибки. Прямо или косвенно, это всё идёт на пользу, и сегодня хочу поделиться одним неудачным случаем.
Default методы появились в java 8, чтобы упростить добавление методов в интерфейс. Подробный обзор можно прочитать в этом посте.
✅ Легко добавить новый метод
✅ Нет ошибок компиляции
✅ Методы при желании переопределяются
C java 8 в интерфейсе Collection появились методы по умолчанию spliterator(), stream(), parallelStream(), removeIf(…).
Какие могут быть проблемы?
❌ Реализация по умолчанию не подходит
❌ Разработчики не узнают, что добавился новый метод, который нужно переопределить. Ошибок компиляции нет, предупреждений тоже
❌ Нет тестов нового метода и интеграционных тестов
От этих проблем пострадали пользователи SynchronizedCollection из библиотеки Apache Commons.
Что произошло?
В SynchronizedCollection каждый метод синхронизирован по объекту lock:
synchronized (lock) {
return coll.remove(object);
}
Изменения последовательны, данные в безопасности и всегда актуальны. Что делает дефолтный метод removeIf? Берёт итератор, проверяет каждый элемент на соответствие условию и удаляет, если нужно.
Переложим на методы SynchronizedCollection. Синхронизация по lock берётся, отпускается, берётся, отпускается, и так несколько раз. При большой нагрузке управление перехватит другой поток, и произойдёт коллизия. Дефолтный метод не выполнит гарантий, заданных классом.
Ошибку легко исправить - переопределить метод removeIf:
synchronized (lock) {
return coll.removeIf(filter);
}
Проблема в том, что такие ошибки сложно обнаружить. Default метод появился в марте 2014, а класс обновили в июле 2019. 5 лет пользователи SynchronizedCollection пользовались ненадёжным методом.5 лет! Может новым методом никто не пользовался. Может поток данных через коллекцию был небольшим. Может никаких последствий не было. А может были, неизвестно.
Даже такая безобидная фича как "методы по умолчанию" привела к ошибке. Мы можем вынести из неё пару best practices:
▫️Если интерфейс используется только внутри системы, достаточно написать тесты для всех реализаций.
▫️Для общедоступных библиотек по возможности избегать методов по умолчанию.
#core
❤2
Пробовали когда-нибудь парное программирование?
Anonymous Poll
5%
Да, часто практикую
24%
Да, один-два раза
41%
Нет, но интересно попробовать
30%
Нет, только традиционный подход
👍2
IDEA: Code with me
Парное программирование - agile практика, когда два человека сидят за одним компьютером и работают над задачей. Один пишет код, другой - наблюдает.
Если партнёры хорошо сработаются, то код получится проще, а ошибок будет меньше.
Intellij IDEA недавно выпустила классный плагин Code with me, и теперь парным программированием можно заняться и на удалёнке.
Найти его легко: File → Settings → Plugins → Marketplace → Code with me
Новая плашка появится рядом с иконками Run/Debug. Можно отправить ссылку коллеге и вместе работать над задачей👯
#idea
Парное программирование - agile практика, когда два человека сидят за одним компьютером и работают над задачей. Один пишет код, другой - наблюдает.
Если партнёры хорошо сработаются, то код получится проще, а ошибок будет меньше.
Intellij IDEA недавно выпустила классный плагин Code with me, и теперь парным программированием можно заняться и на удалёнке.
Найти его легко: File → Settings → Plugins → Marketplace → Code with me
Новая плашка появится рядом с иконками Run/Debug. Можно отправить ссылку коллеге и вместе работать над задачей👯
#idea
По статистике 64% приложений сидят на java 8, а самая популярная фича java 8 - это Stream API.
Самая запутанная часть Stream API - коллекторы, о них я написала лонгрид в 3 частях.
Часть 1: обзор и простые коллекторы
Часть 2: сложные коллекторы
Часть 3: особенности дизайна
Рассмотрим почти все, что есть в JDK. Без внимания останутся collectingAndThen и teeing(Java 12). Не нашла ни одного кейса, где они полезны🤷
Самая запутанная часть Stream API - коллекторы, о них я написала лонгрид в 3 частях.
Часть 1: обзор и простые коллекторы
Часть 2: сложные коллекторы
Часть 3: особенности дизайна
Рассмотрим почти все, что есть в JDK. Без внимания останутся collectingAndThen и teeing(Java 12). Не нашла ни одного кейса, где они полезны🤷
Коллекторы Stream API, часть 1: простые методы
В первой части повторим основы - из чего состоит стрим и что такое коллектор. Каждый код со Stream API состоит из 3х частей:
1️⃣ Получение стрима
2️⃣ Преобразования
3️⃣ Терминальная операция
1️⃣
Коллекторы - статические методы класса Collectors, которые возвращают аргумент для метода collect. Я буду опускать основной класс и вместо Collectors.counting() будут писать counting(). Чтобы было короче.
Чаще всего элементы стрима собирают в обычную коллекцию:
▪️toCollection, toList, toSet
▪️toUnmodifiableSet, toUnmodifiableList
▫️counting
▫️averagingToInt / Long / Double
▫️joining
▫️maxBy, minBy
▫️reducing
▫️summingInt / Long / Double
▫️summarizingInt / Long / Double
Интересны здесь только два метода:
🔸 joining
Соединяет элементы в одну строку:
Возвращает объект IntSummaryStatistics, который содержит минимум, максимум, среднее, количество элементов и их сумму.
Остальные методы сами по себе бесполезны, так как есть простые аналоги:
Они нужны в коллекторах groupingBy и partitioningBy, про них подробно поговорим завтра.
#core
В первой части повторим основы - из чего состоит стрим и что такое коллектор. Каждый код со Stream API состоит из 3х частей:
1️⃣ Получение стрима
2️⃣ Преобразования
3️⃣ Терминальная операция
1️⃣
list.stream()
2️⃣ .filter(e -> e != 3)
3️⃣ .count();
Терминальная операция collect собирает элементы стрима в другую структуру данных. Все подробности передаются через аргумент:collect(Collector collector) Коллекторы - статические методы класса Collectors, которые возвращают аргумент для метода collect. Я буду опускать основной класс и вместо Collectors.counting() будут писать counting(). Чтобы было короче.
Чаще всего элементы стрима собирают в обычную коллекцию:
▪️toCollection, toList, toSet
▪️toUnmodifiableSet, toUnmodifiableList
Set res=students.stream()Ещё одна группа - коллекторы, которые возвращают одно значение:
.filter(…).collect(toSet())
▫️counting
▫️averagingToInt / Long / Double
▫️joining
▫️maxBy, minBy
▫️reducing
▫️summingInt / Long / Double
▫️summarizingInt / Long / Double
Интересны здесь только два метода:
🔸 joining
Соединяет элементы в одну строку:
chars.stream().collect(joining("-"));
// ['a','b','c'] → a-b-c
🔸summarizingIntВозвращает объект IntSummaryStatistics, который содержит минимум, максимум, среднее, количество элементов и их сумму.
Остальные методы сами по себе бесполезны, так как есть простые аналоги:
list.stream().collect(counting())Коллекторы mapping, flatMapping и filtering применяют функцию к элементам перед отправкой в другой коллектор.
// аналог
list.stream().count()
Set<Long> ids = …Использовать их напрямую тоже смысла нет. Проще применить к элементам map, flatmap или filter, а потом собрать результаты:
collect(mapping(Student::id, toSet())
map(Student::id).collect(toSet())❓Зачем нужны эти методы?
Они нужны в коллекторах groupingBy и partitioningBy, про них подробно поговорим завтра.
#core
👍5❤1