Java for Beginner
871 subscribers
1.01K photos
275 videos
14 files
1.68K links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Привет)

Ничего нового, просто хотел выразить свою благодарность той паре-тройке человек, которые ставят лайки на каждом посте в канале. 🙏

Вы лучшие, спасибо! ❤️
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15
История технологии сегодня — 16 июля

ℹ️ Кто родился в этот день

Бори́с Васи́льевич Бу́нкин (1922—2007) — советский и российский учёный, конструктор и организатор производства зенитных ракетных комплексов для ПВО. С 1968 по 1998 год — генеральный конструктор предприятия НПО «Алмаз», осуществляющего разработку и серийное производство зенитных ракетных комплексов, составляющих основу вооружения отечественных войск ПВОС-75С-125С-300С-400.

Фриц Цернике (нид. Frits Zernike; 16 июля 1888 — 10 марта 1966)голландский физик, лауреат Нобелевской премии по физике 1953 года «За обоснование фазово-контрастного метода, особенно за изобретение фазово-контрастного микроскопа».


🌐 Знаковые события

1867 — Француз Жозеф Монье, бывший садовник, получил патент на армированный бетон, ставший главным материалом при возведении высотных зданий.

1969 — с космодрома на мысе Канаверал стартовала РН «Сатурн-V» с космическим кораблём «Аполлон-11». Через несколько дней посадочный модуль «Орёл» совершит первую пилотируемую посадку на Луну.

1993 — в Лондоне прошла презентация Amiga CD32 — первой 32-битной игровой консоли, использующей CD-ROM.

2000 — принято решение об увеличении числа доменов Интернета.


#Biography #Birth_Date #Events #16июля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
[Совет по Java #061]

Тема: Thread.yield() — подсказка планировщику, но может быть проигнорирована. Не используйте для синхронизации.

Проблема: Метод Thread.yield() призван сигнализировать планировщику потоков, что текущий поток готов уступить процессорное время другим потокам.

Однако это всего лишь подсказка (hint) для JVM и операционной системы. Планировщик может проигнорировать её, особенно в средах с вытесняющей многозадачностью, где решение о переключении принимается системой.

Некоторые разработчики используют yield() в циклах ожидания (busy-wait) для "уменьшения нагрузки" на процессор, полагая, что это предотвратит зависание. Это ошибочная практика: она не гарантирует прогресс, не обеспечивает взаимное исключение и не защищает от гонок данных. Более того, в многопроцессорных системах вызов yield() может вообще не изменить поведение, так как другие потоки могут выполняться на других ядрах.

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

Решение: Для координации потоков используйте механизмы синхронизации из java.util.concurrent или встроенные synchronizedwait()/notify().

Если нужно временно освободить процессор, применяйте Thread.sleep(1) с минимальной задержкой — это более предсказуемый способ, хотя тоже не идеален.

Для реализации эффективного ожидания используйте LockSupport.park() или Condition.await(). Для уступки в вычислительных циклах с интенсивным использованием CPU можно использовать yield() в исключительных случаях, но только после тщательного анализа и с чётким пониманием, что это не влияет на корректность.

В подавляющем большинстве сценариев yield() не нужен, а его использование свидетельствует о попытке "замаскировать" проблемы синхронизации.
public class ThreadYield {
private boolean flag = false;

//Антипаттерн: yield() в цикле ожидания
public void badWait() {
while (!flag) {
Thread.yield(); // Плохо: может никогда не сработать, а если сработает, то не факт
}
// Действие после флага
}

//Правильно: использование Lock или wait/notify
private final Object lock = new Object();

public void goodWait() throws InterruptedException {
synchronized (lock) {
while (!flag) {
lock.wait(); // Блокируется до уведомления
}
}
}

public void setFlagTrue() {
synchronized (lock) {
flag = true;
lock.notifyAll();
}
}
}


Объяснение:
 Спецификация Java не даёт никаких гарантий относительно того, что yield() действительно вызовет переключение контекста.

Разные реализации JVM и операционные системы трактуют его по-разному: на Windows это обычно приводит к немедленному переключению, на Linux может быть проигнорировано.

Полагаться на него для синхронизации — значит внести в код фактор случайности. Правильные механизмы (wait/notify, Lock, Semaphore, CountDownLatch) обеспечивают детерминированное освобождение ресурсов и гарантируют, что поток будет возобновлён только когда условие действительно выполнено.

Даже Thread.sleep(0) часто работает аналогично yield(), но тоже не рекомендуется.


#Java #советы
👍6
Потом удивляемся почему нет рабочих мест для погромистов. Грууусть...
🗿5🤓2
Что выведет код?

public class Task160726 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.print("A");
Thread.yield();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.print("B");
Thread.yield();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}


