JavaRush /Курсы /Java Server /Диагностика Gradle: 4 команды

Диагностика Gradle: 4 команды

Java Server
5 уровень , 1 лекция
Открыта

1. Gradle как собеседник: сначала вопрос, потом команда

Если спросить новичка: «Что делать, когда сборка не работает?», часто звучит что-то вроде: «Ну… нажать Run ещё раз… может, повезёт?». Это нормальная стадия — примерно как пытаться починить Wi‑Fi взглядом. Но на практике полезнее относиться к Gradle как к инструменту, который умеет объяснять, что он знает о вашем проекте. Ему просто нужно задать правильный вопрос.

Вся сегодняшняя лекция о том, что у Gradle есть четыре очень «дружелюбные» команды, которые почти ничего не ломают, зато хорошо показывают состояние проекта. tasks отвечает на вопрос «какие кнопки вообще есть», help --task — «что делает конкретная кнопка», dependencies — «какие библиотеки реально участвуют», а --version — «какой Gradle и какая Java сейчас используются». Это не теория ради теории: эти команды экономят время каждый раз, когда проект ведёт себя не так, как вы ожидали.

Важно: все команды ниже я буду писать в виде ./gradlew .... На Windows обычно будет gradlew.bat .... Смысл один: мы запускаем именно Wrapper из репозитория, а не «что-то, что установлено на этой машине».

2. ./gradlew tasks: карта возможностей вашего проекта

Команда tasks — это буквально оглавление возможностей Gradle-проекта. В IDE вы видите кнопочки и меню, но Gradle умеет показать список задач официально и в одном формате для всех. Это особенно полезно, когда вы открыли чужой репозиторий, когда проект стал сложнее или когда вы просто забыли, как называется нужная задача. Спойлер: так будет регулярно, и это нормально.

Запускаем в корне проекта ReadLater Starter (то есть там, где лежит build.gradle.kts и gradlew):

# Печатаем список доступных задач (краткий список по группам)
./gradlew tasks

В ответ вы увидите довольно много текста. Цель — не читать его как книгу, а научиться быстро выхватывать смысл: задачи сгруппированы по категориям. Например, если у вас подключен application plugin (а он у нас подключен), вы увидите секцию Application tasks. Примерно так (вывод немного отличается между версиями, но общая идея стабильна):

Application tasks

run - Runs this project as a JVM application

А благодаря java plugin обычно будет секция Build tasks и задачи вроде build, jar, classes. Например:

Build tasks

build - Assembles and tests this project.
jar - Assembles a jar archive containing the classes of the 'main' feature.

Обратите внимание на важный психологический момент. До этого курса многие воспринимают Gradle как «что-то, что собирает проект». Команда tasks показывает, что Gradle — это не одна кнопка, а набор действий. А вы, как разработчик, выбираете нужное действие. Это как кухня: плита умеет и греть, и кипятить, и жарить. Если вы всё время жмёте одну кнопку «Сделай еду», результат будет… философский.

Иногда ./gradlew tasks показывает не все задачи. Это не баг и не заговор: часть задач считается продвинутыми и скрыта из краткого списка, чтобы новичку не вываливать в лицо сотни строк. Если хочется увидеть вообще всё, можно использовать флаг --all:

# Показываем вообще все задачи, включая "advanced" (вывод будет очень большим)
./gradlew tasks --all

Пока не нужно влюбляться в этот вывод и пытаться его выучить. Достаточно запомнить идею: если вы не знаете, как проект «умеет жить», tasks — первый ответ.

И да, это ещё один аргумент, почему запуск через IDE не должен быть единственным способом. IDE может добавить свои сценарии и спрятать часть Gradle-реальности. tasks показывает то, что действительно есть в проекте, а не то, что IDE «угадала».

3. ./gradlew help --task: паспорт задачи

После tasks появляется следующий естественный вопрос: «Окей, задача есть. Но что она точно делает?» Тут в дело вступает команда help --task. Она хороша тем, что вместо легенд и догадок («кажется, build — это то же самое, что jar…») вы получаете короткое описание прямо от Gradle.

Например, хотим понять задачу run:

# Смотрим подробности конкретной задачи (описание, тип, группу и путь)
./gradlew help --task run

Вывод будет примерно таким (сокращу до сути):

Detailed task information for run

Path
     :run

Type
     JavaExec

Description
     Runs this project as a JVM application

Group
     application

Из этого можно вынести сразу несколько практических вещей. Во‑первых, Path :run подтверждает, что задача существует в нашем проекте и живёт на корневом уровне — у нас один проект, без модулей. Во‑вторых, Description обычно совпадает с тем, что вы видели в tasks, но здесь формулировка точнее и стабильнее. В‑третьих, Group объясняет, почему задача оказалась в секции Application tasks.

Точно так же можно уточнить, что делает build:

# Уточняем, что именно Gradle вкладывает в задачу build
./gradlew help --task build

Со временем это превращается в очень полезную привычку. Вы видите в README или в чужом чате фразу «просто запусти assemble» и, вместо того чтобы нервно кивать, спокойно пишете ./gradlew help --task assemble. После этого уже можно понять, подходит ли эта задача именно вам.

