Java: fill the gaps

Description
Привет! Меня зовут Диана, и я занимаюсь разработкой с 2013. Здесь пишу просто и понятно про джава бэк

🔥Тот самый курс по многопочке🔥
https://fillthegaps.ru/mt

Комплименты, вопросы, предложения: @utki_letyat
Advertising
We recommend to visit
HAYZON
HAYZON
5,992,507 @hayzonn

لا اله الا الله محمد رسول الله

👤 𝐅𝐨𝐮𝐧𝐝𝐞𝐫: @Tg_Syprion
🗓 ᴀᴅᴠᴇʀᴛɪsɪɴɢ: @SEO_Fam
Мои каналы: @mazzafam

Last updated 3 weeks, 6 days ago

Architec.Ton is a ecosystem on the TON chain with non-custodial wallet, swap, apps catalog and launchpad.

Main app: @architec_ton_bot
Our Chat: @architec_ton
EU Channel: @architecton_eu
Twitter: x.com/architec_ton
Support: @architecton_support

Last updated 3 weeks ago

Канал для поиска исполнителей для разных задач и организации мини конкурсов

Last updated 1 month, 1 week ago

2 months, 2 weeks ago

GraalVM, часть 2: native image

Продолжаем вникать в GraalVM. Сегодня поговорим о самой интересной его части — native image билдер.

Он компилирует java код и все нужные классы сразу в бинарный файл. Нет промежуточного этапа в виде байткода, а значит для запуска не нужна JVM.

Джава код запускается без JVM🤯

Бинарник собирается под конкретную платформу, поэтому код больше не write once, run anywhere! Одна из киллер фич java отправляется на антресоль.

Что получаем от такого богохульства:
Быстрый старт, тк все классы уже загружены
😐 Немного усложняется CI и тестирование
😡 Нужно адаптировать код

Например, статические блоки по классике выполняются при загрузке класса. Если класс не загружается, блок не выполнится.

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

😡 Если приложение использует библиотеки, они тоже должны предоставлять нейтив вариант
😡 Долгая компиляция

Сама с native images не сталкивалась, но видела доклад, как их используют в одном из проектов Сбера. Так что вещь рабочая, хоть и специфичная.

Spring native image🍃****

Интересный проект по адаптации Spring под нейтив имедж. Обычные спринг приложения стартуют несколько минут. Ожидается, что native вариант запустится за несколько секунд!

Сложность в том, что в спринге большая часть магии происходит на старте. Активно используется рефлекшн и создаются прокси-классы. Чтобы адаптировать Spring под native, надо переписать огромную часть кода.

Плюс не все библиотеки легко адаптируются под нэйтив. Например, сейчас нет поддержки Mockito. А куда мы без него?

Поэтому сохраняется интрига — непонятно, что в итоге получится, и стоит ли оно того. Но следить за этим очень интересно🥰

Подведем итог

GraalVM — проект, объединяющий несколько направлений:
🌸 JIT компилятор. Уже сейчас можно запустить на OpenJDK и OracleJDK и чуточку ускорить приложение
🌸 Виртуальная машина GraalVM
🌸 Сборщик native image. Интересен и сам подход, и проекты, которые его используют, например, Spring native image

Есть в GraalVM и другие штуки, например, мультиязычный рантайм. Но они вряд ли пригодятся большинству из нас, поэтому не будем о них😊

2 months, 2 weeks ago
2 months, 3 weeks ago

GraalVM, часть 1

Последние годы на конференциях встречаются доклады про GraalVM. У них мало просмотров, тк есть мнение, что Грааль — что-то экспериментальное и далёкое от коммерческой разработки.

Но нет!

GraalVM — проект, который объединяет в себе целую смесь идей и технологий. В этом посте расскажу о самом близком к практике и понятном компоненте — JIT-компиляторе Graal и зачем он нужен.

