TGViewer
Channel Public Channel
Библиотека джависта | Java, Spring, Maven, Hibernate

Библиотека джависта | Java, Spring, Maven, Hibernate

@javaproglib

Все самое полезное для Java-разработчика в одном канале.

Учиться у нас: clc.to/AATM8w

Для обратной связи: @proglibrary_feeedback_bot

По рекламе: @tproger_sales_bot

РКН: https://gosuslugi.ru/snet/67a5bbda1b17b35b6c1a55c4
Subscribers
22K
Photos
2.5K
Videos
57
Links
3.7K

Showing posts older than #7811 · Back to latest

Older Posts 20 shown
Post #7810 2.13K
🔍 Просто о сложном: что такое Garbage Collector (GC)?

Garbage Collector (GC) в Java — это механизм автоматического управления памятью, который отвечает за очистку памяти от объектов, которые больше не используются в программе. Вместо того, чтобы разработчик вручную освобождал память, как в некоторых других языках программирования, Java использует сборщик мусора, который делает это автоматически.

🔵 Как работает GC?

Когда вы создаёте объект в Java, он занимает место в куче (heap) — области памяти, предназначенной для динамического распределения. Однако по мере работы программы некоторые объекты становятся ненужными, и их можно удалить, чтобы освободить память для других задач. Это и есть основная задача GC — найти объекты, которые больше не используются, и освободить память.

🔵 Основные этапы работы GC

1. Маркировка. На первом этапе система анализирует объекты в куче и помечает те, на которые существуют ссылки, то есть которые всё ещё могут быть использованы в программе. Эти объекты называют живыми.

2. Сборка мусора. После маркировки GC удаляет объекты, которые не были помечены как «живые». Эти объекты больше не используются в программе и могут быть безопасно удалены, а занимаемое ими пространство освобождается.

3. Компактизация (Compaction). Иногда после удаления объектов в куче остаются фрагменты пустой памяти. В этом случае GC может перемещать объекты, чтобы устранить фрагментацию и сделать память более сплошной. Это улучшает использование доступных ресурсов.

🔵 Типы Garbage Collector в Java

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

— Serial GC: простой сборщик, использующий один поток для работы с памятью. Это может быть полезно в простых приложениях, но вызывает большие паузы в работе программы, что не подходит для сложных многозадачных приложений.

— Parallel GC: этот сборщик использует несколько потоков для работы, что ускоряет процесс очистки. Он подходит для многозадачных приложений и приложений с большими объемами данных, где важно минимизировать время пауз.

— CMS (Concurrent Mark-Sweep): сборщик мусора, который работает параллельно с основной программой, минимизируя паузы. Он использует несколько шагов для маркировки и уборки мусора, чтобы не блокировать выполнение приложения на долгое время.

— G1 (Garbage First): один из самых современных сборщиков мусора. Он фокусируется на минимизации времени пауз и дает разработчикам больше контроля над процессом. G1 отлично подходит для больших приложений с высоким уровнем взаимодействия.

🔵 Паузы и их влияние на производительность

Одним из главных аспектов работы GC является Stop-the-World пауза, когда приложение временно приостанавливается, чтобы сборщик мусора очистил память. Хотя паузы в большинстве случаев довольно короткие, они могут заметно повлиять на производительность, особенно в приложениях с высокими требованиями к времени отклика.

🔵 Как улучшить производительность при работе с GC

— Оптимизация размера кучи. Размер кучи можно настроить в зависимости от объема данных, с которым работает ваше приложение. Неправильно выбранный размер может привести к слишком частым или слишком редким сборкам мусора.

— Использование правильного сборщика. Выбор сборщика мусора зависит от особенностей вашего приложения. Например, для приложений с требованием низкой задержки лучше использовать G1 или CMS.

— Профилирование. Используйте инструменты профилирования, чтобы отслеживать, как работает GC в вашем приложении. Это поможет выявить проблемы и оптимизировать использование памяти.

🔵 Когда стоит задуматься о Garbage Collector

