Перейти к основному содержимому

Справочник по Java


Назначение

Справочник-шпаргалка по Java — типы, синтаксис, стандартная библиотека, типовые паттерны. Не заменяет пошаговое обучение. Учебный курс: раздел.

Учебные статьи: Типы данных и переменные · Коллекции (сводка операций).

Новые API-гайды раздела Java:


Краткое пояснение

Компоненты и ключевые особенности языка.


Быстрый старт

javac Main.java && java Main
mvn compile
mvn package
./gradlew build
java -jar app.jar

Справочные таблицы

Содержание справочника


1. Основные понятия и структура программы

1.1. Класс

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

public class MyClass {
// тело класса
}

1.2. Метод main

Точка входа в программу — метод main. Он должен быть статическим, иметь модификатор public, возвращать void и принимать массив строк в качестве аргумента.

public static void main(String[] args) {
// точка входа
}

1.3. Пакеты

Пакеты группируют связанные классы и интерфейсы. Объявление пакета — первая исполняемая строка в файле (кроме комментариев).

package com.example.myapp;

1.4. Импорты

Инструкции import подключают классы из других пакетов. Можно импортировать отдельные классы или все классы пакета с помощью звёздочки.


import java.util.List;
import java.util.*;


2. Типы данных

2.1. Примитивные типы

В Java восемь примитивных типов — от byte до boolean. Каждый имеет фиксированный размер, диапазон значений и назначение. Подробнее — Типы данных и переменные.

ТипРазмер, байтДиапазон значенийНазначениеПримерПо умолчанию
byte1от −128 до 127целое числоbyte b = -5;0
short2от −32 768 до 32 767целое числоshort s = 42;0
int4от −2³¹ до 2³¹ − 1целое числоint i = -12345;0
long8от −2⁶³ до 2⁶³ − 1целое числоlong l = 1_122_334_455L;0L
float4±1,4×10⁻⁴⁵ … ±3,4×10³⁸вещественное числоfloat f = 3.141592f;0.0f
double8±4,9×10⁻³²⁴ … ±1,8×10³⁰⁸вещественное число двойной точностиdouble d = 3.141592653589d;0.0d
char2от 0 до 65 535символ (UTF-16)char c = 'Z';'\u0000'
booleanне фиксированtrue или falseлогическое значениеboolean b = true;false

Литералы float и long требуют суффиксов f/F и L/l. Целые литералы без суффикса — int; вещественные без суффикса — double.


2.2. Обёрточные классы (Wrapper Classes)

Каждому примитивному типу соответствует класс-обёртка:

  • Byte
  • Short
  • Integer
  • Long
  • Float
  • Double
  • Character
  • Boolean

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

Пример:

Integer num = Integer.valueOf(42);
int primitive = num.intValue();

2.3. Ссылочные типы

Ссылочные типы включают:

  • Классы (String, пользовательские классы)
  • Интерфейсы
  • Массивы
  • Перечисления (enum)
  • Аннотации

Значение ссылочного типа — это адрес объекта в куче. Значение по умолчанию — null.


3. Переменные

3.1. Объявление и инициализация

int age = 25;
String name = "Alice";
boolean isActive = true;

3.2. Область видимости

  • Локальные переменные: объявлены внутри метода или блока. Должны быть инициализированы перед использованием.
  • Поля класса (instance variables): принадлежат объекту. Инициализируются значениями по умолчанию.
  • Статические поля (class variables): принадлежат классу. Объявляются с ключевым словом static.

3.3. Модификаторы доступа для полей

  • public — доступ из любого места
  • protected — доступ из того же пакета и подклассов
  • default (без модификатора) — доступ только в пределах пакета
  • private — доступ только внутри класса

4. Операторы

4.1. Арифметические

  • + — сложение
  • - — вычитание
  • * — умножение
  • / — деление
  • % — остаток от деления

4.2. Унарные

  • + — унарный плюс
  • - — унарный минус
  • ++ — инкремент
  • -- — декремент
  • ! — логическое НЕ (для boolean)

4.3. Операторы присваивания

  • =
  • +=, -=, *=, /=, %=

4.4. Операторы сравнения

  • == — равенство (для примитивов — значение, для ссылок — адрес)
  • != — неравенство
  • <, <=, >, >=

4.5. Логические операторы

  • && — логическое И (с коротким замыканием)
  • || — логическое ИЛИ (с коротким замыканием)
  • & — побитовое И / логическое И без короткого замыкания
  • | — побитовое ИЛИ / логическое ИЛИ без короткого замыкания
  • ^ — исключающее ИЛИ (XOR)