Начнем с основ:
✍️ Программист пишет java код
✍️ Компилятор превращает его в байт-код
✍️ JIT-компилятор внутри JVM переводит байт-код в системные вызовы для конкретной ОС

JVM использует два типа компиляторов: С1 и С2:
🐍 С1 (client) — для десктопа, браузера и приложений на слабом железе. Быстрый старт, низкое потребления памяти, но мало оптимизаций
🐊 С2 (server) — для больших и мощных серверов. Алгоритмы сложнее, памяти нужно больше, зато на выходе более оптимизированный нативный код

Разделение было актуально 20 лет назад. Сейчас железо мощнее и дешевле, поэтому с java 8 работает смешанный тип (tiered compilation) с участием обоих компиляторов.

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

Тот случай, когда проще написать заново:)

В Java 9 работа с JIT-компилятором скрылась за отдельным интерфейсом JVMCI — JVM Compiler Interface. Теперь можно собрать JVM с другим компилятором. Например, с новым и свежим JIT компилятором Graal.

В OpenJDK включается флажками
\-XX:+UnlockExperimentalVMOptions \-XX:+UseJVMCICompiler

Работает пока только для Linux, иногда показывает небольшой прирост скорости. Так что имеет смысл попробовать!

В GraalVM есть ещё одно интересное направление, и о нем расскажу в следующем посте🔥

5 months ago

Костыль в JDK и сортировка списков

Вести абстрактные разговоры о разработке легко и приятно. Можно два часа рассуждать, что такое хорошее API, но гораздо полезнее обсудить конкретные примеры. Сегодня разберём метод сортировки.

Если показать вопрос перед постом питонисту, он однозначно выберет list.sort(). Хотя бы потому что в питоне есть такой метод.

Класс Integer реализует интерфейс Comparable, сортировка чисел — базовая функциональность любого языка программирования. Так что метод sort() максимально логичен.

Однако в интерфейсе List нет такого метода, только
void sort(Comparator<?super Е> c) {…}

Для элементарной операции сортировки чисел приходится писать
list.sort(Comparator.naturalOrder())

Код с Comparator.naturalOrder() похож на какой-то костыль. Под капотом не происходит ничего особенного, реализация компаратора очень простая:
(с1, с2) \-> c1.compareTo(c2)

Так зачем писать так сложно? Почему в интерфейсе List нет метода sort()?

Сейчас расскажу:)

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

C начала 2000-х в JDK есть метод Collections.sort(List). Статический метод, который меняет внутреннее состояние аргумента. Сейчас это порицается, но в те времена было норм.

В больших компаниях классы JDK часто расширяли удобными методами, в том числе сортировкой в функциональном стиле:
CustomList sorted = list.sort();

Спустя много лет стало понятно, что экземплярные методы сортировки — это классно, и надо добавить такой метод в JDK. Чтобы текущие реализации списков не сломались, это должен быть дефолтный метод в интерфейсе List.

Но есть проблема. Допустим, на проекте есть такой класс:
public class CustomList implements List { public CustomList sort() {…} }

Допустим, в java 8 в интерфейс List добавили бы метод
default void sort() {…}

Старый метод не может переопределить дефолтный. тк возвращаемые значения не совместимы. Поэтому проекты, которые определили свой функциональный sort в начале 2000-х, перестанут компилироваться. Пользователи будут недовольны?

Многие проекты полагаются на свой sort, поэтому разработчики JDK не стали добавлять его в интерфейс. Метод sort(Comparator) использовался редко, поэтому теперь он с нами.

У Stream API нет проблем с совместимостью, так что для стримов есть прекрасный метод sorted(). Для коллекций метод sorted() есть в Kotlin?
(обратите внимание на суффикс -ed, всё по правилам функционального подхода)

Ответ на вопрос перед постом: отсортировать список можно так:
***✅*** list.sort(Comparator.naturalOrder()); ***✅*** list = list.stream().sorted().toList();

Если вам понравился list.sort(), значит у вас хороший вкус на API. К сожалению, у java свои загоны, поэтому этого метода в JDK нет.