#Tasks
👍3
Что такое ProcessHandle в Java 9? 🤓

Ответ:

ProcessHandle (Java 9)
— это улучшенный API для управления процессами ОС из Java.

Позволяет получить дескриптор текущего процесса (ProcessHandle.current()), получить PID, родительский процесс, дочерние процессы, а также завершить процесс (destroy(), destroyForcibly()).

Можно также подписаться на завершение процесса через onExit(), возвращающее CompletableFuture<ProcessHandle>. Это улучшение по сравнению с устаревшим Runtime.exec() и Process позволяет более удобно управлять внешними процессами.



#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
История технологии сегодня — 17 июля

ℹ️ Кто родился в этот день

Серге́й Константи́нович Годуно́в (17 июля 1929, Москва — 15 июля 2023, Новосибирск) — советский и российский учёный в области математики и механикиакадемик РАН (1994; член-корреспондент АН СССР с 1976). Работы по теории обыкновенных дифференциальных уравненийуравнений в частных производныхвычислительной математикемеханике сплошных средлинейной алгебре.

Гордон Гулд (17 июля 1920, Манхэттен, Нью-Йорк — 16 сентября 2005, Манхэттен, Нью-Йорк) — американский физик, которому широко приписывается изобретение лазера. Гулд первым предложил использовать термин лазер (англ. laser), представляющий собой акроним от английского Light Amplification by Stimulated Emission of Radiation, что в переводе означает усиление света посредством вынужденного излучения.

Жорж Леме́тр (полное имя — Жорж Анри́ Жозе́ф Эдуа́р Леме́тр, фр. Georges Henri Joseph Édouard Lemaître); 17 июля 1894, Шарлеруа, Эно — 20 июня 1966, Лёвен, Брабант) — бельгийский священникастрофизиккосмолог и математик, автор теории Большого взрыва. Один из наиболее влиятельных астрофизиков XX века.


🌐 Знаковые события

1975 — состоялась стыковка космических кораблей «Союз» (СССР) и «Аполлон» (США).


#Biography #Birth_Date #Events #17июля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Раздел 11. Работа с файлами, I/O и сетью (NIO.2)

Глава 2. Современный NIO.2 (java.nio.file)

Атрибуты файлов — BasicFileAttributes

Каждый файл или директория в файловой системе хранит не только данные, но и метаданные — информацию о самом файле. Эти метаданные называются атрибутами файла и включают размер, временные метки (когда файл создан, изменён или к нему обращались), тип файла (обычный файл, директория, символическая ссылка) и права доступа. В Java NIO.2 работа с атрибутами вынесена в отдельную иерархию интерфейсов, корнем которой является BasicFileAttributes.

Метаданные — это данные о данных. В контексте файловой системы это не содержимое файла, а его характеристики: размер, время создания, права доступа, владелец и т.д.

Интерфейс BasicFileAttributes (пакет java.nio.file.attribute) предоставляет базовый набор атрибутов, общий для всех поддерживаемых JVM файловых систем. Для платформоспецифичных атрибутов существуют расширения: PosixFileAttributes (Unix/Linux/macOS) и DosFileAttributes (Windows). Эта архитектура следует принципу ISP (Interface Segregation Principle, принцип разделения интерфейса): общий интерфейс содержит только универсальные атрибуты, а специфичные вынесены в подинтерфейсы.


Что такое атрибуты файла

Атрибуты файла делятся на несколько категорий:
Базовые атрибуты (BasicFileAttributes) — доступны на всех платформах:
Размер файла (size) — число байтов, занимаемых файлом. Для директорий это платформозависимо и обычно равно размеру записей директории, а не сумме размеров файлов внутри.
Время создания (creationTime) — момент первого создания файла. На некоторых файловых системах может не поддерживаться или совпадать с временем модификации.
Время последней модификации (lastModifiedTime) — момент последнего изменения содержимого файла.
Время последнего доступа (lastAccessTime) — момент последнего чтения файла или выполнения stat().
Тип файла — флаги isDirectory(), isRegularFile(), isSymbolicLink(), isOther().