4.6. Побитовые операторы

Побитовый оператор работает с отдельными битами целого (флаги, маски, сдвиги).

  • ~ — побитовое НЕ
  • &lt;&lt; — сдвиг влево
  • &gt;&gt; — арифметический сдвиг вправо
  • &gt;&gt;> — логический сдвиг вправо

4.7. Тернарный оператор

int max = (a > b) ? a : b;

4.8. Оператор instanceof

Проверяет, является ли объект экземпляром указанного класса или интерфейса.

if (obj instanceof String) { ... }

5. Управляющие конструкции

5.1. Условные операторы

if-else
if (condition) {
// код
} else if (anotherCondition) {
// код
} else {
// код
}

switch (до Java 13 и после)

Поддерживает byte, short, char, int, String, enum, и начиная с Java 17 — sealed-классы.

Java 14+ поддерживает выражения switch:

int dayValue = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};

5.2. Циклы

for
for (int i = 0; i < 10; i++) { ... }

for-each (enhanced for)
for (String item : list) { ... }

while
while (condition) { ... }

do-while
do {
// код
} while (condition);

5.3. Операторы управления потоком

  • break — выход из цикла или switch
  • continue — переход к следующей итерации цикла
  • return — выход из метода с возвратом значения (если метод не void)

Можно использовать метки для выхода из вложенных циклов:

outer: for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (someCondition) break outer;
}
}

6. Методы

Интерактивное демо — вызов функции и стек на примере JavaScript. В Java объявление другое, но вызов, локальные переменные и возврат устроены так же. Обобщённо: функции в коде.

Play ITЗагрузка интерактивного демо…


6.1. Сигнатура метода

[модификаторы] тип_возврата имя([параметры]) [throws исключения]

Пример:

public static int add(int a, int b) {
return a + b;
}

6.2. Перегрузка методов

Методы с одинаковым именем, но разными параметрами (тип, количество, порядок).


6.3. Вариадические методы

Принимают переменное число аргументов одного типа:

public void printAll(String... messages) {
for (String msg : messages) System.out.println(msg);
}

Вызов:

printAll("A", "B", "C");

6.4. Рекурсия

Метод вызывает сам себя. Должно быть условие завершения.

public int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}

7. Классы и объекты

7.1. Конструкторы

  • Имя совпадает с именем класса
  • Не имеют возвращаемого типа
  • Вызываются при создании объекта через new
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
}

7.2. Ключевое слово this

Ссылается на текущий экземпляр объекта. Используется для:

  • Разрешения конфликта имён (параметр и поле)
  • Вызова другого конструктора (this(...))
  • Возврата текущего объекта

7.3. Статические члены

Объявляются с static. Принадлежат классу, а не экземпляру.

public static final double PI = 3.14159;

7.4. Блоки инициализации

  • Статический блок: выполняется один раз при загрузке класса
  • Блок инициализации экземпляра: выполняется перед каждым конструктором
static {
// инициализация статических полей
}

{
// инициализация полей экземпляра
}

8. Наследование и полиморфизм

8.1. Ключевое слово extends

Класс наследует поля и методы другого класса.

class Animal { ... }
class Dog extends Animal { ... }

8.2. Ключевое слово super

  • Вызов конструктора родителя: super(...)
  • Доступ к полям и методам родителя: super.method()

8.3. Переопределение методов (Override)

Метод в подклассе заменяет метод родительского класса. Должен иметь:

  • То же имя
  • Те же параметры
  • Совместимый тип возврата
  • Уровень доступа не уже, чем у родителя

Аннотация @Override настоятельно рекомендуется: компилятор проверит, что метод действительно переопределяет родительский.


8.4. Запрет наследования

Класс, помеченный final, не может быть унаследован.

public final class MathUtils { ... }

9. Интерфейсы и абстрактные классы

9.1. Интерфейс (interface)

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

  • Абстрактные методы (без тела)
  • Методы по умолчанию (default) — с реализацией
  • Статические методы
  • Частные методы (private) — начиная с Java 9
public interface Drawable {
void draw(); // абстрактный метод

default void resize() {
System.out.println("Resizing...");
}

static boolean isSupported() {
return true;
}
}

Класс реализует интерфейс с помощью ключевого слова implements.

public class Circle implements Drawable {
public void draw() {
System.out.println("Drawing a circle");
}
}