5 months ago
5 months, 1 week ago

REST API— неоднозначная тема, по которой часто много вопросов и споров. В этом посте кратко расскажу, что такое REST API и как он связан с REST. И самое интересное — покажу принципы REST API на реальных примерах.

Начнём сначала.

REST — это набор архитектурных принципов, которые описал Roy Fielding в диссертации 2000 года. Один из тезисов гласит, что взаимодействие между системами должно крутиться вокруг понятия ресурса.

REST API, в свою очередь, это набор рекомендаций для API: как составить URL-ы, что они принимают и возвращают. От REST здесь берётся только понятие ресурса. Остальное — частные интерпретации, в оригинальном документе ничего этого нет.

Под REST API обычно понимают следующий набор правил:

1️⃣ В основе пути — существительное во множественном числе

*❌ https://www.youtube.com/watch?v=123
* https://rutube.ru/video/123

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

2️⃣ Иерархия ресурсов отражается в URL

Например, в магазине одежды есть раздел с футболками. Как это отразить в API:
*❌ https://www.lamoda.ru/c/2478/clothes-futbolki/
* https://www.sportmaster.ru/catalog/zhenskaya_odezhda/futbolki/

3️⃣ Желаемые действия с ресурсом определяются через HTTP методы

Искусственный пример:
▫️ GET /users — вернуть список всех пользователей
▫️ GET /users/5 — получить пользователя с id=5
▫️ POST /users — добавить пользователя
▫️ PUT /users/5 — обновить пользователя с id=5 целиком
▫️ PATCH /users/5 — обновить часть полей у пользователя с id=5

Найти идеальный реальный пример у меня не получилось, но очень близок оказался HeadHunter API по работе с резюме. Там всё по канону, но для редактирования они используют PUT.

4️⃣ Вызов методов GET, DELETE, PUT, PATCH должен быть идемпотентным

Чтобы без проблем вызвать метод повторно, если что-то пошло не так

5️⃣ Методы PUT, POST and PATCH возвращают новый/обновлённый объект

6️⃣ Дополнительные параметры для метода GET указываются через ?, а тело метода остаётся пустым

GET /resumes?text=java&age_from=18 – поиск совершеннолетних кандидатов, в резюме которых встречается "java"

7️⃣ Информация для POST, PUT, PATCH запросов передаётся в теле метода

8️⃣ В качестве ответа возвращается соответствующий HTTP код
▫️ 1хх: информационные сообщения, чаще всего служебные. Для бизнес-логики не используются
▫️ 2xx: всё супер
▫️ 3xx: redirect
▫️ 4xx: ошибка на стороне клиента
▫️ 5xx: ошибка на стороне сервера

Какие плюсы у REST API?

Плюс на самом деле только один — в таком API проще разобраться. У Stepik REST API нет документации, но и так понятно, что GET /api/courses возвращает список курсов.

Как видно по примерам выше, некоторые компании придерживаются подобных правил, некоторые — нет. Rutube более REST API, чем Youtube, но для успеха продукта этого явно недостаточно?

7 months, 3 weeks ago

Как считается хэшкод по умолчанию?

На собеседованиях часто обсуждают методы equals и hashcode. За что отвечают, как соотносятся между собой, когда переопределять, а когда не стоит.

Если хочется посмотреть, как думает человек за пределами стандартного ответа, возможен такой диалог:

— Как считается хэшкод по умолчанию?
— Это адрес объекта в памяти
— А почему так?
— Адрес каждого объекта уникален, то что надо для хэшкода
— Сборщик мусора перемещает объекты внутри памяти. Как это влияет на значения хэшей?
?**

Тут можно предположить, что хэшкод считается один раз и приписывается к самому объекту. Это будет логичная мысль.

А вот вычисление хэша на основе адреса в памяти — популярный миф. В этом посте разберём, как на самом считается хэшкод под умолчанию.