— Когда ваше приложение работает с большим количеством объектов, и необходимо следить за производительностью.
— Если заметны задержки или паузы, вызванные работой GC, и нужно оптимизировать работу с памятью.
— В сложных многозадачных или распределённых приложениях, где важно, чтобы GC не блокировал выполнение других задач.

══════ Навигация ══════
Вакансии • Задачи • Собесы

🐸 Библиотека джависта

#CoreJava
  • ❤ 8
  • 👍 3
  • 🌚 2
  • 🥰 1
  • 🥱 1
Post #7809 2.08K
🔴 Java-дайджест: что происходит в экосистеме прямо сейчас:

➡️ JDK 27 выходит в сентябре. Релиз запланирован на 15 сентября, продолжаются early-access сборки. Среди заметных нововведений — JEP 523 (G1 станет GC по умолчанию во всех средах) и JEP 527 (гибридный постквантовый обмен ключами для TLS 1.3).

➡️ Project Valhalla становится ближе. JEP 401 (Value Objects) получил статус Proposed to Target для JDK 28. Это первый шаг к появлению value objects в виде preview-функции. Разбор — в сегодняшнем #CoreJava.

➡️ JSON в стандартной библиотеке. JEP 540 (Simple JSON API) предлагает простой API для чтения и записи JSON без сторонних библиотек. Пока это инкубатор, но направление выглядит многообещающим.

➡️ Security. Июльский Critical Patch Update уже вышел. Если инфраструктура ещё не обновлена, стоит проверить, что используется актуальная сборка JDK с последними исправлениями безопасности.

➡️ Spring Boot 3.5 завершает OSS-жизненный цикл. Последний открытый релиз ветки 3.5.x уже опубликован. Для получения дальнейших OSS-обновлений рекомендуется переходить на Spring Boot 4.x либо использовать коммерческую поддержку.

══════ Навигация ══════
Вакансии • Задачи • Собесы

🐸 Библиотека джависта

#News
  • ❤ 7
  • 😢 2
  • 🌚 2
  • 🔥 1
Post #7807 2.24K
☕️ Настройка Testcontainers + PostgreSQL

Надоели моки репозиториев, которые не ловят реальные SQL-баги?
Настраиваем Testcontainers, запускаем настоящий PostgreSQL прямо в тестах, без внешних зависимостей.

⚙️ Шаг 1 — Зависимости (Maven)

<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.19.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>1.19.7</version>
<scope>test</scope>
</dependency>


> Для Gradle: testImplementation "org.testcontainers:postgresql:1.19.7"

🐳 Шаг 2 — Базовый тест

@SpringBootTest
@Testcontainers
class UserRepositoryTest {

@Container
static PostgreSQLContainer<?> postgres =
new PostgreSQLContainer<>("postgres:16-alpine");

@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}

@Autowired
UserRepository userRepository;

@Test
void shouldSaveAndFindUser() {
var user = new User("alice@example.com");
userRepository.save(user);

var found = userRepository.findByEmail("alice@example.com");
assertThat(found).isPresent();
}
}


Всё. Spring подхватит datasource-проперти через @DynamicPropertySource — Liquibase/Flyway накатятся сами.

⚡️ Шаг 3 — Ускоряем: переиспользуем контейнер

По умолчанию контейнер поднимается на каждый тест-класс.
Чтобы один инстанс жил на весь прогон — выносим в абстрактный класс:

@SpringBootTest
@Testcontainers
public abstract class BaseIntegrationTest {

@Container
static final PostgreSQLContainer<?> POSTGRES =
new PostgreSQLContainer<>("postgres:16-alpine")
.withReuse(true); // ← ключевая строка

@DynamicPropertySource
static void props(DynamicPropertyRegistry r) {
r.add("spring.datasource.url", POSTGRES::getJdbcUrl);
r.add("spring.datasource.username", POSTGRES::getUsername);
r.add("spring.datasource.password", POSTGRES::getPassword);
}
}


Наследуй в каждом интеграционном тесте — контейнер поднимется один раз.

🔍 Шаг 4 — Отладка: смотрим логи контейнера

POSTGRES.followOutput(new Slf4jLogConsumer(
LoggerFactory.getLogger("postgres-container")
));