Полезный трюк: help --task хорош не только для «главных» задач. Например, сегодня у нас есть команда dependencies, и она тоже является задачей. Можно сделать так:

# Даже "диагностические" команды — это задачи, у них тоже есть описание и опции
./gradlew help --task dependencies

И вы увидите, что это не магическая команда, а обычная задача, у которой есть опции и смысл. Здесь же часто можно заметить, что у задачи есть параметры (например, можно смотреть зависимости для конкретной конфигурации). Мы не обязаны запоминать все опции прямо сейчас — главное, что вы умеете находить первоисточник.

4. ./gradlew dependencies: смотрим реальные библиотеки

В предыдущей лекции мы выяснили неприятную для наивного мышления вещь: добавив одну зависимость, вы почти всегда получаете «букет» транзитивных зависимостей. То есть реальный набор библиотек в проекте — это дерево. Команда dependencies как раз печатает это дерево. И это тот редкий случай, когда длинный вывод Gradle — не наказание, а честный ответ на вопрос «что у меня реально на classpath?».

Самый простой вариант — без уточнений:

# Печатаем зависимости по всем конфигурациям (обычно очень много вывода)
./gradlew dependencies

Вы увидите много секций. Почему много? Потому что Gradle показывает зависимости по конфигурациям. Условно: есть зависимости, которые нужны при компиляции (compileClasspath), при запуске (runtimeClasspath), при тестах и так далее. Даже если вы пока не пишете тесты, Gradle всё равно умеет показывать эти конфигурации — это часть взрослой модели проекта.

Новичку обычно удобнее начать с двух конфигураций: compileClasspath и runtimeClasspath. Если вывод слишком большой, можно попросить показать дерево только для одной конфигурации. Это не какая-то продвинутая магия, а просто способ сделать вывод читаемым:

# Сужаем вывод до одной конфигурации: зависимости, которые реально нужны при запуске
./gradlew dependencies --configuration runtimeClasspath

Теперь представим фрагмент вывода, похожий на то, что будет в нашем ReadLater Starter после подключения стека логирования:

# Пример фрагмента дерева зависимостей (ветки рисуются через +--- и \---)
# runtimeClasspath — то, что попадает в classpath при запуске приложения
runtimeClasspath - Runtime classpath of source set 'main'.
+--- ch.qos.logback:logback-classic:1.5.32
|    +--- ch.qos.logback:logback-core:1.5.32
|    \--- org.slf4j:slf4j-api:2.0.17
\--- tools.jackson.core:jackson-databind:3.0.4
     +--- tools.jackson.core:jackson-annotations:3.0.4
     \--- tools.jackson.core:jackson-core:3.0.4

Смысл читается так: верхний уровень — это то, что в итоге присутствует в runtime classpath. Внутри каждого узла дерева перечислено, что подтянулось вместе с ним. Если вы увидели slf4j-api и не помните, чтобы добавляли его сами, не спешите обвинять IDE в колдовстве. Возможно, logback-classic привёл его транзитивно — и это как раз нормальная ситуация.

Теперь самое полезное: команда dependencies помогает отвечать на конкретные вопросы. Например, «почему у меня на запуске не находится класс?» — вероятно, зависимость не попала в runtimeClasspath. Или «почему в проекте две версии одной библиотеки?» — это тоже видно в дереве, хотя сложные случаи разрешения конфликтов мы сегодня разбирать не будем.

Ещё один полезный сценарий: у вас в build.gradle.kts стоит runtimeOnly("ch.qos.logback:logback-classic:1.5.32"), и вы хотите проверить, что logback-core тоже подтянулся. dependencies — самый честный способ убедиться, что мир такой, как вы думаете.

И последнее: не пугайтесь того, что вывод большой. Читабельность приходит так же, как чтение логов: сначала вы видите «много букв», а потом начинаете замечать паттерны (+---, \---, уровни вложенности) и быстро выхватывать важные ветки.

5. ./gradlew --version: проверяем, чем именно вы запускаете проект

Команда --version выглядит почти смешно короткой, но её практическая ценность огромна. Она отвечает на вопрос: «Какая версия Gradle сейчас запустилась, на какой JVM и вообще где мы находимся?» Когда всё работает, про это легко забыть. Когда не работает — это одна из первых команд, которые экономят полчаса.

Запускаем:

# Проверяем версию Gradle wrapper и JVM, на которой реально стартует сборка
./gradlew --version

Вывод будет примерно такой (сокращенный, но смысловой):

Gradle 9.4.0

Build time:   2025-xx-xx
Kotlin:       2.x.x
Groovy:       4.x
Ant:          1.10.x
Launcher JVM: 25 (Oracle/OpenJDK ...)
OS:           Windows 11 / macOS / Linux