В разных JVM реализации могут отличаться. Рассмотрим исходный код hashcode в OpenJDK. Там 6(!) стратегий вычисления хэшкода. Стратегия задаётся опциями VM:

\-XX:+UnlockExperimentalVMOptions \-XX:hashCode={число}

При первом вызове хэш сохраняется внутри объекта и не меняется. Теперь к стратегиям:

*?-XX:hashCode=0*

Случайное число по алгоритму Lehmer RNG. Генератор один на всех, поэтому работает медленно

*?-XX:hashCode=2*

Чемпион по скорости, всегда возвращает 1:

java.lang.Object@1

Используется как отправная точка для тестов остальных стратегий

*?-XX:hashCode=3*

Обычная возрастающая последовательность:

java.lang.Object@a4 java.lang.Object@a5 java.lang.Object@a6

*?-XX:hashCode=4*
Текущий адрес в памяти. Популярный, но неправильный ответ на собеседованиях. Отчасти в этом виновата спецификация: там адрес приводится как пример реализации. Работает быстро, но не даёт равномерного распределения и должного уровня уникальности

*?-XX:hashCode=1*

Адрес объекта в памяти и немного манипуляций с битами

? Стратегия по умолчанию

Случайное число по алгоритму Xorshift RNG. Следующее значение вычисляется на основе предыдущего. Значения равномерно распределены. Работает быстро, тк у каждого потока свой генератор, и синхронизации между потоками нет

Рейтинг стратегий по скорости:
? Вернуть единицу: 184 операций за микросекунду
? Вариант по умолчанию: 176 оп/мск
? Адрес в памяти-1: 160 оп/мск
▪️ Растущая последовательность: 14 оп/мск
▪️ Случайное число и глобальная переменная: 10 оп/мск

Интересно, что до java 8 самая медленная опция была вариантом по умолчанию.

Итого

Реализация хэшкода зависит от JVM и VM-флажков
В OpenJDK 6 стратегий вычисления хэшкода. По умолчанию используется генератор случайных чисел в рамках одного потока
Расчёт на основе адреса памяти не очень хорош по итоговым характеристикам
Общие переменные в методах снижают производительность при интенсивном использовании. Яркие примеры — стратегии хэшкода с общим генератором и последовательностью

7 months, 3 weeks ago
7 months, 4 weeks ago

*?‍?Чему поучиться*

Посты это прекрасный, но очень сжатый формат. Для тех, кто хочет большего, у меня есть ещё два курса:

*1️⃣*** Основы многопоточности

Бесплатный!

Его задача — пройтись по базовым темам многопоточки и заполнить пробелы, если они есть:
▫️ Класс Thread
▫️ Экзекьюторы
▫️ Основные проблемы в многопоточной среде
▫️ Модификатор volatile
▫️ Ключевое слово synchronized

Темы не раскрыты даже на 50%, многие вещи сильно упрощены. Но чтобы понять базу и пройти несложные собеседования — самое то.

*2️⃣*** Многопоточное программирование на Java

Самый полный и практичный курс по java.util.concurrent и смежным темам?

Разбираемся, как писать эффективный и быстрый код и готовимся к собеседованиям. Изучаем best practices и популярные ошибки.

Самая мощная часть — это практика:
Решаем типичные энтерпрайзные задачи
Анализируем многопоточный код Spring, Kafka, Hadoop и других популярных фреймворков — смотрим интересные приёмы и ищем ошибки
Сравниваем разные решения и оцениваем производительность

Такого вы не найдёте нигде. Курс не пересказывает документацию и Concurrency in practice. Он о том, как применять многопоточку в реальной жизни.

Курс нацелен на самостоятельное прохождение, для всех заданий есть подсказки, инструкции для самопроверки и разбор важных нюансов. Я вела курс с обратной связью 3 года и прекрасно понимаю, где возникают сложности.

Если что-то совсем непонятно, можно у меня спросить:)