Добавь до старта контейнера и все PostgreSQL логи пойдут в твой аппендер.

🔖 Сохраняй пост для следующего проекта.

══════ Навигация ══════
Вакансии • Задачи • Собесы

🐸 Библиотека джависта

#Enterprise
  • 👍 12
  • ❤ 2
  • 🔥 2
  • 🤔 1
Post #7805 1.95K

Forwarded from Proglib.academy | IT-курсы

😱 Знакомо? Лимит уже закончился, а задача всё ещё не готова. Часть токенов могла уйти на повторное чтение файлов, лишний контекст и неудачные попытки.

⚡️ Этому посвящён отдельный блок курса «ИИ для разработчиков». Вы разберёте расходы на собственных проектах, сравните подходы и найдёте места, где агент выполняет лишнюю работу.

В итоге станет понятнее, сколько ресурсов выделять на запуск, когда его останавливать и в какой момент лучше изменить подход 🔍


До 31 июля курс можно купить со скидкой, а все материалы останутся в бессрочном доступе.

🔗 Узнать подробности о курсе

🏃‍♀️ Proglib Academy
  • 🥱 2
  • ❤ 1
Post #7804 2.24K
Куда на самом деле уходят токены во время агентного кодинга? ⚡️
Post #7803 2.75K
🧹 Git-команда, которая спасёт ваш репозиторий от мусора

Проблема: вы удалили ветки, сделали git reset, отменили мёржи, но репозиторий почему-то весит всё больше. git clone на новом месте занимает вечность. Куда уходит место?

Дело в том, что Git — барахольщик. Он хранит все объекты: старые блобы, недостижимые коммиты, забытые stash'ы. Даже то, что вам давно не нужно.

💡 Решение: git gc и его старший брат git gc --aggressive

Рассмотрим все все возможности git gc.

1️⃣ Сколько мусора накопилось

git count-objects -vH

Обратите внимание на size-pack — это реальный вес вашего репо.

2️⃣ Самые тяжёлые объекты в истории

git rev-list --objects --all \
| git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
| awk '/^blob/ {print $3, $4}' \
| sort -rn \
| head -10

Часто находятся артефакты сборки, дампы БД или случайно закоммиченные .jar на 200 МБ 😬

3️⃣ Запустите агрессивную сборку мусора

git gc --aggressive --prune=now

--aggressive заставляет Git перепаковать объекты с нуля, а --prune=now удаляет недостижимые объекты немедленно, не дожидаясь дефолтных двух недель.

4️⃣ Сравните результат
git count-objects -vH

На живых проектах с историей в 2+ года разница бывает в разы.

⚠️ --prune=now безвозвратно удалит объекты, на которые нет ссылок. Если вы планировали восстановить что-то через git reflog — сделайте это до запуска.

💡 Бонус для CI/CD: если ваш пайплайн клонирует репо каждый раз — добавьте git gc в ночной cron. Экономия трафика и времени сборки может приятно удивить.

══════ Навигация ══════
Вакансии • Задачи • Собесы

🐸 Библиотека джависта

#Enterprise
  • 👍 5
  • 🔥 4
  • ❤ 1
Post #7801 2.74K
❌ ThreadLocal + Virtual Threads = утечка памяти

Если вы перешли на virtual threads, но продолжаете использовать ThreadLocal, то у вас проблема, которая пока просто не выстрелила.

ThreadLocal хранит данные в ThreadLocalMap — по одной map на каждый тред. Когда тредов было 200 в пуле, это было терпимо. Когда виртуальных тредов сотни тысяч, каждый несёт свою map, и heap начинает гореть. Плюс мутабельность: ThreadLocal.set() в глубоком call stack — это неявное состояние, которое легко забыть почистить через .remove(). В try-finally это работает до первого необработанного исключения.

Java 21 предлагает замену — ScopedValue.

🔹 Ключевые отличия

ScopedValue.where(TENANT_ID, tenant).run(() -> { ... }) — значение привязано к scope, а не к треду. Вышли из блока и значение автоматически недоступно. Никакого .remove(), никакого «забыл почистить».