POSIX-атрибуты (PosixFileAttributes) — специфичны для Unix-подобных систем:
Владелец (owner) — пользователь, владеющий файлом.
Группа (group) — группа пользователей, ассоциированная с файлом.
Права доступа (permissions) — набор битов rwx для владельца, группы и остальных.

DOS-атрибуты (DosFileAttributes) — специфичны для Windows:
Read-only — файл доступен только для чтения.
Hidden — скрытый файл.
System — системный файл.
Archive — флаг архивации.

Временные метки в NIO.2 представлены классом FileTime, а не устаревшим java.util.Date или long. FileTime хранит время с точностью до наносекунд и предоставляет удобные методы конвертации.

Наносекунда — единица времени, равная одной миллиардной доле секунды (10^-9 с). Современные файловые системы (ext4, NTFS, APFS) хранят временные метки с наносекундной точностью, поэтому FileTime поддерживает эту гранулярность, в отличие от Date, который ограничен миллисекундами.


Чтение атрибутов: Files.readAttributes()

Files.readAttributes(Path, Class<A>
Этот метод — основной способ чтения атрибутов файла. Он принимает путь, класс интерфейса атрибутов и опции следования по символическим ссылкам. Возвращает объект, реализующий запрошенный интерфейс.
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.io.IOException;

public class AttributesReader {

public void printBasicAttributes(Path path) throws IOException {
// Читаем базовые атрибуты
// LinkOption.NOFOLLOW_LINKS — читаем атрибуты самой ссылки, а не цели
BasicFileAttributes attrs = Files.readAttributes(
path,
BasicFileAttributes.class,
LinkOption.NOFOLLOW_LINKS
);

System.out.println("Файл: " + path.getFileName());
System.out.println("Размер: " + attrs.size() + " байт");
System.out.println("Создан: " + attrs.creationTime());
System.out.println("Изменён: " + attrs.lastModifiedTime());
System.out.println("Доступ: " + attrs.lastAccessTime());
System.out.println("Директория: " + attrs.isDirectory());
System.out.println("Обычный файл: " + attrs.isRegularFile());
System.out.println("Символическая ссылка: " + attrs.isSymbolicLink());
}
}

Метод readAttributes() выполняет один системный вызов stat() (POSIX) или GetFileAttributesEx() (Windows), который возвращает структуру со всеми базовыми метаданными. Это эффективнее, чем вызывать отдельные методы Files.size(), Files.isDirectory(), Files.getLastModifiedTime() — каждый из которых выполняет свой системный вызов.

Системный вызов stat() — это вызов ядра Unix, который возвращает структуру stat с полной информацией о файле: inode, размер, права, временные метки, количество ссылок. Аналог на Windows — GetFileAttributesEx().

Различия между readAttributes() и отдельными методами Files
// Неэффективно: три системных вызова
long size = Files.size(path);
boolean isDir = Files.isDirectory(path);
FileTime modified = Files.getLastModifiedTime(path);

// Эффективно: один системный вызов
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
long size = attrs.size();
boolean isDir = attrs.isDirectory();
FileTime modified = attrs.lastModifiedTime();

При интенсивной работе с файловой системой (например, сканирование дерева из миллиона файлов) использование readAttributes() снижает нагрузку на систему в 3–5 раз по сравнению с отдельными вызовами.


#Java #для_новичков #beginner #IO #NIO #Files #BasicFileAttributes
👍4
Методы интерфейса BasicFileAttributes

size()
Возвращает размер файла в байтах как long. Для обычных файлов это точное количество байтов данных. Для директорий значение платформозависимо: на Unix это размер блока данных директории (список записей), а не рекурсивный размер содержимого.
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
long fileSize = attrs.size();


creationTime()

Возвращает FileTime — момент создания файла. На файловых системах, не поддерживающих время создания (например, старые версии ext2), может возвращать lastModifiedTime() как fallback. На Windows NTFS это точное время создания записи MFT.

MFT (Master File Table) — это центральная структура данных файловой системы NTFS, содержащая записи обо всех файлах и директориях тома. Каждая запись MFT хранит метаданные файла, включая временные метки.

lastModifiedTime()
Возвращает FileTime — момент последнего изменения содержимого файла. Это время обновляется при записи в файл, усечении (truncate), изменении прав доступа (на некоторых ФС) и других операциях, модифицирующих inode.

lastAccessTime()
Возвращает FileTime — момент последнего обращения к файлу. Важно: на многих Linux-системах по умолчанию atime (access time) обновляется отложенно (relatime) или вообще не обновляется (noatime) для снижения нагрузки на диск. Поэтому это поле может быть неточным или совпадать с lastModifiedTime().

relatime (relative atime) — режим обновления времени доступа в Linux, при котором atime обновляется только если оно старше mtime, или прошло более 24 часов с последнего обновления. Это компромисс между функциональностью и производительностью.

isDirectory(), isRegularFile(), isSymbolicLink(), isOther()


Эти методы определяют тип файловой сущности:
isDirectory() — директория (содержит записи других файлов).
isRegularFile() — обычный файл с данными.
isSymbolicLink() — символическая ссылка.
isOther() — всё остальное: именованные каналы (named pipes), сокеты домена Unix, блочные и символьные устройства.

Именованный канал (named pipe, FIFO) — это механизм межпроцессного взаимодействия в Unix, представленный как файл в файловой системе. Процессы пишут в один конец канала и читают из другого.

Сокет домена Unix (Unix domain socket) — механизм межпроцессного взаимодействия в пределах одной машины, более быстрый, чем TCP-сокеты, так как не использует сетевой стек.
Важно: эти методы не требуют отдельных системных вызовов, так как тип файла уже известен из структуры, возвращённой stat().


fileKey()

Возвращает объект, уникально идентифицирующий файл в файловой системе. На Unix это обычно пара (device_id, inode_number). На Windows — идентификатор файла NTFS. Может вернуть null, если файловая система не поддерживает уникальную идентификацию.
Object key = attrs.fileKey();
if (key != null) {
System.out.println("Уникальный ключ файла: " + key);
}

fileKey() полезен для обнаружения жёстких ссылок (hard links): два разных пути с одинаковым fileKey() указывают на один inode и, следовательно, на одни и те же данные.

Жёсткая ссылка (hard link) — это дополнительное имя для существующего файла в файловой системе. Все жёсткие ссылки на файл имеют один inode и разделяют данные. Удаление одной ссылки уменьшает счётчик ссылок; файл удаляется физически только когда счётчик достигает нуля.

Пример: вывод всех атрибутов для файла
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

public class FullAttributesReporter {

public void report(Path path) throws IOException {
// Определяем, какой тип атрибутов запрашивать
// Сначала пробуем POSIX (Unix/Linux/macOS)
if (FileSystems.getDefault().supportedFileAttributeViews().contains("posix")) {
reportPosixAttributes(path);
} else if (FileSystems.getDefault().supportedFileAttributeViews().contains("dos")) {
reportDosAttributes(path);
} else {
reportBasicAttributes(path);
}
}

private void reportBasicAttributes(Path path) throws IOException {
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);

System.out.println("=== Базовые атрибуты ===");
System.out.println("Путь: " + path.toAbsolutePath());
System.out.println("Размер: " + formatSize(attrs.size()));
System.out.println("Создан: " + formatTime(attrs.creationTime()));
System.out.println("Изменён: " + formatTime(attrs.lastModifiedTime()));
System.out.println("Доступ: " + formatTime(attrs.lastAccessTime()));
System.out.println("Тип: " + resolveType(attrs));
System.out.println("Уникальный ключ: " + attrs.fileKey());
}

private void reportPosixAttributes(Path path) throws IOException {
PosixFileAttributes attrs = Files.readAttributes(path, PosixFileAttributes.class);

reportBasicAttributes(path); // POSIX extends Basic

System.out.println("=== POSIX-атрибуты ===");
System.out.println("Владелец: " + attrs.owner().getName());
System.out.println("Группа: " + attrs.group().getName());
System.out.println("Права: " + PosixFilePermissions.toString(attrs.permissions()));
}

private void reportDosAttributes(Path path) throws IOException {
DosFileAttributes attrs = Files.readAttributes(path, DosFileAttributes.class);

reportBasicAttributes(path); // DOS extends Basic

System.out.println("=== DOS-атрибуты ===");
System.out.println("Только чтение: " + attrs.isReadOnly());
System.out.println("Скрытый: " + attrs.isHidden());
System.out.println("Системный: " + attrs.isSystem());
System.out.println("Архивный: " + attrs.isArchive());
}

private String formatSize(long bytes) {
if (bytes < 1024) return bytes + " B";
if (bytes < 1024 * 1024) return String.format("%.2f KB", bytes / 1024.0);
if (bytes < 1024L * 1024 * 1024) return String.format("%.2f MB", bytes / (1024.0 * 1024));
return String.format("%.2f GB", bytes / (1024.0 * 1024 * 1024));
}

private String formatTime(FileTime time) {
// FileTime.toInstant() возвращает Instant — точку на временной шкале
return time.toInstant().toString();
}

private String resolveType(BasicFileAttributes attrs) {
if (attrs.isDirectory()) return "директория";
if (attrs.isRegularFile()) return "обычный файл";
if (attrs.isSymbolicLink()) return "символическая ссылка";
return "другое";
}

public static void main(String[] args) {
try {
new FullAttributesReporter().report(Paths.get("/etc/passwd"));
} catch (IOException e) {
System.err.println("Ошибка чтения атрибутов: " + e.getMessage());
}
}
}