Один класс может реализовывать несколько интерфейсов.


9.2. Абстрактный класс (abstract class)

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

public abstract class Shape {
protected String color;

public abstract double area();

public void setColor(String color) {
this.color = color;
}
}

Подкласс обязан реализовать все абстрактные методы, если сам не является абстрактным.


9.3. Отличия

  • Интерфейс поддерживает множественное наследование поведения.
  • Абстрактный класс позволяет наследовать состояние (поля) и частичную реализацию.
  • Интерфейсы не имеют конструкторов; абстрактные классы — имеют.

10. Исключения (Exceptions)

10.1. Иерархия исключений

  • Throwable — корень иерархии
    • Error — фатальные ошибки (например, OutOfMemoryError)
    • Exception
      • Проверяемые (checked) — компилятор требует обработки (IOException, SQLException)
      • Непроверяемые (unchecked) — наследники RuntimeException (NullPointerException, IllegalArgumentException)

10.2. Обработка исключений

try {
// код, который может выбросить исключение
} catch (IOException e) {
// обработка
} finally {
// всегда выполняется
}

10.3. Множественные catch

catch (IOException | SQLException e) {
// обработка нескольких типов
}

10.4. Try-with-resources (Java 7+)

Автоматическое закрытие ресурсов, реализующих AutoCloseable.

try (FileInputStream fis = new FileInputStream("file.txt")) {
// работа с файлом
} // fis.close() вызывается автоматически

10.5. Создание собственных исключений

public class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message);
}
}

11. Дженерики (Generics)

11.1. Основы

Дженерики обеспечивают типобезопасность при компиляции.

List<String> names = new ArrayList<>();
names.add("Alice");
// names.add(123); // ошибка компиляции

11.2. Параметры типа

  • T — Type
  • E — Element
  • K — Key
  • V — Value
  • N — Number

11.3. Ограничения

  • ? — wildcard (неизвестный тип)
  • ? extends T — верхняя граница (любой подтип T)
  • ? super T — нижняя граница (любой надтип T)

Пример:

public void copy(List<? extends Number> src, List<? super Number> dest) { ... }

11.4. Стирание типов (Type Erasure)

Во время выполнения информация о дженериках недоступна. Это ограничивает рефлексию и запрещает создание массивов параметризованных типов.


12. Коллекции (Collections Framework)

12.1. Иерархия основных интерфейсов

  • Collection
    • List — упорядоченная коллекция с дубликатами (ArrayList, LinkedList, CopyOnWriteArrayList)
    • Set — без дубликатов (HashSet, LinkedHashSet, TreeSet, EnumSet)
    • Queue — очередь (ArrayDeque, PriorityQueue; BlockingQueue — в java.util.concurrent)
  • Map — ассоциативный массив (HashMap, LinkedHashMap, TreeMap, ConcurrentHashMap)

Подробная шпаргалка с таблицами сложности — Коллекции в Java.


12.2. Основные реализации

ТипОсобенности
ArrayListO(1) доступ по индексу; вставка в середину — O(n)
LinkedListO(1) вставка/удаление с известным узлом; get(i) — O(n)
HashSetУникальность; O(1) в среднем; порядок не гарантирован
LinkedHashSetКак HashSet + порядок вставки
TreeSetСортировка; O(log n)
HashMapПары ключ–значение; O(1) в среднем; один null-ключ
LinkedHashMapКак HashMap + порядок вставки (или access-order)
TreeMapСортировка по ключу; O(log n)
ArrayDequeОчередь и стек быстрее legacy Stack

12.3. Утилиты

  • Collectionssort, reverse, shuffle, unmodifiableList, synchronizedList
  • Arrays — методы для массивов (asList, sort, binarySearch)

12.4. Stream API (Java 8+)

Подробнее: Stream API в Java.

Позволяет функционально обрабатывать коллекции.

List<String> result = names.stream()
.filter(n -> n.startsWith("A"))
.map(String::toUpperCase)
.collect(Collectors.toList());

13. Многопоточность

13.1. Создание потоков

  • Через наследование Thread
  • Через реализацию Runnable
  • Через ExecutorService
Thread t = new Thread(() -> {
System.out.println("Running in thread");
});
t.start();

13.2. Пул потоков

ExecutorService executor = Executors.newFixedThreadPool(4);
executor.submit(() -> { /* задача */ });
executor.shutdown();