Иммутабельность по дизайну. Нельзя сделать .set(). Если нужно другое значение, создаёте вложенный scope. Это убирает целый класс багов с «протеканием» контекста между запросами.

Легковесность. Внутри массив вместо HashMap. При масштабе в 100k+ тредов разница в потреблении памяти ощутимая.

Работает в связке со StructuredTaskScope: дочерние виртуальные треды автоматически наследуют scoped values родителя. Не нужно вручную пробрасывать контекст.

Практический вывод: если вы мигрируете на virtual threads, аудит ThreadLocal — обязательный шаг. ScopedValue пока preview, но API стабилизируется, и направление очевидно. Как минимум стоит уже сейчас заменить ThreadLocal на ReentrantLock-protected shared state или ScopedValue там, где передаёте tenant ID, request context, trace ID и подобные per-request данные.

══════ Навигация ══════
Вакансии • Задачи • Собесы

🐸 Библиотека джависта

#CoreJava
  • 👍 9
  • ❤ 1
  • 🔥 1
  • 🎉 1
Post #7800 2.07K

Forwarded from Proglib.academy | IT-курсы

😳 Documentation Driven Development звучит как ещё один модный термин. Пока не попробуешь объяснить свой проект AI.

Агент работает только с тем контекстом, который ему дали. Если документация неполная или устарела, он начинает додумывать — отсюда появляется неверный код.

🔘 На курсе «ИИ для разработчиков» эту тему разбирает Арсений Харланов. Он покажет, как подготовить документацию и контекст, чтобы агент понимал архитектуру проекта, ограничения и связи между компонентами.

Также разберём, как выбирать модель под задачу: Claude, DeepSeek, Qwen и другие ✏️

Впереди 7 недель работы со своим репозиторием. Вебинары проходят вживую и остаются в записи.


Стартуем 31 августа. До конца июля можно присоединиться по ранней цене, а доступ к материалам останется бессрочным 😀

🔗 Посмотреть, что будет на курсе

🏃‍♀️ Proglib Academy
  • 🎉 1
  • 🥱 1
Post #7799 2.18K
😮‍💨 Документация давно перестала быть формальностью. Особенно когда проект нужно объяснить кому-то ещё 👇
Post #7797 2.45K
❓ Как правильно определять границы сервисов в микросервисах?

Один из недооценённых скиллов в разработке — это умение провести правильную границу между сервисами. Большинство «распределённых монолитов», которые мы встречаем в продакшене, рождаются именно здесь.

Разобрали тему — держи шпаргалку 👇

🔹 Что такое Service Boundary

Это контракт на три вещи:

— за что сервис отвечает;
— какими данными он владеет;
— как он общается с соседями.

Представь компанию: HR не лезет в финансы, а склад не занимается зарплатами. Так же должны работать твои сервисы.

🔹 4 принципа, которые работают

1. Business Capability First

Режь по бизнес-функциям, а не по техническим слоям. OrderService, PaymentService, UserService, потому что именно так бизнес думает о системе.

2. Single Responsibility

Один сервис — одна ответственность. Если в описании сервиса есть союз и, это уже тревожный звоночек 🚨

3. Data Ownership

У каждого сервиса своя БД. Без исключений. Shared database = shared pain.

4. Loose Coupling

Только API, никакого прямого доступа к чужим таблицам.

🔹 Классический антипаттерн

// ❌ Бизнес-логика смешана в одном сервисе
@Service
public class BadOrderService {
public String processOrderAndPayment(int id) {
String order = orderRepository.findById(id)
.orElse("Order not found");
String paymentStatus = "Payment Successful"; // 🚨 чужая ответственность
return order + " | " + paymentStatus;
}
}


Выглядит безобидно, пока не нужно масштабировать платежи отдельно, сменить платёжного провайдера или добавить retry-логику только для оплаты. Тут и начнутся реальные проблемы.

🔹 Советы из практики