На что смотреть в контексте нашего курса. Во‑первых, Gradle 9.4.0 — это наша фиксированная версия Wrapper. Если вы видите другую, значит, скорее всего, запустили не Wrapper, а локальный Gradle, или у вас как-то подменился Wrapper. Во‑вторых, Launcher JVM: 25 — это проверка, что сборка действительно стартует на Java 25. Когда на машине одновременно стоят JDK 17 и JDK 25, жизнь иногда любит устраивать сюрпризы. --version помогает поймать их на месте преступления.

Есть и третий нюанс, особенно полезный «в команде», даже если команда пока состоит из вас и будущего вас через два месяца. Когда вы будете писать README или просить помощи у коллеги, фраза «у меня не работает build» слишком общая. А фраза «у меня Gradle 9.4.0, JVM 25, но ./gradlew build падает вот так» — это уже нормальная инженерная коммуникация.

6. Маленькая методика: как избегать паники

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

Вот простая блок-схема, которая помогает «разруливать» типовые ситуации:

flowchart TD
    %% Мини-алгоритм: от вопроса → к диагностической команде Gradle
    A["Появилась проблема или вопрос по проекту"] --> B{"Что я хочу узнать?"}

    B -->|Какие возможности есть?| C["./gradlew tasks"]
    B -->|Что делает конкретная задача?| D["./gradlew help --task <name>"]
    B -->|Какие библиотеки реально участвуют?| E["./gradlew dependencies"]
    B -->|Какая версия Gradle/JVM сейчас?| F["./gradlew --version"]

    C --> G[Нашёл нужную задачу]
    D --> G
    E --> H[Нашёл нужную ветку дерева]
    F --> I[Убедился в baseline]

А чтобы было ещё проще, можно держать в голове табличку «вопрос → команда → куда смотреть». Здесь нет магии, просто сокращаем путь от «непонятно» к «конкретно»:

Ситуация/вопрос Команда На что смотреть в выводе
“Какой командой это вообще делается?” ./gradlew tasks Нужная секция (Application, Build), наличие run/build/jar
“А run точно существует? И что он делает?” ./gradlew help --task run Description, Group, Path
“Откуда в проекте взялась вот эта библиотека?” ./gradlew dependencies --configuration runtimeClasspath Ветка дерева, кто подтянул транзитивно
“Почему у меня разные версии окружения и у соседа всё работает?” ./gradlew --version Gradle version, Launcher JVM

Заметьте: ни одна из этих команд не требует «менять сборку». Это чистая диагностика. Сначала вы наблюдаете проект таким, какой он есть, а уже потом — в следующей лекции про baseline — будем говорить о том, как держать его стабильным.

7. Типичные ошибки при работе с Gradle-командами

Ошибка №1: запускать команды не из корня проекта.
Это классика: вы открыли терминал в src/main/java, набрали ./gradlew tasks, а терминал честно говорит: «нет такого файла». В такие моменты хочется обидеться на Gradle, но виновата география. Корень проекта — там, где лежат gradlew, build.gradle.kts, settings.gradle.kts. Если вы не в корне, Gradle не может быть вашим проводником: у него нет карты местности.

Ошибка №2: использовать gradle, а не ./gradlew.
Это тихая и опасная ошибка. gradle запускает локально установленный Gradle (если он установлен), а ./gradlew запускает версию, зафиксированную в репозитории. Иногда они совпадают, и вы думаете: «всё нормально». А потом внезапно начинают отличаться — и проект «ломается сам». В рамках курса правильная привычка простая: команды всегда начинаются с ./gradlew (или gradlew.bat на Windows).

Ошибка №3: пытаться прочитать весь вывод tasks или dependencies как роман.
Gradle выводит много текста, и новичок пытается «всё понять». В итоге не понимает ничего и устаёт. На практике вывод нужно читать как справочник: нашли нужную секцию, посмотрели 5–10 строк вокруг, остановились. Ваш мозг — не лог-файл, не надо прогонять через него гигабайты.

Ошибка №4: ожидать, что tasks или help “починят проект”.
tasks и help --task — диагностические команды. Они ничего не собирают и не запускают. Иногда новичок запускает ./gradlew tasks, видит список и думает: «почему приложение не стартануло?» Потому что вы попросили Gradle рассказать, что он умеет, а не делать работу. Это как открыть меню в ресторане и удивиться, что еда не появилась на столе.

Ошибка №5: смотреть зависимости “в целом”, но не уточнять конфигурацию.
./gradlew dependencies без параметров честно показывает всё подряд: compile, runtime, test, и это легко превращается в шум. Если вопрос про запуск приложения, то чаще всего полезнее смотреть runtimeClasspath. Если вопрос «почему не компилируется импорт», чаще полезнее compileClasspath. Мы пока не превращаем это в науку, но привычка «сначала выбрать правильную конфигурацию» сильно ускоряет диагностику.

1
Задача
Java Server, 5 уровень, 1 лекция
Недоступна
Карта задач проекта и описание `run`
Карта задач проекта и описание `run`
1
Задача
Java Server, 5 уровень, 1 лекция
Недоступна
Версия Gradle и дерево runtime-зависимостей
Версия Gradle и дерево runtime-зависимостей
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