13.3. Синхронизация

  • synchronized — блок или метод
  • volatile — гарантирует видимость изменений между потоками
  • Lock — гибкая альтернатива (ReentrantLock)
  • AtomicInteger, AtomicReference — атомарные операции без блокировок

13.4. CompletableFuture (Java 8+)

Подробнее: Асинхронность в Java.

Асинхронное программирование с цепочками действий.

CompletableFuture.supplyAsync(() -> fetchData())
.thenApply(data -> process(data))
.thenAccept(result -> System.out.println(result));

13.5. JMM и concurrency decision table

СитуацияБазовый выбор
Флаг остановки, "готово/не готово"volatile
Счетчик, инкремент, CASAtomicInteger / AtomicLong
Несколько полей должны меняться как единое состояниеsynchronized или Lock
Много потоков читают редко изменяемую структуруReadWriteLock

Короткое правило:

  • volatile решает задачу видимости;
  • x++ остается неатомарной операцией;
  • для инкрементов и счетчиков лучше AtomicInteger или AtomicLong.

14. Работа с файлами и вводом-выводом

Подробнее: Ввод-вывод и файлы в Java, Строки в Java.


14.1. Потоки ввода-вывода

  • InputStream / OutputStream — байтовые
  • Reader / Writer — символьные

14.2. Файловые операции (NIO.2, Java 7+)

Пакет java.nio.file:

  • Path — путь к файлу
  • Files — статические методы (readAllLines, write, copy, delete)
  • Paths.get("...") — создание объекта Path

Пример:

List<String> lines = Files.readAllLines(Paths.get("input.txt"));
Files.write(Paths.get("output.txt"), lines);

14.3. Сериализация

Класс должен реализовывать Serializable.

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.ser"));
oos.writeObject(obj);

15. Аннотации (Annotations)

Подробнее: Аннотации и рефлексия в Java, Современные конструкции Java.


15.1. Встроенные аннотации

  • @Override — переопределение метода
  • @Deprecated — устаревший код
  • @SuppressWarnings — подавление предупреждений

15.2. Создание собственных аннотаций

public @interface Author {
String name();
int version() default 1;
}

Использование:

@Author(name = "Timur", version = 2)
public class MyClass { ... }

15.3. Retention и Target

  • @Retention(RetentionPolicy.RUNTIME) — доступна во время выполнения
  • @Target(ElementType.METHOD) — применима только к методам

16. Модульная система (Project Jigsaw, Java 9+)

16.1. module-info.java

module com.example.myapp {
requires java.base;
requires java.sql;
exports com.example.myapp.api;
}

16.2. Преимущества

  • Явные зависимости
  • Инкапсуляция пакетов
  • Улучшенная производительность запуска

17. Стандартная библиотека — ключевые пакеты

ПакетНазначение
java.langОсновные классы (Object, String, Math, System)
java.utilКоллекции, дата/время, Scanner, Random
java.ioПотоки ввода-вывода
java.nioНовые I/O операции
java.netСетевое взаимодействие
java.timeСовременный API даты и времени (Java 8+)
java.textФорматирование текста, чисел, дат
java.mathBigInteger, BigDecimal
java.securityКриптография, подписи
javax.cryptoШифрование

18. Дата и время (java.time)

18.1. Основные классы

  • LocalDateTime — дата и время без часового пояса
  • ZonedDateTime — с часовым поясом
  • Instant — момент времени в UTC
  • Duration — временной промежуток в секундах/наносекундах
  • Period — период в годах, месяцах, днях

18.2. Пример

LocalDateTime now = LocalDateTime.now();
LocalDateTime future = now.plusDays(7);
long days = ChronoUnit.DAYS.between(now, future);

19. Работа с JSON и XML

19.1. JSON

Java не включает встроенную поддержку JSON в стандартную библиотеку до Java EE / Jakarta EE, но широко используются сторонние библиотеки:


Jackson (наиболее популярная)
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(person);
Person p = mapper.readValue(json, Person.class);

Gson (от Google)
Gson gson = new Gson();
String json = gson.toJson(person);
Person p = gson.fromJson(json, Person.class);

19.2. XML

DOM-парсинг (в памяти)
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File("data.xml"));

SAX-парсинг (событийный, потоковый)

Подходит для больших файлов, потребляет меньше памяти.


JAXB (Java Architecture for XML Binding, устарел в Java 11, восстановлен в Jakarta EE)

Аннотации позволяют преобразовывать объекты в XML и обратно:

@XmlRootElement
public class Person {
@XmlElement
public String name;
}

20. Сетевое программирование

20.1. Низкоуровневые сокеты

TCP (Socket / ServerSocket)
// Сервер
ServerSocket server = new ServerSocket(8080);
Socket client = server.accept();

// Клиент
Socket socket = new Socket("localhost", 8080);

UDP (DatagramSocket)
DatagramSocket socket = new DatagramSocket();
byte[] buffer = "Hello".getBytes();
InetAddress address = InetAddress.getByName("localhost");
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, address, 9000);
socket.send(packet);

20.2. HTTP-клиент (Java 11+)

Встроенная поддержка HTTP/2:

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/data"))
.build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

Для более сложных сценариев используются библиотеки: Apache HttpClient, OkHttp.


21. JDBC (Java Database Connectivity)

21.1. Подключение к базе

String url = "jdbc:postgresql://localhost:5432/mydb";
String user = "user";
String password = "pass";

Connection conn = DriverManager.getConnection(url, user, password);

21.2. Выполнение запросов

Statement (без параметров)
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users");

PreparedStatement (с параметрами, защита от SQL-инъекций)
PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE id = ?");
ps.setInt(1, userId);
ResultSet rs = ps.executeQuery();

21.3. Обработка результата

while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
}

21.4. Транзакции

conn.setAutoCommit(false);
try {
// несколько операций
conn.commit();
} catch (SQLException e) {
conn.rollback();
}

21.5. Пулы соединений

Используются в production — HikariCP, Apache DBCP, C3P0.


22. Модульное тестирование

22.1. JUnit 5 (современный стандарт)

Аннотации
  • @Test — метод теста
  • @BeforeEach, @AfterEach — перед/после каждого теста
  • @BeforeAll, @AfterAll — статические методы, один раз на класс
  • @Disabled — пропустить тест

Утверждения (Assertions)
assertEquals(expected, actual);
assertTrue(condition);
assertThrows(IllegalArgumentException.class, () -> method());

22.2. Mockito (моки)

List mockedList = Mockito.mock(List.class);
when(mockedList.get(0)).thenReturn("first");
assertEquals("first", mockedList.get(0));
verify(mockedList).get(0);

23. Сборка проектов

23.1. Maven

Файл pom.xml определяет проект, зависимости, плагины.

<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
</dependencies>

Команды Maven:

mvn compile
mvn test
mvn package
mvn clean install

23.2. Gradle

Файл build.gradle (Groovy или Kotlin DSL):

dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
}

Команды:

  • ./gradlew build
./gradlew build
  • ./gradlew test
./gradlew test
  • ./gradlew run
./gradlew run

Gradle использует инкрементальную сборку и кэширование, что ускоряет повторные сборки.


24. JVM — параметры запуска и настройка

Опции передаются команде java до имени класса или -jar. Они задают системные свойства, размер кучи, сборщик мусора, логирование GC и поведение при сбоях. Большинство флагов фиксируется при старте процесса; проверить фактическую конфигурацию работающей JVM можно через jcmd <pid> VM.flags (см. JVM в проде).

Теория памяти, поколений и алгоритмов GC — в JVM, память и потоки и сравнении GC Java, Python и Go.

24.1. Три категории флагов

HotSpot (OpenJDK) делит аргументы на три уровня. Префикс подсказывает, где искать опцию в справке.

КатегорияПрефиксКто поддерживаетКак посмотреть список
Стандартныебез префикса (-D, -jar, …)любая JVM по спецификацииjava -help
Нестандартные-Xреализация HotSpot (могут меняться между версиями)java -X
Расширенные-XXтонкая настройка HotSpotjava -XX:+PrintFlagsFinal (длинный вывод)

Синтаксис расширенных флагов: + включает булеву опцию, - выключает; для чисел и строк — -XX:Имя=значение (например -XX:MaxGCPauseMillis=200).


24.2. Стандартные опции

ФлагНазначение
-Dproperty=valueСистемное свойство; в коде — System.getProperty("property")
-javaagent:/path/to/agent.jarПодключение Java-агента (мониторинг, APM, bytecode-инструментация)
-agentpath:pathnameНативный агент по абсолютному пути
-verbose:classЛог загрузки каждого класса
-verbose:gcКраткий вывод событий GC (устаревает; предпочтителен -Xlog:gc* с JDK 9+)
-verbose:jniВызовы JNI

Пример:

java -Dfile.encoding=UTF-8 -Dspring.profiles.active=prod -jar app.jar

24.3. Нестандартные опции (-X)

ФлагНазначение
-Xms<size>Начальный размер heap (например 512m, 1g)
-Xmx<size>Максимальный размер heap; при исчерпании — OutOfMemoryError: Java heap space
-Xss<size>Размер стека одного потока (эквивалент -XX:ThreadStackSize)
-XintТолько интерпретация, без JIT (диагностика, не для продакшена)
-Xbootclasspath:pathДополнительные архивы для bootstrap class loader (редко)
-Xloggc:fileЛог GC в файл (устарел; с JDK 9+ — -Xlog:gc*:file=gc.log)
-XnoclassgcОтключить сборку неиспользуемых классов (узкие сценарии)
-XprofПрофилирование JVM (устарело; вместо него JFR, async-profiler)

Типовый запуск с фиксированной кучей:

java -Xms1g -Xmx8g -jar app.jar

Равные -Xms и -Xmx убирают расширение heap во время работы и упрощают планирование памяти на сервере.

Metaspace (метаданные классов, с Java 8 вместо PermGen) настраивается флагами -XX, не -X:

  • -XX:MetaspaceSize — порог, после которого JVM запрашивает память у ОС
  • -XX:MaxMetaspaceSize — жёсткий потолок (при превышении — OOM Metaspace)

24.4. Расширенные опции — поведение и GC

Выбор сборщика мусора (подробнее — раздел 4.15):

ФлагСборщикКогда уместен
-XX:+UseSerialGCSerialМалый heap, одно ядро
-XX:+UseParallelGCParallel (Throughput)Пакетная обработка, допустимы редкие длинные паузы
-XX:+UseG1GCG1Универсальный выбор; по умолчанию с JDK 9
-XX:+UseZGCZGCНизкие паузы, большие heap (JDK 15+ generational)
-XX:+UseShenandoahGCShenandoahНизкие паузы, альтернатива ZGC
-XX:+UseConcMarkSweepGCCMSУдалён с JDK 14 — только legacy

Параметры G1 и целевых пауз:

ФлагНазначение
-XX:MaxGCPauseMillis=nЦелевая длительность паузы для G1 (ориентир, не гарантия)
-XX:G1HeapRegionSize=4mРазмер региона G1 (обычно 1–32 МБ, часто подбирается автоматически)
-XX:MaxNewSize=256mПотолок young generation (для поколенческих сборщиков)

Java Flight Recorder (JFR):

java -XX:+FlightRecorder -XX:StartFlightRecording=duration=60s,filename=app.jfr -jar app.jar

В Temurin/OpenJDK 11+ JFR доступен без коммерческой лицензии. Запись у работающего процесса — jcmd (см. JVM в проде — jcmd, дамп памяти и JFR).

Пример продакшен-профиля с G1:

java -Xms2g -Xmx2g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 \
-Xlog:gc*,gc+heap=info:file=gc.log:time,uptime,level,tags \
-jar app.jar

24.5. Расширенные опции — отладка и диагностика

ФлагНазначение
-XX:ErrorFile=./hs_err_%p.logФайл при фатальной ошибке JVM (crash)
-XX:+HeapDumpOnOutOfMemoryErrorАвтоматический heap dump при OOM
-XX:HeapDumpPath=./dumpsКаталог для дампов
-XX:OnError="cmd args"Команда ОС при fatal error (осторожно в проде)
-XX:+TraceClassLoadingКакие классы загружаются
-XX:+PrintClassHistogramГистограмма объектов по SIGQUIT (Linux) / Ctrl+Break

Логирование GC. Флаги -XX:+PrintGC, -XX:+PrintGCDetails устарели. С JDK 9 используйте унифицированное логирование:

-Xlog:gc*:file=gc.log:time,uptime,level,tags

Удалённая отладка (IDE подключается к процессу):

-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005

suspend=y останавливает JVM до подключения отладчика — удобно при старте, опасно в проде без контроля.


24.6. Расширенные опции — производительность

ФлагНазначение
-XX:ThreadStackSize=256Размер стека потока в килобайтах (аналог -Xss256k)
-XX:+UseStringDeduplicationДедупликация одинаковых String в G1 (JDK 8u20+)
-XX:MaxPermSize=128mТолько Java 7 и ранее (PermGen); в Java 8+ — Metaspace
-XX:+AggressiveOptsУдалён; не использовать в новых версиях

Модульная система (Java 9+): --add-opens java.base/java.lang=ALL-UNNAMED открывает пакет для reflection (часто в legacy-библиотеках и тестах). Это обход ограничений JPMS, а не замена явного opens в module-info.java.


24.7. Шпаргалка — что держать под рукой

ЗадачаМинимальный набор флагов
Ограничить память-Xms… -Xmx…
Включить G1 явно-XX:+UseG1GC -XX:MaxGCPauseMillis=…
Лог GC в файл-Xlog:gc*:file=…
OOM → дамп для MAT-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=…
Профиль 60 с в продеjcmd <pid> JFR.start … (runbook)
Проверить флаги процессаjcmd <pid> VM.flags
Память и контейнеры

В Docker и Kubernetes лимит cgroup может быть меньше видимой ОЗУ хоста. С JDK 10+ учитывайте -XX:+UseContainerSupport (включён по умолчанию в современных сборках) и не ставьте -Xmx выше лимита контейнера — иначе OOMKill со стороны оркестратора раньше, чем Java heap.


25. Профилирование и мониторинг

25.1. Встроенные инструменты JDK

  • jps — список Java-процессов
  • jstat — статистика GC и heap
  • jstack — дамп стеков потоков
  • jmap — информация о памяти, heap dump
  • jconsole, jvisualvm — графические инструменты мониторинга
  • jcmd — универсальная команда для отправки команд процессу

25.2. Внешние инструменты

  • VisualVM — расширенный мониторинг
  • YourKit, JProfiler — коммерческие профайлеры
  • Prometheus + Micrometer — метрики в production

25.3. JFR быстрые команды

jcmd <pid> JFR.start name=debug settings=profile duration=60s filename=recording.jfr
jcmd <pid> JFR.dump name=debug filename=recording.jfr
jcmd <pid> JFR.stop name=debug

При чтении JFR сначала смотрят:

  1. горячие методы по CPU;
  2. аллокации по типам/методам;
  3. паузы GC и частоту stop-the-world событий.

26. Отладка

26.1. Логирование

Используйте фреймворки вместо System.out.println:

  • SLF4J — фасад
  • Logback или Log4j2 — реализации

Пример:

private static final Logger log = LoggerFactory.getLogger(MyClass.class);
log.info("Processing user: {}", userId);

26.2. IDE-отладка

  • Точки останова (breakpoints)
  • Пошаговое выполнение (step into / over / out)
  • Инспекция переменных
  • Вычисление выражений во время отладки

27. Лучшие практики разработки на Java

27.1. Именование

  • Классы — UpperCamelCase
  • Методы и переменные — lowerCamelCase
  • Константы — UPPER_SNAKE_CASE
  • Пакеты — строчные, без подчёркиваний (com.example.project)

27.2. Читаемость кода

  • Методы короткие (до 20–30 строк)
  • Одна ответственность на метод
  • Избегать глубокой вложенности условий
  • Использовать выразительные имена

27.3. Безопасность

  • Не логировать чувствительные данные (пароли, токены)
  • Валидировать входные данные
  • Использовать PreparedStatement вместо конкатенации SQL
  • Обновлять зависимости (CVE-уязвимости)

27.4. Производительность

  • Избегать создания лишних объектов в циклах
  • Использовать StringBuilder для конкатенации строк в цикле
  • Предпочитать примитивы обёрткам, где возможно
  • Использовать пул соединений и потоков

27.5. Обработка ошибок

  • Не игнорировать исключения
  • Логировать причину ошибки (e.getMessage(), e.getCause())
  • Не выбрасывать исключения из блоков finally
  • Использовать конкретные типы исключений

27.6. Неизменяемость

  • Делать классы неизменяемыми, когда это возможно (final поля, отсутствие сеттеров)
  • Использовать Collections.unmodifiableList() для защиты коллекций

27.7. Совместимость

  • Указывать версию языка в pom.xml или build.gradle
  • Избегать использования preview-функций в production
  • Тестировать на целевой версии JVM

28. Language Basics — API-дополнение

Сводка ключевых API-акцентов для базового языка (синхронизировано с dev.java language basics):

ТемаЧто важно в production
Примитивы и обёрткиИзбегать лишнего boxing в горячих участках
equals / hashCodeКорректные контракты для коллекций и доменных типов
switch-выраженияЯвное ветвление без fall-through
record / sealedМеньше шаблонного кода и более строгие модели
ИсключенияChecked/unchecked разделять по смыслу контракта

