Java | Фишки и трюки
7.21K subscribers
182 photos
29 videos
6 files
40 links
Java: примеры кода, интересные фишки и полезные трюки

Купить рекламу: https://telega.in/c/java_tips_and_tricks

✍️По всем вопросам: @Pascal4eg
Download Telegram
🚀 Секреты работы с VarHandle и как они могут заменить рефлексию

VarHandle — это "новый" API, введённый в Java 9, который предоставляет низкоуровневый доступ к переменным (поля, массивы и элементы) в многопоточной среде. Он является более производительным и безопасным способом работы с полями, чем традиционная рефлексия.

🔍 Зачем использовать VarHandle вместо рефлексии?
1️⃣ ПроизводительностьVarHandle предоставляет прямой доступ к полям и переменным, минуя накладные расходы, которые присущи рефлексии.
2️⃣ Поддержка атомарных операцийVarHandle поддерживает атомарные операции, такие как чтение и запись, что полезно в многозадачности.
3️⃣ Типобезопасность — в отличие от рефлексии, VarHandle является типобезопасным, что уменьшает количество ошибок при компиляции.

📌 Как использовать VarHandle?
1️⃣ Используйте метод VarHandles.lookup() для получения экземпляра VarHandle.
2️⃣ Используйте его для чтения и записи значений в поля объектов.
3️⃣ Поддерживает операции, такие как get(), set(), а также атомарные операции.

📌 Пример использования VarHandle:

import java.lang.invoke.*;

public class VarHandleExample {
private String field = "Initial Value";

public static void main(String[] args) throws Throwable {
VarHandleExample example = new VarHandleExample();
VarHandle varHandle = MethodHandles.lookup().findVarHandle(VarHandleExample.class, "field", String.class);

// Чтение значения через VarHandle
System.out.println("Current value: " + varHandle.get(example));

// Изменение значения через VarHandle
varHandle.set(example, "Updated Value");
System.out.println("Updated value: " + varHandle.get(example));

// Атомарное обновление значения
boolean success = varHandle.compareAndSet(example, "Updated Value", "New Value");
System.out.println("Atomic update successful: " + success);
System.out.println("Final value: " + varHandle.get(example));
}
}


Когда использовать VarHandle вместо рефлексии?
- Когда необходимо работать с полями объектов или массивами без накладных расходов рефлексии.
- Для оптимизации производительности в многозадачных приложениях.
- Когда нужно обеспечить типобезопасность и атомарность операций при работе с полями.

#Java #VarHandle #Reflection #Concurrency #Performance
👍132
🚀 Ускорение загрузки через AOT Compilation

AOT (Ahead-Of-Time) Compilation — это технология, которая позволяет компилировать байт-код Java в нативный код до его запуска. Это может значительно ускорить время загрузки приложения, так как исключает необходимость выполнения JIT-компиляции в процессе работы.

🔍 Зачем использовать AOT Compilation?
1️⃣ Ускорение старта приложения — уменьшение времени запуска за счет заранее скомпилированных частей программы.
2️⃣ Понижение нагрузки на JVM — выполнение всех операций компиляции до старта приложения, что снижает потребление ресурсов во время выполнения.
3️⃣ Использование нативного кода — AOT позволяет использовать преимущества более быстрого выполнения нативного кода вместо байт-кода.

📌 Как включить AOT Compilation?
1️⃣ Скомпилируйте класс с помощью javac в обычный байт-код.
2️⃣ Примените инструмент jaotc (Java AOT Compiler) для компиляции байт-кода в нативный код.
3️⃣ Запустите приложение с использованием скомпилированных AOT-артефактов.

📌 Пример использования AOT Compilation:

1. Компиляция классов с помощью javac:

javac MyApp.java


2. Генерация AOT-артефактов с помощью jaotc:

jaotc --output libMyApp.aot MyApp.class


3. Запуск приложения с AOT:

java -XX:AOTLibrary=libMyApp.aot -cp . MyApp


🔗 Особенности AOT Compilation:
1️⃣ AOT-компиляция доступна начиная с Java 9.
2️⃣ Используется для ускорения старта приложения, особенно для больших и сложных систем.
3️⃣ Не все Java-библиотеки могут быть компилированы с использованием AOT, особенно те, которые активно используют Reflection или динамическую загрузку классов.

💡 Совет: AOT лучше всего работает в приложениях, где известен весь набор классов и методов, которые будут использоваться. В случаях с динамическими зависимостями может быть ограничена эффективность.

#Java #AOTCompilation #Performance #Java9
👍91
⚡️ Оптимизация работы с большими коллекциями в Java

Работа с большими List и Map в Java может привести к высоким затратам памяти и снижению производительности. Как этого избежать?

Ошибка: использование ArrayList без задания начального размера

List<String> list = new ArrayList<>(); // По умолчанию – 10 элементов
for (int i = 0; i < 1000000; i++) {
list.add("data");
}


➡️ Решение: укажите размер сразу, если он известен

List<String> list = new ArrayList<>(1000000);


Ошибка: HashMap без настройки initialCapacity и loadFactor

По умолчанию HashMap перераспределяет бакеты при загрузке 75%, что может вызвать лишние перераспределения.

➡️ Решение: настройка параметров

Map<String, String> map = new HashMap<>(1000000, 0.9f);