Что ещё:
▫️ Прохождение занимает 2-3 месяца
▫️ Доступ сразу после оплаты
▫️ Есть рассрочка и оплата за счёт компании
▫️ Можно оформить налоговый вычет и вернуть в следующем году 13% стоимости

Почитать программу, отзывы и записаться → https://fillthegaps.ru/mt

9 months, 2 weeks ago

Чего ждать от Java ближайшие 10 лет?

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

*⭐️ Project Loom*

Цель: добавить легковесные(виртуальные) потоки

Самая заметная фича со времён Stream API. Большинство проектов получат огромный буст от внедрения виртуальных потоков. Что важно — с минимальными изменениями в коде.

В Java 21 вышло базовое апи по работе с виртуальными потоками. Предстоит ещё много работы внутри JVM и в рамках языка, чтобы удобно управлять тысячами задач.
*⭐️ ZGC / Shenandoah*

Цель: сборщик мусора с минимальными паузами

Сборщики чуть отличаются по реализации, но задача одна — обеспечить минимум простоя во время сборки мусора. Разумеется, не бесплатно. Паузы уменьшаются, но увеличивается расход памяти и снижается пропускная способность.

Для большинства проектов это не актуально. Сборщик по умолчанию G1 отлично работает и становится лучше с каждым релизом.

*⭐️ Project Panama*

Цель: упростить работу с native кодом и памятью за пределами JVM

Проект делится на 2 направления:

? Новый вариант JNI

Нужен для работы с библиотеками, которые не написаны на Java, и вряд ли когда-нибудь будут: работа с графикой, манипуляции с ОС, сетью и тд. Текущий JNI очень старый, работает медленно и не безопасен. Поэтому пишут новый:)

? Работа с памятью за пределами JVM

Нужна проектам, которые хотят управлять памятью без посредничества Java. Самим делать сборку мусора, сжимать и раскладывать данные по определённым структурам.

*⭐️ Project Amber*

Цель: упростить язык, добавить новые конструкции

Самые "народные" фичи, которые часто попадают в обзоры и статьи: var, текстовые блоки, records, pattern matching, sealed классы, string templates и так далее.

Что-то получается хорошо, что-то не очень. Где-то много пафосных разговоров про data-oriented programming. Есть странные фичи, вроде упрощения написания Hello world.

*⭐️ Project Leyden*

Цель: ускорить время старта Java программ

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

*⭐️ Project Valhalla*

Цель: оптимизировать работу с данными

Здесь так же два направления:

? Создать value types — объект с полями и методами, работа с которым идёт как с примитивом:
Передаётся по значению
Компактно лежит в памяти
Не может быть null

? Создать общую схему работы с примитивами, объектами и value types, избавить разработчика от мыслей про boxing/unboxing

* А когда будет готово?*

Плохая новость — реализации всех проектов растягиваются на десятки лет.

10 лет — не преувеличение. Лямбда-выражения в java обсуждались с 2004 года, а увидели свет только в 2014.

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

На java пишут большие системы, которые работают десятки лет. Поэтому основательный подход абсолютно оправдан?

We recommend to visit
HAYZON
HAYZON
5,992,507 @hayzonn

لا اله الا الله محمد رسول الله

👤 𝐅𝐨𝐮𝐧𝐝𝐞𝐫: @Tg_Syprion
🗓 ᴀᴅᴠᴇʀᴛɪsɪɴɢ: @SEO_Fam
Мои каналы: @mazzafam

Last updated 3 weeks, 6 days ago

Architec.Ton is a ecosystem on the TON chain with non-custodial wallet, swap, apps catalog and launchpad.

Main app: @architec_ton_bot
Our Chat: @architec_ton
EU Channel: @architecton_eu
Twitter: x.com/architec_ton
Support: @architecton_support

Last updated 3 weeks ago

Канал для поиска исполнителей для разных задач и организации мини конкурсов

Last updated 1 month, 1 week ago