Быстрые API-правила:

  • String сравнивать через equals, не ==.
  • Для денег использовать BigDecimal, не double.
  • Для DTO в новом коде часто лучше record.
  • В публичных контрактах лучше явная семантика Optional, чем "иногда null".
record UserDto(long id, String email) {}

String level = switch (score) {
case 0, 1 -> "low";
case 2 -> "medium";
default -> "high";
};

29. Collections Framework — API-дополнение

Расширение к разделу коллекций: фокус на правильный выбор структуры и контракты.

СтруктураБрать, когдаРиск при неверном выборе
ArrayListдефолтный списокожидать дешёвые вставки в середину
LinkedListчастые вставки в начало/серединувызывать get(index) в цикле
HashSetуникальные элементыждать стабильный порядок обхода
HashMapбыстрый key-valueзависеть от порядка итерации
LinkedHashMapнужен порядок вставкисчитать его автоматически sorted
TreeMap / TreeSetнужен сортированный обходпереплатить O(log n), когда порядок не нужен
EnumSetмножество констант enumиспользовать HashSet без причины
ArrayDequeочередь/стек в кодебрать Stack или Vector
PriorityQueueприоритет на извлечениипутать с FIFO
ConcurrentHashMapконкурентный доступзаменять им всё без причины
BlockingQueueproducer–consumerблокировки без ограничения ёмкости

Ключевые API-методы Map, которые реально экономят код:

Map<String, Integer> counts = new HashMap<>();
counts.merge("java", 1, Integer::sum);
counts.computeIfAbsent("streams", k -> 0);
counts.putIfAbsent("virtual-threads", 1);

Практика:

  • Для неизменяемых наборов — List.of, Set.of, Map.of.
  • Для очереди/стека в алгоритмах — ArrayDeque, а не Stack.
  • Для удаления по условию — removeIf, а не мутация в for-each.

30. Streams и Gatherers — API-дополнение

Дополнение к Stream API: как проектировать pipeline без потери читаемости и скорости.

КатегорияПримеры
Intermediatefilter, map, flatMap, distinct, sorted, limit
TerminaltoList, collect, reduce, count, findFirst, anyMatch
Primitive streamsIntStream, LongStream, DoubleStream

Типовой pipeline:

Map<String, Long> byRole = users.stream()
.filter(User::isActive)
.collect(Collectors.groupingBy(User::getRole, Collectors.counting()));

Критичные правила:

  1. Для toMap всегда думайте о коллизиях ключей.
  2. parallelStream() подходит для CPU-bound, не для блокирующего I/O.
  3. peek — для отладки, не для бизнес-логики.

Про Gatherers (Java 24+) — используйте, когда нужен stateful intermediate-шаг (например, оконная обработка), а обычный pipeline получается нечитабельным или слишком аллоцирует промежуточные структуры.


31. Virtual Threads — API-дополнение

Дополнение к асинхронности и устройству virtual threads: практическая карта применения (Java 21+).

СценарийРекомендуемая модель
Массовый блокирующий I/Ovirtual threads
CPU-bound расчётыфиксированный пул platform threads
Смешанный сервисразделение пулов CPU/I-O + таймауты

Базовый шаблон:

try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
Future<String> profile = executor.submit(() -> loadProfile(userId));
Future<List<String>> orders = executor.submit(() -> loadOrders(userId));
// ...
}

На что смотреть в эксплуатации:

  • таймауты на все внешние вызовы;
  • отсутствие долгого блокирующего I/O внутри synchronized;
  • метрики p95/p99 и thread dump под нагрузкой.

32. Executor sizing heuristics

Практические эвристики, с которых обычно начинают:

Тип нагрузкиСтартовая настройка
CPU-boundразмер пула около числа ядер
I/O-bound (platform threads)ограниченный пул + очередь + таймауты
I/O-bound (virtual threads)task-per-request + контроль таймаутов и cancellation

Всегда проверяйте настройки под нагрузочным тестом.

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

Основа по протоколу

Базовый разбор HTTP и HTTPS находится в отдельной статье — HTTP как основа веб-интеграций.


В подборках

Статья входит в тематические подборки и блок "С чего начать?" на главной. Соседние шаги того же маршрута:

СправочникиСправочник по конфигурациям в Java, Документация и инструменты Java (Microsoft), Справочник по Python, Справочник по F#, Справочник по Flask, Справочник по конфигурациям в C#.


Содержание