→ Начни с монолита. Не дроби систему заранее. Сначала пойми домен, потом режь по швам.
→ Следи за chatty communication. Если сервис делает 10 вызовов к соседям на каждый запрос, граница явно проведена не там.
→ Изучи DDD. Bounded Context из Domain-Driven Design это лучший инструмент для поиска правильных границ. Инвестиция окупается быстро

══════ Навигация ══════
Вакансии • Задачи • Собесы

🐸 Библиотека джависта

#CoreJava
  • 👍 3
  • 🔥 2
  • ❤ 1
  • ❤‍🔥 1
  • 👾 1
Post #7796 2.19K

Forwarded from Proglib.academy | IT-курсы

🤢 Чем больше разработчиков в команде начинают пользоваться Claude Code, тем заметнее одна проблема: кодовая база перестаёт выглядеть как работа одной команды.

Где-то есть тесты, где-то их забыли. Где-то агент следует архитектуре проекта, где-то предлагает решение, которое с ней не сочетается.

⚠️ И это не проблема Claude Code. Он просто следует тому контексту, который получает от каждого разработчика.

Завтра покажем, как передать AI инженерный контекст команды и не превратить его внедрение в ещё один источник хаоса.

🗓 23 июля, 19:00 МСК
Бесплатно. 60 минут доклада + 30 минут вопросов.

🔗 Занять место на вебинаре и разобраться, почему так происходит

🏃‍♀️ Proglib Academy
  • 🥱 2
  • ❤ 1
Post #7795 2.32K
🏃‍♀️ Скорость разработки растёт, но вместе с ней появляется новая проблема — кодовая база быстро теряет единый стиль.

Ниже — бесплатный вебинар о том, как этого избежать ⚠️
Post #7793 2.67K
⚙️ JaCoCo

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

В отличие от встроенных средств IntelliJ IDEA, которые отлично справляются с локальной разработкой, JaCoCo предлагает комплексный подход к анализу покрытия:

✔️ Многоформатные отчёты — HTML для визуализации, XML и CSV для автоматической обработки
✔️ Бесшовная интеграция с системами сборки (Maven/Gradle)
✔️ Готовность к CI/CD — работает с Jenkins, GitLab CI и другими платформами
✔️ Возможность исключать из анализа ненужные классы и пакеты
✔️ Совместимость с SonarQube и аналогичными системами контроля качества

JaCoCo идеален для проектов, где важна прозрачность метрик тестирования и автоматизация проверок качества кода на всех этапах разработки.

🔗 JaCoCo GitHub

🔹 Курс «Алгоритмы и структуры данных»
🔹 Получить консультацию менеджера
🔹 Сайт Академии 🔹 Сайт Proglib

🐸 Библиотека джависта

#Enterprise
  • 👍 5
  • ❤ 3
  • 🔥 1
  • 👏 1
Post #7791 2.39K
🐧 Магия Linux CLI

Процесс жрёт CPU на 100%, а top показывает только PID? Используйте strace -cp <PID>, и вы получите статистику системных вызовов — сразу видно, процесс висит на диске, сети или чём-то ещё.

🔹 Зачем это нужно

— Показывает, на какие системные вызовы тратится время: read, write, futex, epoll_wait.
— Если 90% времени в futex, то дедлок или контеншн на мьютексе.
— Если read/write, то проблема с I/O, проверяйте диск или NFS.
— Если connect/sendto, то приложение ждёт ответа от другого сервиса.

🔹 Как использовать

— Статистика вызовов процесса: strace -cp <PID>
— Трассировка в реальном времени: strace -p <PID> -e trace=network
— Только файловые операции: strace -p <PID> -e trace=file
— С таймстемпами: strace -p <PID> -T -e trace=write
— Трейсить с дочерними процессами: strace -fp <PID>

💡 strace замедляет процесс, поэтому на проде используйте strace -c (только статистика) вместо полной трассировки — оверхед минимальный.

══════ Навигация ══════
Вакансии • Задачи • Собесы

🐸 Библиотека джависта

#Enterprise
  • 👍 4
  • ❤ 2
  • 🔥 1
Post #7790 2.38K
  • 😁 19
  • 👍 3
  • 😢 1
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →