Пример: установка времени модификации файла в текущий момент
Команда
Путь байтов в памяти JVM при работе с атрибутами
Чтение атрибутов: путь данных
При вызове
Объект
Выполняется системный вызов
JNI-код JVM копирует поля структуры из нативной памяти в объекты Java. Создаётся экземпляр внутреннего класса, реализующего
Поля объекта атрибутов содержат примитивы (
Объект
Если вы сохраняете атрибуты в долгоживущую коллекцию (например, строите карту
Запись атрибутов: путь данных
При
Объект
Выполняется системный вызов
Ядро ОС обновляет соответствующие поля в inode/MFT. Это операция только над метаданными; блоки данных файла не затрагиваются.
Никаких новых объектов в куче JVM не создаётся. Метод возвращает
POSIX-права: путь данных
При
Множество
JVM преобразует множество разрешений в целое число — битовую маску POSIX-прав. Эта маска передаётся в нативный код.
Выполняется системный вызов
Объект
ClassLoader — это компонент JVM, отвечающий за динамическую загрузку классов в память. Каждый загруженный класс хранится в Metaspace и связан с ClassLoader'ом. Когда ClassLoader становится недостижимым для GC, все его классы и связанные с ними структуры Metaspace могут быть освобождены.
Оптимизация: массовое чтение атрибутов и давление на GC
При сканировании больших файловых деревьев частая ошибка — хранение всех атрибутов в памяти:
Каждый объект
Оптимизированный подход — извлекать только нужные поля и не хранить объекты атрибутов:
Ещё лучше — использовать
#Java #для_новичков #beginner #IO #NIO #Files #BasicFileAttributes
import java.nio.file.*;
import java.nio.file.attribute.FileTime;
import java.io.IOException;
import java.time.Instant;
public class FileToucher {
public void touch(Path path) throws IOException {
if (Files.notExists(path)) {
// Если файла нет — создаём пустой файл
// и время модификации будет равно времени создания (сейчас)
Files.createFile(path);
System.out.println("Файл создан: " + path);
return;
}
// Файл существует — обновляем только время модификации
FileTime now = FileTime.from(Instant.now());
Files.setLastModifiedTime(path, now);
// Проверяем, что установилось
FileTime verify = Files.getLastModifiedTime(path);
if (verify.compareTo(now) >= 0) {
System.out.println("Время модификации обновлено: " + verify);
} else {
throw new IOException("Не удалось обновить время модификации");
}
}
public void touchWithAccessTime(Path path) throws IOException {
// Обновляем и время модификации, и время доступа
FileTime now = FileTime.from(Instant.now());
Files.setAttribute(path, "basic:lastModifiedTime", now);
Files.setAttribute(path, "basic:lastAccessTime", now);
// Проверяем через readAttributes
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
System.out.println("mtime: " + attrs.lastModifiedTime());
System.out.println("atime: " + attrs.lastAccessTime());
}
public static void main(String[] args) {
try {
Path file = Paths.get("/tmp/test_touch.txt");
new FileToucher().touch(file);
} catch (IOException e) {
System.err.println("Ошибка: " + e.getMessage());
}
}
}
Команда
touch в Unix работает именно так: если файла нет — создаёт пустой, если есть — обновляет временные метки. Важно, что Files.setLastModifiedTime() не изменяет содержимое файла, только метаданные inode.Путь байтов в памяти JVM при работе с атрибутами
Чтение атрибутов: путь данных
При вызове
Files.readAttributes(path, BasicFileAttributes.class):Объект
Path находится в куче (Heap). JVM извлекает его строковое представление и кодирует в массив байтов пути в нативной памяти через JNI.Выполняется системный вызов
stat() (POSIX) или GetFileAttributesEx() (Windows). Ядро ОС читает inode/MFT-запись и возвращает структуру с метаданными в нативную память ядра.JNI-код JVM копирует поля структуры из нативной памяти в объекты Java. Создаётся экземпляр внутреннего класса, реализующего
BasicFileAttributes (например, UnixFileAttributes в OpenJDK). Этот объект создаётся в Young Generation, в области Eden.Поля объекта атрибутов содержат примитивы (
long для размера, long для наносекунд времени) и объекты FileTime. Каждый вызов creationTime(), lastModifiedTime(), lastAccessTime() возвращает новый объект FileTime или кэшированный экземпляр — это зависит от реализации JVM. В OpenJDK FileTime создаётся лениво при первом вызове геттера и кэшируется в поле объекта атрибутов.Объект
BasicFileAttributes — лёгкий: он содержит несколько long-полей и ссылки на FileTime. Если вы читаете атрибуты в цикле (например, при сканировании директории из 100 000 файлов), каждая итерация создаёт новый объект атрибутов в Eden. Эти объекты становятся мусором сразу после обработки файла, если вы не сохраняете ссылку. Minor GC эффективно собирает их, так как они не переживают цикла.Если вы сохраняете атрибуты в долгоживущую коллекцию (например, строите карту
Map<Path, BasicFileAttributes> для всех файлов проекта), объекты атрибутов переходят в Old Generation через Survivor Space. При большом количестве файлов это может существенно увеличить размер Old Generation и вызвать Major GC (Full GC) раньше, чем ожидалось.Запись атрибутов: путь данных
При
Files.setLastModifiedTime(path, fileTime):Объект
FileTime хранит время как long в наносекундах (или секундах + наносекунды). Он находится в куче. JVM извлекает примитивное значение и передаёт его в нативный код.Выполняется системный вызов
utimensat() (современный POSIX, поддерживает наносекунды) или utime() (устаревший, точность до секунд). На Windows — SetFileTime().Ядро ОС обновляет соответствующие поля в inode/MFT. Это операция только над метаданными; блоки данных файла не затрагиваются.
Никаких новых объектов в куче JVM не создаётся. Метод возвращает
void. Объект FileTime, переданный как параметр, остаётся в куче до тех пор, пока на него есть ссылка. Если это локальная переменная — он собирается при следующей Minor GC.POSIX-права: путь данных
При
Files.setPosixFilePermissions(path, permissions):Множество
Set<PosixFilePermission> — это объект в куче, содержащий ссылки на enum-константы. Enum-константы в Java создаются один раз при загрузке класса и хранятся в Metaspace (вместе с классом PosixFilePermission). Само множество — это объект HashSet или EnumSet в куче.JVM преобразует множество разрешений в целое число — битовую маску POSIX-прав. Эта маска передаётся в нативный код.
Выполняется системный вызов
chmod() (POSIX) или SetFileSecurity() (Windows, если используется ACL-эмуляция). Ядро обновляет биты прав в inode.Объект
Set<PosixFilePermission> становится мусором после выхода из метода, если он не сохранён. Minor GC собирает его. Enum-константы остаются в Metaspace навсегда (до выгрузки класса), так как Metaspace не подлежит обычной сборке мусора в полном смысле — классы выгружаются только при выгрузке ClassLoader'а.ClassLoader — это компонент JVM, отвечающий за динамическую загрузку классов в память. Каждый загруженный класс хранится в Metaspace и связан с ClassLoader'ом. Когда ClassLoader становится недостижимым для GC, все его классы и связанные с ними структуры Metaspace могут быть освобождены.
Оптимизация: массовое чтение атрибутов и давление на GC
При сканировании больших файловых деревьев частая ошибка — хранение всех атрибутов в памяти:
// Проблемный код: храним все атрибуты в памяти
Map<Path, BasicFileAttributes> cache = new HashMap<>();
Files.walk(root).forEach(p -> {
try {
cache.put(p, Files.readAttributes(p, BasicFileAttributes.class));
} catch (IOException e) { /* ignore */ }
});
// При миллионе файлов cache содержит миллион объектов BasicFileAttributes в Old Generation
Каждый объект
BasicFileAttributes в OpenJDK занимает примерно 40–56 байт (зависит от архитектуры и JVM). Для миллиона файлов это 40–56 МБ только на объекты атрибутов, плюс накладные расходы HashMap (примерно в 2 раза больше). Это может привести к Major GC или OOM.Оптимизированный подход — извлекать только нужные поля и не хранить объекты атрибутов:
// Оптимизированный код: извлекаем только размер и mtime, храним примитивы
Map<Path, Long> sizeCache = new HashMap<>();
Files.walk(root).forEach(p -> {
try {
BasicFileAttributes attrs = Files.readAttributes(p, BasicFileAttributes.class);
sizeCache.put(p, attrs.size()); // только long, лёгкий объект
} catch (IOException e) { /* ignore */ }
});
// Объект attrs становится мусором сразу после итерации
Ещё лучше — использовать
Files.newDirectoryStream() и читать атрибуты порциями, не загружая всё дерево в память:// Обход с минимальным потреблением памяти
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
for (Path entry : stream) {
BasicFileAttributes attrs = Files.readAttributes(entry, BasicFileAttributes.class);
process(entry, attrs.size(), attrs.lastModifiedTime());
// attrs собирается GC сразу после process()
}
}
#Java #для_новичков #beginner #IO #NIO #Files #BasicFileAttributes
👍3
Что выведет код?
#Tasks
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.io.*;
public class Task170726 {
public static void main(String[] args) throws IOException, InterruptedException {
Path path = Paths.get("test.txt");
Files.write(path, "ABC".getBytes());
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
long size1 = attrs.size();
long modified1 = attrs.lastModifiedTime().toMillis();
Thread.sleep(2000);
Files.write(path, "ABCDE".getBytes(), StandardOpenOption.TRUNCATE_EXISTING);
long size2 = attrs.size();
long modified2 = attrs.lastModifiedTime().toMillis();
BasicFileAttributes attrsNew = Files.readAttributes(path, BasicFileAttributes.class);
long size3 = attrsNew.size();
long modified3 = attrsNew.lastModifiedTime().toMillis();
System.out.println(size1 + " " + size2 + " " + size3);
System.out.println(modified1 == modified2);
System.out.println(modified1 == modified3);
}
}
#Tasks
👍2
Варианты ответа:
Anonymous Quiz
29%
3 5 5 true false
14%
3 3 5 false false
43%
3 3 5 true false
14%
3 3 5 true true
👍2
Ребят, есть предложение! 😉
А давайте как в старые-добрые встретимся в воскресение часиков с 16 по мск и посидим, поговорим?
Предлагайте темы и вопросы которые можем обсудить.
Можем просто провести нытинг)
Старичкам канала быть обязательно! 😏
Придёте? 🚘
А давайте как в старые-добрые встретимся в воскресение часиков с 16 по мск и посидим, поговорим?
Предлагайте темы и вопросы которые можем обсудить.
Можем просто провести нытинг)
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6👎1🤣1
Что такое 🤓
Ответ:
StackWalker (Java 9) — это эффективный API для обхода стека вызовов.
Предоставляет метод walk(Function<Stream<StackFrame>, T>) для получения стрима кадров стека.
Более производительный, чем Thread.getStackTrace(), так как не создаёт массив всех кадров, а лениво обходит только нужные.
Позволяет фильтровать, пропускать и т.д. Полезен для логирования, отладки, безопасности (проверка, кто вызывает метод). Поддерживает режимы: RETAIN_CLASS_REFERENCE для работы с классами.
#собеседование
StackWalker в Java 9? Ответ:
Предоставляет метод walk(Function<Stream<StackFrame>, T>) для получения стрима кадров стека.
Более производительный, чем Thread.getStackTrace(), так как не создаёт массив всех кадров, а лениво обходит только нужные.
Позволяет фильтровать, пропускать и т.д. Полезен для логирования, отладки, безопасности (проверка, кто вызывает метод). Поддерживает режимы: RETAIN_CLASS_REFERENCE для работы с классами.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
https://habr.com/ru/articles/1060204/
Статья для размышлений за завтраком. И одна из тем которые я предлагаю завтра обсудить
Статья для размышлений за завтраком. И одна из тем которые я предлагаю завтра обсудить
Хабр
А нам точно нужны code agents?
Предисловие На написание данной статьи меня побудило несколько факторов: Проблемы со сгенерированным кодом при работе в команде. Возросшая когнитивная нагрузка. Активное (насильное) внедрение со...
👍4
История технологии сегодня — 18 июля
ℹ️ Кто родился в этот день
Ро́алд Хо́ффман (англ. Roald Hoffmann; род. 18 июля 1937 года, Золочев, Тарнопольское воеводство, Польша) — американский химик, лауреат Нобелевской премии по химии «за разработку теории протекания химических реакций» совместно с Кэнъити Фукуи.
Ха́ртмут Ми́хель (нем. Hartmut Michel; род. 18 июля 1948 года, Людвигсбург, Германия) — немецкий биохимик, лауреат Нобелевской премии по химии 1988 года за точную структуру бактериального реакционного фотосинтетического центра.
🌐 Знаковые события
1898 — Пьер и Мария Кюри представили в Парижской Академии доклад об открытии нового химического элемента — полония — второго после урана, обладающего радиоактивностью.
1968 — образована компания «Intel». Её основали Роберт Нойс и Гордон Мур.
1991 — Вышел первый номер компьютерного еженедельника «ComputerWorld — USSR», который известен под названием «Computer Weekly».
2011 — запуск космической обсерватории «Радиоастрон».
#Biography #Birth_Date #Events #18июля
Ро́алд Хо́ффман (англ. Roald Hoffmann; род. 18 июля 1937 года, Золочев, Тарнопольское воеводство, Польша) — американский химик, лауреат Нобелевской премии по химии «за разработку теории протекания химических реакций» совместно с Кэнъити Фукуи.
Ха́ртмут Ми́хель (нем. Hartmut Michel; род. 18 июля 1948 года, Людвигсбург, Германия) — немецкий биохимик, лауреат Нобелевской премии по химии 1988 года за точную структуру бактериального реакционного фотосинтетического центра.
1898 — Пьер и Мария Кюри представили в Парижской Академии доклад об открытии нового химического элемента — полония — второго после урана, обладающего радиоактивностью.
1968 — образована компания «Intel». Её основали Роберт Нойс и Гордон Мур.
1991 — Вышел первый номер компьютерного еженедельника «ComputerWorld — USSR», который известен под названием «Computer Weekly».
2011 — запуск космической обсерватории «Радиоастрон».
#Biography #Birth_Date #Events #18июля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Скоро релиз))
Если я когда нибудь победю Angular)))
Как вам? (это еще не доработанная версия)
Если я когда нибудь победю Angular)))
Как вам? (это еще не доработанная версия)
🔥11
История технологии сегодня — 19 июля
ℹ️ Кто родился в этот день
Сэмюэл Кольт (Самуи́л Кольт, англ. Samuel Colt; 22 июля 1814, Хартфорд — 10 января 1862, Хартфорд) — американский оружейник, изобретатель и промышленник, основатель компании Colt’s Patent Fire-Arms Manufacturing Company (сейчас Colt’s Manufacturing Company). Происходил из аристократической и достаточно богатой семьи, но независимо от этого основал компанию сам. Наибольшей известностью пользуется как реформатор револьверного оружия: в 1835 году изобрёл капсульный револьвер, который быстро потеснил другие системы и дал толчок для создания револьверов под унитарный металлический патрон.
🌐 Знаковые события
1927 — В Ленинграде испытан первый отечественный аэроглиссер.
#Biography #Birth_Date #Events #19июля
Сэмюэл Кольт (Самуи́л Кольт, англ. Samuel Colt; 22 июля 1814, Хартфорд — 10 января 1862, Хартфорд) — американский оружейник, изобретатель и промышленник, основатель компании Colt’s Patent Fire-Arms Manufacturing Company (сейчас Colt’s Manufacturing Company). Происходил из аристократической и достаточно богатой семьи, но независимо от этого основал компанию сам. Наибольшей известностью пользуется как реформатор револьверного оружия: в 1835 году изобрёл капсульный револьвер, который быстро потеснил другие системы и дал толчок для создания револьверов под унитарный металлический патрон.
1927 — В Ленинграде испытан первый отечественный аэроглиссер.
#Biography #Birth_Date #Events #19июля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10
Please open Telegram to view this post
VIEW IN TELEGRAM
🤓2
История технологии сегодня — 20 июля
ℹ️ Кто родился в этот день
Григо́рий Васи́льевич Кисунько́ (укр. Григорій Васильович Кісунько; 20 июля 1918, Бельманка, Екатеринославская губерния — 11 октября 1998, Москва) — советский учёный в области радиоэлектроники. Один из создателей советской системы противоракетной обороны.
Герд Карл Би́нниг (нем. Gerd Karl Binnig; род. 20 июля 1947) — немецкий физик, в 1986 году совместно с Генрихом Рорером получил Нобелевскую премию по физике за изобретение сканирующего туннельного микроскопа. Разработки Биннига расширили возможности нанотехнологий, позволив не только визуализировать отдельные атомы, но и манипулировать ими.
Гео́ргий Э́рихович Лангема́к (8 (20) июля 1898, Старобельск, Старобельский уезд, Харьковская губерния, Российская империя — 11 января 1938, Москва, РСФСР, СССР) — российский и советский учёный, один из пионеров ракетной техники и один из создателей первых реактивных снарядов в СССР. Основоположник исследований по конструированию реактивных снарядов на бездымном порохе, открыл так называемый закон подобия, знание которого позволило определять оптимальную геометрию сопла реактивного двигателя без длительных дорогостоящих экспериментов — аналитическим расчётом. Ввёл в русский язык термин «космонавтика».
🌐 Знаковые события
1807 — Нисефор Ньепс с братом получили патент на один из ранних двигателей внутреннего сгорания: пиреолофор[англ.].
1969 — «Аполлон-11» совершил первую в истории пилотируемую посадку на Луну.
#Biography #Birth_Date #Events #20июля
Григо́рий Васи́льевич Кисунько́ (укр. Григорій Васильович Кісунько; 20 июля 1918, Бельманка, Екатеринославская губерния — 11 октября 1998, Москва) — советский учёный в области радиоэлектроники. Один из создателей советской системы противоракетной обороны.
Герд Карл Би́нниг (нем. Gerd Karl Binnig; род. 20 июля 1947) — немецкий физик, в 1986 году совместно с Генрихом Рорером получил Нобелевскую премию по физике за изобретение сканирующего туннельного микроскопа. Разработки Биннига расширили возможности нанотехнологий, позволив не только визуализировать отдельные атомы, но и манипулировать ими.
Гео́ргий Э́рихович Лангема́к (8 (20) июля 1898, Старобельск, Старобельский уезд, Харьковская губерния, Российская империя — 11 января 1938, Москва, РСФСР, СССР) — российский и советский учёный, один из пионеров ракетной техники и один из создателей первых реактивных снарядов в СССР. Основоположник исследований по конструированию реактивных снарядов на бездымном порохе, открыл так называемый закон подобия, знание которого позволило определять оптимальную геометрию сопла реактивного двигателя без длительных дорогостоящих экспериментов — аналитическим расчётом. Ввёл в русский язык термин «космонавтика».
1807 — Нисефор Ньепс с братом получили патент на один из ранних двигателей внутреннего сгорания: пиреолофор[англ.].
1969 — «Аполлон-11» совершил первую в истории пилотируемую посадку на Луну.
#Biography #Birth_Date #Events #20июля
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
Please open Telegram to view this post
VIEW IN TELEGRAM
[Совет по Java #062]
Тема:
Проблема: Метод
Это приводит к тому, что разделяемые объекты остаются в частично обновлённом состоянии, а другие потоки, захватившие освобождённые мониторы, могут читать несогласованные данные. Остановка потока в произвольный момент нарушает инварианты объектов, и восстановить состояние системы становится невозможно. Метод был объявлен устаревшим (deprecated) ещё в Java 1.2 и никогда не должен использоваться в production-коде.
Решение: Вместо принудительной остановки используйте кооперативный механизм прерывания. Вызовите
Целевой поток должен периодически проверять статус прерывания с помощью
Дополнительно можно использовать
Объяснение: При вызове
Все мониторы, захваченные этим потоком, принудительно освобождаются, что позволяет другим потокам войти в критическую секцию до того, как изменения были завершены.
Это нарушает атомарность и может привести к трудноотлавливаемым повреждениям данных.
#Java #советы
Тема:
Thread.stop() устарел и опасен (разблокирует все мониторы, оставляя данные в несогласованном состоянии).Проблема: Метод
Thread.stop() принудительно завершает поток, выбрасывая ThreadDeath в целевом потоке. При этом освобождаются все блокировки, которые поток удерживал, но изменения, сделанные в критической секции, не откатываются. Это приводит к тому, что разделяемые объекты остаются в частично обновлённом состоянии, а другие потоки, захватившие освобождённые мониторы, могут читать несогласованные данные. Остановка потока в произвольный момент нарушает инварианты объектов, и восстановить состояние системы становится невозможно. Метод был объявлен устаревшим (deprecated) ещё в Java 1.2 и никогда не должен использоваться в production-коде.
Решение: Вместо принудительной остановки используйте кооперативный механизм прерывания. Вызовите
Thread.interrupt() на потоке, который нужно завершить. Целевой поток должен периодически проверять статус прерывания с помощью
Thread.interrupted() или Thread.currentThread().isInterrupted() и завершать свою работу корректно, освобождая ресурсы и приводя данные в согласованное состояние. Для блокирующих операций (например, wait(), sleep()) прерывание выбрасывает InterruptedException, которое следует обработать, прервав выполнение. Дополнительно можно использовать
volatile boolean флаг для сигнализации завершения, но прерывание является стандартным и более интегрированным с JDK.public class ThreadStopExample {
//Антипаттерн: Thread.stop()
public static void badStop() throws InterruptedException {
Thread t = new Thread(() -> {
while (true) {
System.out.println("Работаю...");
// Если здесь stop() будет вызван, данные могут быть повреждены
}
});
t.start();
Thread.sleep(100);
t.stop(); // Опасно! Освобождает мониторы, оставляя объекты в мусорном состоянии
}
//Правильно: кооперативное завершение через прерывание
public static void goodInterrupt() throws InterruptedException {
Thread t = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("Безопасная работа...");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// Восстанавливаем статус прерывания и выходим
Thread.currentThread().interrupt();
break;
}
}
System.out.println("Поток корректно завершён");
});
t.start();
Thread.sleep(2000);
t.interrupt(); // Сигнал остановки
t.join();
}
// Альтернатива: volatile флаг
private volatile boolean running = true;
public void safeWithFlag() throws InterruptedException {
Thread t = new Thread(() -> {
while (running) {
System.out.println("Работа с флагом...");
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// При прерывании тоже можем выйти
Thread.currentThread().interrupt();
break;
}
}
});
t.start();
Thread.sleep(1000);
running = false; // Сигнал остановки
t.interrupt(); // Дополнительно для прерывания блокировок
t.join();
}
public static void main(String[] args) throws InterruptedException {
// badStop(); // Не запускайте!
goodInterrupt();
}
}Объяснение: При вызове
stop() JVM немедленно завершает поток, не давая ему возможности завершить текущую операцию. Все мониторы, захваченные этим потоком, принудительно освобождаются, что позволяет другим потокам войти в критическую секцию до того, как изменения были завершены.
Это нарушает атомарность и может привести к трудноотлавливаемым повреждениям данных.
interrupt() лишь устанавливает флаг прерывания, не вмешиваясь в выполнение. Поток сам решает, когда и как реагировать на этот сигнал, что позволяет ему корректно завершить работу. Блокирующие методы (например, sleep(), wait(), join(), BlockingQueue.put()) проверяют статус прерывания и выбрасывают InterruptedException, обеспечивая немедленную реакцию на сигнал. В коде с интенсивными вычислениями необходимо явно проверять isInterrupted() в цикле.#Java #советы
👍5