В этом примере FileSystems.getDefault().supportedFileAttributeViews() возвращает множество строк — названий поддерживаемых представлений атрибутов. Проверка "posix" позволяет адаптировать код к текущей ОС без жёсткой привязки к классам.

Представление атрибутов (file attribute view) — это интерфейс, определяющий набор операций чтения/записи для конкретного типа атрибутов. PosixFileAttributeView, DosFileAttributeView, AclFileAttributeView — примеры таких представлений. Каждое представление ассоциировано с именем-строкой ("posix", "dos", "acl").


#Java #для_новичков #beginner #IO #NIO #Files #BasicFileAttributes
👍3
Изменение времени модификации: Files.setLastModifiedTime()

Метод Files.setLastModifiedTime(Path path, FileTime time) устанавливает время последней модификации файла. Это полезно для инструментов, которые копируют файлы и хотят сохранить оригинальные временные метки, или для тестов, которым нужно симулировать старый файл.
import java.nio.file.*;
import java.nio.file.attribute.FileTime;
import java.io.IOException;
import java.time.Instant;

public class ModificationTimeSetter {

public void touchFile(Path path) throws IOException {
// "Touch" — обновить время модификации до текущего момента
FileTime now = FileTime.from(Instant.now());
Files.setLastModifiedTime(path, now);
}

public void setSpecificTime(Path path, Instant instant) throws IOException {
FileTime fileTime = FileTime.from(instant);
Files.setLastModifiedTime(path, fileTime);
}

public void copyTimestamps(Path source, Path target) throws IOException {
// Копируем временные метки с источника на назначение
BasicFileAttributes sourceAttrs = Files.readAttributes(
source, BasicFileAttributes.class
);

Files.setLastModifiedTime(target, sourceAttrs.lastModifiedTime());

// Время создания и доступа устанавливаются через setAttribute
Files.setAttribute(target, "basic:creationTime", sourceAttrs.creationTime());
Files.setAttribute(target, "basic:lastAccessTime", sourceAttrs.lastAccessTime());
}
}


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