Ошибка: использование LinkedList вместо ArrayList для поиска

List<String> list = new LinkedList<>();
list.get(5000); // O(n)


➡️ Решение: используйте ArrayList, если часто выполняете get()

💡 Совет: Профилируйте код с -XX:+PrintGCDetails и jcmd GC.heap_info, чтобы следить за лишними выделениями памяти.

#java #collections #performance
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19🔥52
Как избежать проблем с Parallel Stream?

Использование parallelStream() может замедлить программу, если не учитывать его особенности.

➡️ Проблемы:

🟢 Не стоит использовать с маленькими коллекциями – накладные расходы на потоки выше, чем выгода.
🟢 Будьте осторожны с изменяемыми переменными в forEach().

Ошибка: некорректное изменение общей переменной

int[] sum = {0};
list.parallelStream().forEach(i -> sum[0] += i); // Потенциальная ошибка!


📌 Решение: использовать reduce()

int sum = list.parallelStream().reduce(0, Integer::sum);


💡 Совет: parallelStream() эффективен, если объём данных большой и нет конкурентного доступа.

#java #parallelstream #performance
Please open Telegram to view this post
VIEW IN TELEGRAM
👍131
🔍 JVM Warm-up – почему Java работает медленно при старте?

➡️ Проблема:

JVM использует JIT-компилятор, но оптимизация занимает время. Это приводит к медленному запуску.

📌 Решение 1: предварительная компиляция (AOT, GraalVM)

jaotc --output=app.aot MyApp.class
java -XX:AOTLibrary=app.aot MyApp


📌 Решение 2: заранее прогревать код

for (int i = 0; i < 10000; i++) {
someMethod(); // Прогреваем JIT-компилятор
}


#java #jvm #performance
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥2❤‍🔥1👏1🤯1
🚀 ZGC vs G1GC – какой GC лучше?

В Java 17 появился ZGC – он обещает минимальную задержку. Но лучше ли он G1GC?

✔️ Сравнение:


+------+----------+-----------+----------+
| GC | Паузы | Поддержка | CPU |
| | | хипа | нагрузка |
+------+----------+-----------+----------+
| G1GC | До 200ms | До 16ТБ | Средняя |
| ZGC | <10ms | До 16ТБ | Низкая |
+------+----------+-----------+----------+


📌 Как включить?
-XX:+UseZGC


💡 Совет: ZGC идеально подходит для low-latency приложений, но G1GC лучше сбалансирован для большинства случаев.

#java #gc #performance
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15
⚡️ JSON в Java (Jackson vs Gson vs JSON-B)

Работа с JSON – частая задача, но Jackson, Gson и JSON-B работают по-разному. Какой выбрать?

⚙️ Скорость сериализации (от самого быстрого):

Jackson – самый быстрый (использует ByteBuffer).
Gson – медленнее, так как использует Reflection.
JSON-B – стандартный API, но проигрывает по производительности.

✔️ Пример с использованием Jackson:


ObjectMapper objectMapper = new ObjectMapper();

// Объект → JSON (сериализация)
Person person = new Person("Alice", 30);
String json = objectMapper.writeValueAsString(person);
System.out.println("Jackson Serialized: " + json);

// JSON → Объект (десериализация)
Person deserialized = objectMapper.readValue(json, Person.class);
System.out.println("Jackson Deserialized: " + deserialized.name + ", " + deserialized.age);


✔️ Пример с использованием Gson:


Gson gson = new Gson();

// Объект → JSON (сериализация)
Person person = new Person("Bob", 25);
String json = gson.toJson(person);
System.out.println("Gson Serialized: " + json);

// JSON → Объект (десериализация)
Person deserialized = gson.fromJson(json, Person.class);
System.out.println("Gson Deserialized: " + deserialized.name + ", " + deserialized.age);


✔️ Пример с использованием JSON-B:


Jsonb jsonb = JsonbBuilder.create();

// Объект → JSON (сериализация)
Person person = new Person("Charlie", 35);
String json = jsonb.toJson(person);
System.out.println("JSON-B Serialized: " + json);

// JSON → Объект (десериализация)
Person deserialized = jsonb.fromJson(json, Person.class);
System.out.println("JSON-B Deserialized: " + deserialized.name + ", " + deserialized.age);


💡 Совет: Используйте Jackson для high-performance API, но если важен стандарт – выбирайте JSON-B.

#java #json #jackson #performance
Please open Telegram to view this post
VIEW IN TELEGRAM
👍123🔥3🤔1
⚡️ Как ускорить работу HashMap?

HashMap – одна из самых эффективных структур, но её можно ещё ускорить.

✔️ 3 способа оптимизации:

🟢Задавайте начальный размер – по умолчанию HashMap увеличивается при заполнении на 75%, что может приводить к перераспределению. Укажите new HashMap<>(1000) для больших данных.
🟢Используйте computeIfAbsent() – сокращает проверку наличия ключа перед вставкой.
🟢Не используйте synchronized HashMap – вместо этого применяйте ConcurrentHashMap.

✔️ Пример:

Map<String, Integer> map = new HashMap<>(1000);
map.computeIfAbsent("key", k -> 42);


💡 Совет: Настраивайте HashMap под свои задачи, особенно если храните большие объёмы данных.

#java #hashmap #performance
Please open Telegram to view this post
VIEW IN TELEGRAM
👍191