Он предоставляет несколько фабричных методов:
FileTime.from(Instant instant) — из объекта Instant (точка на временной шкале UTC).
FileTime.fromMillis(long millis) — из миллисекунд с эпохи Unix (1 января 1970).
FileTime.from(long value, TimeUnit unit) — из произвольной единицы времени.

Эпоха Unix (Unix epoch) — это момент времени 00:00:00 UTC 1 января 1970 года. Время в Unix-системах традиционно отсчитывается от этой точки в секундах или миллисекундах.


Универсальный метод: Files.setAttribute()

Метод Files.setAttribute(Path path, String attribute, Object value, LinkOption... options) позволяет установить любой атрибут по его строковому имени. Это полезно, когда вы работаете с атрибутами динамически или пишете универсальный код, не привязанный к конкретному типу файловой системы.


Синтаксис имени атрибута

Имя атрибута имеет формат viewName:attributeName. Если viewName опущен, используется "basic".
// Установка времени модификации через универсальный метод
Files.setAttribute(path, "basic:lastModifiedTime", FileTime.from(Instant.now()));

// Установка POSIX-прав
Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxr-xr-x");
Files.setAttribute(path, "posix:permissions", perms);

// Установка владельца (только Unix с соответствующими правами)
UserPrincipalLookupService lookup = FileSystems.getDefault().getUserPrincipalLookupService();
UserPrincipal newOwner = lookup.lookupPrincipalByName("admin");
Files.setAttribute(path, "posix:owner", newOwner);


UserPrincipal
— это интерфейс в NIO.2, представляющий пользователя или группу в файловой системе. UserPrincipalLookupService — сервис для поиска пользователей по имени.

Метод setAttribute() использует рефлексию и динамическую диспетчеризацию: он парсит строку имени, находит соответствующее FileAttributeView, вызывает его метод записи. Это менее эффективно, чем прямой вызов специализированного метода (например, Files.setPosixFilePermissions()), но предоставляет гибкость при работе с неизвестными заранее типами атрибутов.

Рефлексия (reflection) — это механизм Java, позволяющий программе исследовать и модифицировать структуру и поведение объектов во время выполнения: получать классы, методы, поля, вызывать методы по имени.
Работа с правами доступа POSIX: Files.setPosixFilePermissions()


На Unix-подобных системах права доступа к файлам управляются через POSIX-биты. Класс PosixFilePermissions предоставляет удобные методы для работы с ними.
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.io.IOException;
import java.util.Set;

public class PosixPermissionManager {

public void setStrictPermissions(Path path) throws IOException {
// rw------- — только владелец может читать и писать
Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rw-------");
Files.setPosixFilePermissions(path, perms);
}

public void setExecutable(Path path) throws IOException {
// Добавляем право на выполнение для владельца
Set<PosixFilePermission> perms = Files.getPosixFilePermissions(path);
perms.add(PosixFilePermission.OWNER_EXECUTE);
Files.setPosixFilePermissions(path, perms);
}

public void setSharedReadOnly(Path path) throws IOException {
// r--r--r-- — все могут читать, никто не может писать
Set<PosixFilePermission> perms = PosixFilePermissions.fromString("r--r--r--");
Files.setPosixFilePermissions(path, perms);
}

public void copyPermissions(Path source, Path target) throws IOException {
// Копируем POSIX-права с одного файла на другой
Set<PosixFilePermission> perms = Files.getPosixFilePermissions(source);
Files.setPosixFilePermissions(target, perms);
}

public void createWithPermissions(Path path, String permString) throws IOException {
Set<PosixFilePermission> perms = PosixFilePermissions.fromString(permString);
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);

// createFile с FileAttribute устанавливает права атомарно при создании
Files.createFile(path, attr);
}
}


PosixFilePermission
— это enum, определяющий девять возможных битов прав:
Владелец: OWNER_READ, OWNER_WRITE, OWNER_EXECUTE
Группа: GROUP_READ, GROUP_WRITE, GROUP_EXECUTE
Остальные: OTHERS_READ, OTHERS_WRITE, OTHERS_EXECUTE

Строковое представление "rwxr-xr-x" — это стандартная нотация Unix ls -l, где каждая триада символов описывает права для владельца, группы и остальных. Дефис означает отсутствие права.


#Java #для_новичков #beginner #IO #NIO #Files #BasicFileAttributes
👍4
Пример: установка времени модификации файла в текущий момент
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
Что выведет код?

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
Ребят, есть предложение! 😉

А давайте как в старые-добрые встретимся в воскресение часиков с 16 по мск и посидим, поговорим?

Предлагайте темы и вопросы которые можем обсудить.

Можем просто провести нытинг)

Старичкам канала быть обязательно! 😏

Придёте? 🚘
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6👎1🤣1
Что такое StackWalker в Java 9? 🤓

Ответ:

StackWalker (Java 9)
— это эффективный API для обхода стека вызовов.

Предоставляет метод walk(Function<Stream<StackFrame>, T>) для получения стрима кадров стека.

Более производительный, чем Thread.getStackTrace(), так как не создаёт массив всех кадров, а лениво обходит только нужные.

Позволяет фильтровать, пропускать и т.д. Полезен для логирования, отладки, безопасности (проверка, кто вызывает метод). Поддерживает режимы: RETAIN_CLASS_REFERENCE для работы с классами.



#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍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июля
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Эххххх и правда ведь....)
🤣4
Не оставляем телефон без присмотра....
🤣31