Please open Telegram to view this post
VIEW IN TELEGRAM
🤯7
Что такое 🤓
Ответ:
DirectByteBuffer — это класс, который выделяет память вне кучи (off-heap), напрямую через операционную систему.
Такая память не управляется GC (но объект-буфер — в куче).
Преимущества:
1) эффективный ввод-вывод (можно передать ядру без копирования).
2) снижение нагрузки на GC.
3) работа с большими блоками памяти.
Недостатки:
сложность управления (ручное освобождение через Cleaner или sun.misc.Unsafe).
Используется в NIO, Netty, Cassandra. Утечки off-heap памяти могут привести к OutOfMemoryError типа "Direct buffer memory".
#собеседование
DirectByteBuffer и off-heap memory? Ответ:
Такая память не управляется GC (но объект-буфер — в куче).
Преимущества:
1) эффективный ввод-вывод (можно передать ядру без копирования).
2) снижение нагрузки на GC.
3) работа с большими блоками памяти.
Недостатки:
сложность управления (ручное освобождение через Cleaner или sun.misc.Unsafe).
Используется в NIO, Netty, Cassandra. Утечки off-heap памяти могут привести к OutOfMemoryError типа "Direct buffer memory".
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Let's Encrypt присоединился к санкциям
https://news.ycombinator.com/item?id=48453275#48465754
Тревожных новостей вам с утра, для тех кто в теме🧑💻
https://news.ycombinator.com/item?id=48453275#48465754
Тревожных новостей вам с утра, для тех кто в теме
Please open Telegram to view this post
VIEW IN TELEGRAM
История технологии сегодня — 10 июня
ℹ️ Кто родился в этот день
Юджин Ньюмен Паркер (англ. Eugene Newman Parker; 10 июня 1927, Хоутон, Мичиган — 15 марта 2022) — американский учёный, астроном и астрофизик, известный своими работами по физике плазмы и физике Солнца. Основные труды — в области физики плазмы и её приложений к проблемам астрофизики и геофизики. Исследовал решения уравнений движения для бесстолкновительной плазмы, ускорение быстрых частиц и магнитную аннигиляцию в солнечных вспышках, образование солнечных пятен и природу магнитного поля Солнца, распространение ударных волн в межпланетном пространстве, происхождение и структуру галактических магнитных полей, происхождение и распространение галактических космических лучей. Выполнил пионерские работы по изучению свойств солнечного ветра и его взаимодействия с геомагнитным полем.
Э́двард О́сборн Уи́лсон (англ. Edward Osborne Wilson; 10 июня 1929, Бирмингем, штат Алабама, США — 26 декабря 2021) — американский биолог, социобиолог, мирмеколог, эколог, писатель, дважды лауреат Пулитцеровской премии. Был признанным в мире экспертом по муравьям и получил прозвище Ant Man. Автор более 30 книг и более 430 научных статей, некоторые из которых являются наиболее цитируемыми в истории и изданы в таких важных научных журналах, как Nature или Science. Его работы «Character displacement», опубликованная в 1956 году в соавторстве с Уильямом Брауном-младшим, «The Theory of Island Biogeography», подготовленная вместе с Робертом МакАртуром в 1967 году, «Experimental zoogeography of islands: the colonization of empty islands», изданная в 1969 году вместе Дэниелом Симберлоффом и его книги «The Insect Societies» и «Sociobiology: The New Synthesis» были удостоены награды Science Citation Classic, самой значимой награды, которая определяет наиболее цитируемые научные работы. Он также получил более 150 престижных наград и медалей по всему миру, а также более 40 почётных докторских степеней. Он является почётным членом более 30 всемирно известных и престижных организаций, академий и институтов. Его приглашали читать лекции в более чем 100 университетов и институтов по всему миру.
🌐 Знаковые события
1943 — американский торговец Милтон Рейнольдс запатентовал в США шариковую ручку, изобретённую венгром Ласло Биро.
1996 — корпорация Intel выпустила процессор Pentium II.
#Biography #Birth_Date #Events #10июня
Юджин Ньюмен Паркер (англ. Eugene Newman Parker; 10 июня 1927, Хоутон, Мичиган — 15 марта 2022) — американский учёный, астроном и астрофизик, известный своими работами по физике плазмы и физике Солнца. Основные труды — в области физики плазмы и её приложений к проблемам астрофизики и геофизики. Исследовал решения уравнений движения для бесстолкновительной плазмы, ускорение быстрых частиц и магнитную аннигиляцию в солнечных вспышках, образование солнечных пятен и природу магнитного поля Солнца, распространение ударных волн в межпланетном пространстве, происхождение и структуру галактических магнитных полей, происхождение и распространение галактических космических лучей. Выполнил пионерские работы по изучению свойств солнечного ветра и его взаимодействия с геомагнитным полем.
Э́двард О́сборн Уи́лсон (англ. Edward Osborne Wilson; 10 июня 1929, Бирмингем, штат Алабама, США — 26 декабря 2021) — американский биолог, социобиолог, мирмеколог, эколог, писатель, дважды лауреат Пулитцеровской премии. Был признанным в мире экспертом по муравьям и получил прозвище Ant Man. Автор более 30 книг и более 430 научных статей, некоторые из которых являются наиболее цитируемыми в истории и изданы в таких важных научных журналах, как Nature или Science. Его работы «Character displacement», опубликованная в 1956 году в соавторстве с Уильямом Брауном-младшим, «The Theory of Island Biogeography», подготовленная вместе с Робертом МакАртуром в 1967 году, «Experimental zoogeography of islands: the colonization of empty islands», изданная в 1969 году вместе Дэниелом Симберлоффом и его книги «The Insect Societies» и «Sociobiology: The New Synthesis» были удостоены награды Science Citation Classic, самой значимой награды, которая определяет наиболее цитируемые научные работы. Он также получил более 150 престижных наград и медалей по всему миру, а также более 40 почётных докторских степеней. Он является почётным членом более 30 всемирно известных и престижных организаций, академий и институтов. Его приглашали читать лекции в более чем 100 университетов и институтов по всему миру.
1943 — американский торговец Милтон Рейнольдс запатентовал в США шариковую ручку, изобретённую венгром Ласло Биро.
1996 — корпорация Intel выпустила процессор Pentium II.
#Biography #Birth_Date #Events #10июня
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
[Совет по Java #048]
Тема:
Проблема: Метод
Нельзя полагаться на его выполнение для освобождения критических ресурсов (файловые дескрипторы, сокеты, соединения с БД).
Кроме того,
Решение: Для явного освобождения ресурсов реализуйте интерфейс
Объяснение:
Он никогда не должен использоваться в production-коде.
#Java #советы
Тема:
finalize() — устаревший и непредсказуемый.Проблема: Метод
finalize() вызывается сборщиком мусора в неопределенный момент времени (возможно, никогда). Нельзя полагаться на его выполнение для освобождения критических ресурсов (файловые дескрипторы, сокеты, соединения с БД).
Кроме того,
finalize() имеет серьезные проблемы производительности: объекты с переопределенным finalize() требуют минимум двух циклов GC для удаления, что увеличивает нагрузку. Он также может быть вызван на объекте, который снова становится достижимым (resurrection), создавая хаос. Начиная с Java 9, finalize() помечен как deprecated. Использование его для очистки ресурсов — антипаттерн, ведущий к утечкам и непредсказуемому поведению.Решение: Для явного освобождения ресурсов реализуйте интерфейс
AutoCloseable и используйте try-with-resources. Для нестандартных сценариев (освобождение памяти native, очистка после объектов, которые могут быть забыты) используйте java.lang.ref.Cleaner (Java 9+), который предоставляет предсказуемый механизм регистрации очистки, но не гарантирует немедленного выполнения. Cleaner использует слабые ссылки и вызывается в специальном потоке. Однако лучший подход — всегда явное управление ресурсами через close().public class FinalizeVsCleaner {
//Антипаттерн: finalize (deprecated)
@Deprecated
static class BadResource {
private final FileInputStream stream;
BadResource(String path) throws IOException {
this.stream = new FileInputStream(path);
}
@Override
protected void finalize() throws Throwable {
stream.close(); // Неизвестно, когда и будет ли вызвано!
}
}
//Решение: AutoCloseable + try-with-resources
static class GoodResource implements AutoCloseable {
private final FileInputStream stream;
GoodResource(String path) throws IOException {
this.stream = new FileInputStream(path);
}
public void doWork() { /* ... */ }
@Override
public void close() throws IOException {
if (stream != null) stream.close();
}
}
// Cleaner для критических native-ресурсов (Java 9+)
static class NativeResource implements AutoCloseable {
private final Cleaner cleaner = Cleaner.create();
private final Cleaner.Cleanable cleanable;
private final long nativeHandle;
NativeResource(long handle) {
this.nativeHandle = handle;
this.cleanable = cleaner.register(this, new CleanupAction(handle));
}
private static class CleanupAction implements Runnable {
private final long handle;
CleanupAction(long handle) { this.handle = handle; }
@Override
public void run() {
freeNativeMemory(handle); // native-функция
}
}
@Override
public void close() {
cleanable.clean(); // явный вызов
}
private static native void freeNativeMemory(long handle);
}
}Объяснение:
finalize() объявлен deprecated с Java 9 и будет удален в будущих версиях. Он никогда не должен использоваться в production-коде.
AutoCloseable обеспечивает детерминированное освобождение ресурсов через try-with-resources, что гарантирует закрытие даже при исключениях. Cleaner — это замена finalize() для ситуаций, где ресурс может быть пропущен (например, native-память), но он не должен заменять явный close(). Cleaner использует фоновый поток и не дает гарантий времени вызова.#Java #советы
👍4
Что выведет код?
#Tasks
public class Task100626 {
static class Resource implements AutoCloseable {
@Override
public void close() {
throw new RuntimeException("Close exception");
}
}
public static void main(String[] args) {
try (Resource r = new Resource()) {
throw new IllegalArgumentException("Try exception");
} catch (Exception e) {
System.out.println(e.getClass().getSimpleName());
Throwable[] suppressed = e.getSuppressed();
if (suppressed.length > 0) {
System.out.println(suppressed[0].getClass().getSimpleName());
}
}
}
}#Tasks
👍2
Что такое 🤓
Ответ:
SoftReference — тип ссылки, при котором объект будет удалён сборщиком мусора только в случае нехватки памяти, перед тем как будет выброшено OutOfMemoryError.
Идеально для реализации кэшей — кэш будет хранить объекты, пока есть свободная память, и автоматически очищаться при её дефиците.
В сочетании с ReferenceQueue можно отслеживать удаление объектов и выгружать их из кэша.
Это проще, чем LRU-алгоритмы, но даёт меньший контроль.
Применяется в кэшах библиотек, загрузчиках изображений.
#собеседование
SoftReference и как его использовать для кэша? Ответ:
Идеально для реализации кэшей — кэш будет хранить объекты, пока есть свободная память, и автоматически очищаться при её дефиците.
В сочетании с ReferenceQueue можно отслеживать удаление объектов и выгружать их из кэша.
Это проще, чем LRU-алгоритмы, но даёт меньший контроль.
Применяется в кэшах библиотек, загрузчиках изображений.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
История технологии сегодня — 11 июня
ℹ️ Кто родился в этот день
Жак-Ив Кусто́ (фр. Jacques-Yves Cousteau; 11 июня 1910, Сент-Андре-де-Кюбзак, Бордо, Франция — 25 июня 1997, Париж, Франция) — французский исследователь Мирового океана, фотограф, режиссёр, изобретатель, автор множества книг и фильмов. Являлся членом Французской академии. Известен как Капитан Кусто (фр. Commandant Cousteau). Совместно с Эмилем Ганьяном в 1943 году разработал и испытал акваланг. В его честь назван уступ Кусто на Плутоне. Кусто стал создателем водонепроницаемых камер и осветительных приборов, а также изобрёл первую подводную телевизионную систему.
Шарль Фабри́ (фр. Marie Paul Auguste Charles Fabry; 11 июня 1867, Марсель — 11 декабря 1945, Париж) — французский физик, открывший вместе с Анри Буиссоном[нем.] озоновый слой атмосферы и один из изобретателей интерферометра Фабри — Перо.
🌐 Знаковые события
1991 — фирма «Microsoft» выпустила операционную систему MS DOS 5.0.
2008 — на орбиту запущен космический гамма-телескоп Fermi.
#Biography #Birth_Date #Events #11июня
Жак-Ив Кусто́ (фр. Jacques-Yves Cousteau; 11 июня 1910, Сент-Андре-де-Кюбзак, Бордо, Франция — 25 июня 1997, Париж, Франция) — французский исследователь Мирового океана, фотограф, режиссёр, изобретатель, автор множества книг и фильмов. Являлся членом Французской академии. Известен как Капитан Кусто (фр. Commandant Cousteau). Совместно с Эмилем Ганьяном в 1943 году разработал и испытал акваланг. В его честь назван уступ Кусто на Плутоне. Кусто стал создателем водонепроницаемых камер и осветительных приборов, а также изобрёл первую подводную телевизионную систему.
Шарль Фабри́ (фр. Marie Paul Auguste Charles Fabry; 11 июня 1867, Марсель — 11 декабря 1945, Париж) — французский физик, открывший вместе с Анри Буиссоном[нем.] озоновый слой атмосферы и один из изобретателей интерферометра Фабри — Перо.
1991 — фирма «Microsoft» выпустила операционную систему MS DOS 5.0.
2008 — на орбиту запущен космический гамма-телескоп Fermi.
#Biography #Birth_Date #Events #11июня
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Раздел 11. Работа с файлами, I/O и сетью (NIO.2)
Глава 1. Классический Java I/O (java.io)
BufferedInputStream – буферизованное чтение. Путь данных через память JVM
Ключевое архитектурное решение — разделение ответственности.
Внутреннее устройство
Поля
Механика fill() и путь данных
Метод
Путь данных при
Проверка состояния буфера. Определение, можно ли читать с начала или требуется сдвиг/расширение.
Системный вызов read().
Копирование в heap. Данные из нативного буфера через JNI попадают в
Обновление счетчиков.
Путь данных в памяти: детальный разбор
Сценарий: первое чтение после создания
Путь данных для первого
Массив
Сценарий: последующие чтения из буфера
Никаких системных вызовов, никакого JNI, никакого обращения к ядру. Данные извлекаются из массива в heap напрямую JVM-байткодом. Это на порядки быстрее, чем побайтовое чтение через
Сценарий: буфер исчерпан
#Java #для_новичков #beginner #IO #NIO #BufferedInputStream
Глава 1. Классический Java I/O (java.io)
BufferedInputStream – буферизованное чтение. Путь данных через память JVM
BufferedInputStream — декоратор над InputStream, добавляющий внутреннюю буферизацию к любому underlying потоку. Он не является самостоятельным источником данных, а служит промежуточным слоем, который накапливает данные в памяти и выдает их порциями при запросе. Это устраняет главный недостаток побайтового чтения: накладные расходы системных вызовов.Ключевое архитектурное решение — разделение ответственности.
FileInputStream отвечает за взаимодействие с ОС и файловой системой. BufferedInputStream отвечает за оптимизацию паттерна доступа: замену множества мелких запросов на несколько крупных. Это классический применение паттерна декоратора в Java I/O.Внутреннее устройство
// Упрощенная структура из OpenJDK
public class BufferedInputStream extends FilterInputStream {
// Внутренний буфер в heap JVM
protected volatile byte[] buf;
// Количество байт, фактически доступных в буфере
protected int count;
// Текущая позиция чтения в буфере
protected int pos;
// Позиция маркера для mark/reset, -1 если не установлен
protected int markpos = -1;
// Максимальное количество байт, читаемых после mark
protected int marklimit;
// Конструкторы
public BufferedInputStream(InputStream in) {
this(in, 8192); // Размер по умолчанию
}
public BufferedInputStream(InputStream in, int size) {
super(in);
if (size <= 0) {
throw new IllegalArgumentException("Buffer size <= 0");
}
buf = new byte[size]; // Выделение в heap
}
}
Поля
buf, count, pos образуют кольцевой буфер (ring buffer), хотя в стандартной реализации используется линейный массив с сдвигом при исчерпании. При вызове read() BufferedInputStream сначала проверяет pos < count. Если условие истинно — байт возвращается из buf[pos++] без системного вызова. Если ложно — выполняется fill(), который читает новый блок данных из underlying потока.Механика fill() и путь данных
Метод
fill() — сердце буферизации. Он выполняется, когда внутренний буфер исчерпан:// Упрощенная логика fill()
private void fill() throws IOException {
byte[] buffer = getBufIfOpen();
if (markpos < 0) {
// Маркер не установлен — читаем с начала буфера
pos = 0;
} else if (pos >= buffer.length) {
// Позиция достигла конца буфера
if (markpos > 0) {
// Сдвигаем данные от markpos к началу
int sz = pos - markpos;
System.arraycopy(buffer, markpos, buffer, 0, sz);
pos = sz;
markpos = 0;
} else if (buffer.length >= marklimit) {
// Буфер превысил лимит маркера — сбрасываем
markpos = -1;
pos = 0;
} else {
// Расширяем буфер
int nsz = pos * 2;
if (nsz > marklimit) nsz = marklimit;
byte[] nbuf = new byte[nsz];
System.arraycopy(buffer, 0, nbuf, 0, pos);
buf = nbuf;
buffer = nbuf;
markpos = 0;
}
}
count = pos;
// Системный вызов: чтение из underlying потока
int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
if (n > 0) count = n + pos;
}
Путь данных при
fill():Проверка состояния буфера. Определение, можно ли читать с начала или требуется сдвиг/расширение.
Системный вызов read().
getInIfOpen().read(buffer, pos, len) — один вызов для чтения до buffer.length - pos байт.Копирование в heap. Данные из нативного буфера через JNI попадают в
buf в heap.Обновление счетчиков.
count устанавливается в количество фактически прочитанных байт.Путь данных в памяти: детальный разбор
Сценарий: первое чтение после создания
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("data.bin"), 8192)) {
int firstByte = bis.read(); // Инициирует fill()
}
Путь данных для первого
read():[Java: bis.read()]
-> [BufferedInputStream: pos=0, count=0, буфер пуст]
-> [fill()]
-> [FileInputStream.read(buf, 0, 8192)]
-> [JNI: нативный readBytes]
-> [Ядро ОС: syscall read(fd, native_buf, 8192)]
-> [Page Cache: поиск/загрузка страниц]
-> [Копирование: 8192 байт из page cache в native_buf]
-> [Возврат в userspace]
-> [JNI: копирование 8192 байт в buf[8192] в heap]
-> [BufferedInputStream: count=8192, pos=0]
-> [Возврат buf[0] как int]
Массив
buf[8192] создан при конструировании BufferedInputStream и размещен в heap. Для размера 8192 байт это обычный объект, не humongous. Он размещается в Eden space young generation.Сценарий: последующие чтения из буфера
int secondByte = bis.read(); // pos=1, count=8192, системный вызов отсутствует
int thirdByte = bis.read(); // pos=2, count=8192, системный вызов отсутствует
[Java: bis.read()]
-> [BufferedInputStream: pos < count? 1 < 8192 — да]
-> [Возврат buf[1] как int, pos++]
Никаких системных вызовов, никакого JNI, никакого обращения к ядру. Данные извлекаются из массива в heap напрямую JVM-байткодом. Это на порядки быстрее, чем побайтовое чтение через
FileInputStream.Сценарий: буфер исчерпан
// После 8192 вызовов read()
int byte8193 = bis.read(); // pos=8192, count=8192, буфер пуст
[Java: bis.read()]
-> [BufferedInputStream: pos < count? 8192 < 8192 — нет]
-> [fill()]
-> [System.arraycopy при необходимости]
-> [FileInputStream.read(buf, 0, 8192)]
-> [Новый системный вызов]
-> [count=новое_значение, pos=0]
-> [Возврат buf[0]]
#Java #для_новичков #beginner #IO #NIO #BufferedInputStream
👍4
Роль garbage collector
Жизненный цикл буфера
Буфер
Проблема: большой буфер и humongous objects
При размере буфера 1MB и размере G1-региона 1MB массив становится humongous object. Он размещается в специальных humongous-регионах old generation и не перемещается при minor GC. Это увеличивает фрагментацию heap и может вызвать преждевременный full GC.
Рекомендация: использовать стандартный размер 8KB или увеличивать до 64KB для последовательного чтения больших файлов. Размеры более 256KB редко дают выигрыш из-за размера страницы ОС (4KB) и размера блока файловой системы (4KB).
Проблема: утечка ссылки на поток
Если ссылка на
mark() и reset(): семантика и память
Если количество прочитанных байт после
Расширение буфера при активном маркере:
Это единственный сценарий, где
Практический пример: сравнение производительности
Ожидаемые результаты на SSD:
#Java #для_новичков #beginner #IO #NIO #BufferedInputStream
Жизненный цикл буфера
public void processFile(String path) throws IOException {
// buf создается в Eden space при конструировании BufferedInputStream
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(path))) {
int b;
// Цикл без аллокаций в heap — GC не вовлечен
while ((b = bis.read()) != -1) {
processByte(b);
}
} // close() вызывается автоматически
// buf становится недостижимым
// GC собирает buf и bis при следующей minor collection
}Буфер
buf — это долгоживущий объект относительно метода. Он создается при входе в try и живет до выхода. Если метод вызывается часто, буфер может быть повышен в survivor space или old generation при выживании нескольких minor GC. Это нормально — буфер небольшой (8KB) и не создает проблем с памятью.Проблема: большой буфер и humongous objects
// Потенциально проблематично: 1MB буфер
BufferedInputStream bis = new BufferedInputStream(fis, 1024 * 1024);
При размере буфера 1MB и размере G1-региона 1MB массив становится humongous object. Он размещается в специальных humongous-регионах old generation и не перемещается при minor GC. Это увеличивает фрагментацию heap и может вызвать преждевременный full GC.
Рекомендация: использовать стандартный размер 8KB или увеличивать до 64KB для последовательного чтения больших файлов. Размеры более 256KB редко дают выигрыш из-за размера страницы ОС (4KB) и размера блока файловой системы (4KB).
Проблема: утечка ссылки на поток
// Антипаттерн: утечка ссылки
private InputStream leakedStream;
public void open(String path) throws IOException {
leakedStream = new BufferedInputStream(new FileInputStream(path));
// Если исключение позже — поток не закрыт, buf не освобожден
}
Если ссылка на
BufferedInputStream сохраняется в поле класса, GC не может освободить буфер даже после исчерпания потока. Буфер остается в памяти до тех пор, пока объект BufferedInputStream достижим. При многократном открытии файлов без закрытия это приводит к исчерпанию heap.mark() и reset(): семантика и память
BufferedInputStream поддерживает маркировку позиции для последующего возврата. Это требует хранения данных в буфере между mark() и reset():bis.mark(1024); // Запомнить позицию, лимит 1024 байт вперед
// Чтение до 1024 байт
bis.reset(); // Вернуться к отмеченной позиции
Если количество прочитанных байт после
mark() превышает marklimit, маркер инвалидируется. Если данные влезают в текущий буфер — reset() работает без системных вызовов. Если требуется больше данных, чем вмещает буфер — fill() выполняет System.arraycopy для сдвига или расширяет буфер.Расширение буфера при активном маркере:
// Из fill(): буфер расширяется до marklimit
byte[] nbuf = new byte[nsz]; // Новый массив в heap
System.arraycopy(buffer, 0, nbuf, 0, pos); // Копирование старых данных
buf = nbuf; // Старая ссылка на массив теряется, GC собирает старый buf
Это единственный сценарий, где
BufferedInputStream создает новые массивы в процессе работы. При отсутствии mark()/reset() буфер остается неизменным.Практический пример: сравнение производительности
public class BufferedPerformanceDemo {
private static final int FILE_SIZE = 10 * 1024 * 1024; // 10 MB
public static void main(String[] args) throws IOException {
// Создание тестового файла
createTestFile("test.bin", FILE_SIZE);
// Тест 1: FileInputStream без буферизации
measure("FileInputStream raw", () -> {
try (FileInputStream fis = new FileInputStream("test.bin")) {
while (fis.read() != -1) {} // Побайтово
}
});
// Тест 2: FileInputStream с внешним буфером
measure("FileInputStream + byte[]", () -> {
try (FileInputStream fis = new FileInputStream("test.bin")) {
byte[] buf = new byte[8192];
while (fis.read(buf) != -1) {}
}
});
// Тест 3: BufferedInputStream (внутренняя буферизация)
measure("BufferedInputStream", () -> {
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("test.bin"))) {
while (bis.read() != -1) {} // Побайтово, но буферизовано
}
});
}
private static void measure(String name, Runnable task) {
long start = System.nanoTime();
task.run();
long ms = (System.nanoTime() - start) / 1_000_000;
System.out.printf("%s: %d ms%n", name, ms);
}
private static void createTestFile(String path, int size) throws IOException {
byte[] data = new byte[size];
new Random().nextBytes(data);
try (FileOutputStream fos = new FileOutputStream(path)) {
fos.write(data);
}
}
}Ожидаемые результаты на SSD:
FileInputStream raw: 15 000-30 000 msFileInputStream + byte[]: 30-50 msBufferedInputStream: 30-50 msBufferedInputStream с побайтовым read() достигает той же производительности, что и FileInputStream с внешним массивом, но с более чистым API. Внешний буфер требует ручного управления размером и границами, BufferedInputStream инкапсулирует эту сложность.#Java #для_новичков #beginner #IO #NIO #BufferedInputStream
👍4
Что выведет код?
#Tasks
import java.io.*;
public class Task110626 {
public static void main(String[] args) throws IOException {
byte[] data = {10, 20, 30, 40, 50};
BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(data));
bis.mark(2);
System.out.print(bis.read());
System.out.print(bis.read());
System.out.print(bis.read());
bis.reset();
System.out.print(bis.read());
}
}
#Tasks
👍2
Что такое 🤓
Ответ:
Метод finalize() был способом выполнить "последнюю волю" объекта перед сборкой мусора.
Чтобы его переопределить, достаточно было написать protected void finalize() throws Throwable { try { ... } finally { super.finalize(); } }.
Проблемы:
JVM мог не вызвать finalize() для всех объектов перед завершением;
вызывался в отдельном потоке финализации (низкий приоритет);
имел непредсказуемое время выполнения.
Поэтому его использование считалось антипаттерном много лет.
Начиная с Java 18, его удалили.
#собеседование
Object.finalize() и как его переопределить? Ответ:
Чтобы его переопределить, достаточно было написать protected void finalize() throws Throwable { try { ... } finally { super.finalize(); } }.
Проблемы:
JVM мог не вызвать finalize() для всех объектов перед завершением;
вызывался в отдельном потоке финализации (низкий приоритет);
имел непредсказуемое время выполнения.
Поэтому его использование считалось антипаттерном много лет.
Начиная с Java 18, его удалили.
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
История технологии сегодня — 12 июня
День Росси́и (до 2002 года — День принятия Декларации о государственном суверенитете Российской Федерации) — государственный праздник Российской Федерации. Отмечается 12 июня — в день принятия в 1990 году Декларации о государственном суверенитете РСФСР. Установлен в 1992 году (нерабочий день с 1991 года).
ℹ️ Кто родился в этот день
Владимир Александрович Магницкий (30 мая [12 июня] 1915, Пенза — 16 октября 2005, Москва) — советский учёный-геофизик, академик АН CCCP (1979), основатель советской школы физики земных недр. Заложил основы отечественной школы физики земных недр, проанализировал результаты различных направлений с общих позиций и новые физические методы в исследовании внутреннего строения Земли. Для определения температурного распределения в недрах Земли предложил использовать метод реперных точек, а при изучении процессов формирования месторождений полезных ископаемых — теорию зонной плавки; при анализе состава нижней мантии предложил гипотезу о распаде вещества на окислы. При построении модели Земли ввёл методы, основанные на использовании уравнений состояния вещества при высоких давлениях.
🌐 Знаковые события
1967 — запущен космический аппарат Венера-4, впервые в мире передавший данные об атмосфере другой планеты.
#Biography #Birth_Date #Events #12июня
День Росси́и (до 2002 года — День принятия Декларации о государственном суверенитете Российской Федерации) — государственный праздник Российской Федерации. Отмечается 12 июня — в день принятия в 1990 году Декларации о государственном суверенитете РСФСР. Установлен в 1992 году (нерабочий день с 1991 года).
Владимир Александрович Магницкий (30 мая [12 июня] 1915, Пенза — 16 октября 2005, Москва) — советский учёный-геофизик, академик АН CCCP (1979), основатель советской школы физики земных недр. Заложил основы отечественной школы физики земных недр, проанализировал результаты различных направлений с общих позиций и новые физические методы в исследовании внутреннего строения Земли. Для определения температурного распределения в недрах Земли предложил использовать метод реперных точек, а при изучении процессов формирования месторождений полезных ископаемых — теорию зонной плавки; при анализе состава нижней мантии предложил гипотезу о распаде вещества на окислы. При построении модели Земли ввёл методы, основанные на использовании уравнений состояния вещества при высоких давлениях.
1967 — запущен космический аппарат Венера-4, впервые в мире передавший данные об атмосфере другой планеты.
#Biography #Birth_Date #Events #12июня
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
[Совет по Java #049]
Тема:
Проблема: Вызов
Современные JVM имеют сложные эвристики для управления памятью, и явный вызов может быть проигнорирован (например, при использовании G1 GC с параметром
Разработчики часто вызывают
Решение: Никогда не вызывайте
Доверьте управление памятью JVM. Настройте параметры GC (размеры куч, поколения, алгоритм) под ваше приложение. Для профилирования используйте инструменты мониторинга (JConsole, VisualVM, GC logs). Если вам нужно принудительно запустить GC для тестирования или бенчмаркинга, используйте флаг
Объяснение: Современные JVM используют сборщики мусора, которые адаптивно оптимизируют паузы и пропускную способность.
Явный вызов
На HotSpot JVM по умолчанию
#Java #советы
Тема:
System.gc() не гарантирует запуск сборщика мусора.Проблема: Вызов
System.gc() (или Runtime.getRuntime().gc()) является запросом к JVM на выполнение сборки мусора, но спецификация Java не требует, чтобы JVM немедленно или вообще запускала GC. Современные JVM имеют сложные эвристики для управления памятью, и явный вызов может быть проигнорирован (например, при использовании G1 GC с параметром
-XX:+DisableExplicitGC). Более того, принудительный запуск Full GC может вызвать длительные паузы ("stop-the-world"), снижая производительность приложения. Разработчики часто вызывают
System.gc() в ошибочной надежде "почистить память" или избежать OutOfMemoryError, но это может привести к обратному эффекту: сборка мусора запускается в неподходящий момент, перемещая объекты между поколениями и увеличивая фрагментацию.Решение: Никогда не вызывайте
System.gc() в production-коде. Доверьте управление памятью JVM. Настройте параметры GC (размеры куч, поколения, алгоритм) под ваше приложение. Для профилирования используйте инструменты мониторинга (JConsole, VisualVM, GC logs). Если вам нужно принудительно запустить GC для тестирования или бенчмаркинга, используйте флаг
-XX:+ExplicitGCInvokesConcurrent или вызывайте System.gc() в изолированной среде с отключенным DisableExplicitGC. public class SystemGcExample {
//Антипаттерн: вызов System.gc()
public static void badPractice() {
// ... после обработки больших данных
System.gc(); // Бесполезно и вредно!
// JVM может проигнорировать, а если запустит — вызовет паузу
}
//Решение: довериться JVM
public static void goodPractice() {
// Просто работаем, JVM сама решит, когда собрать мусор
byte[] data = new byte[1024 * 1024];
// данные становятся недоступными
data = null;
// JVM соберет их при необходимости
}
// Для отладки: мониторинг GC через MXBean
public static void printGcStats() {
for (GarbageCollectorMXBean bean : ManagementFactory.getGarbageCollectorMXBeans()) {
System.out.println(bean.getName() + ": " + bean.getCollectionCount() + " collections");
}
}
// Единственное разумное использование: сигнал в тестах или бенчмарках
public static void onlyForBenchmark() {
// При бенчмаркинге можно вызвать несколько раз для стабилизации состояния
for (int i = 0; i < 3; i++) {
System.gc();
Thread.sleep(100);
}
}
public static void main(String[] args) {
goodPractice();
System.out.println("GC вызов не гарантирован, не полагайтесь на него");
}
}Объяснение: Современные JVM используют сборщики мусора, которые адаптивно оптимизируют паузы и пропускную способность.
Явный вызов
System.gc() нарушает эту адаптивность. На HotSpot JVM по умолчанию
System.gc() вызывает Full GC, очищающий все поколения, что особенно дорого для приложений с большой кучей. С помощью флага -XX:+DisableExplicitGC можно полностью отключить реакцию на явные вызовы, что многие production-системы и делают. Если вам кажется, что памяти не хватает, лучше анализировать утечки через heap dump, а не полагаться на принудительный GC. #Java #советы
👍4
Что выведет код?
#Tasks
public class Task120626 {
static boolean finalized = false;
@Override
protected void finalize() {
finalized = true;
}
public static void main(String[] args) {
new Task120626();
System.gc();
System.out.println(finalized);
}
}#Tasks
👍2
👍2
Что такое 🤓
Ответ:
ReferenceQueue — это очередь, в которую помещаются объекты-ссылки (Soft, Weak, Phantom) после того, как объекты, на которые они указывали, становятся недостижимыми (т.е. удаляются GC).
Это позволяет программе узнать, какие объекты были собраны, и провести post-processing (например, удалить ключи из кэша).
Используется в WeakHashMap внутри. Работает так: создаётся ReferenceQueue, затем при создании ссылки передаётся в конструктор.
После очистки объекта GC добавляет ссылку в очередь. Можно вызывать poll() или remove().
#собеседование
ReferenceQueue? Ответ:
ReferenceQueue — это очередь, в которую помещаются объекты-ссылки (Soft, Weak, Phantom) после того, как объекты, на которые они указывали, становятся недостижимыми (т.е. удаляются GC).
Это позволяет программе узнать, какие объекты были собраны, и провести post-processing (например, удалить ключи из кэша).
Используется в WeakHashMap внутри. Работает так: создаётся ReferenceQueue, затем при создании ссылки передаётся в конструктор.
После очистки объекта GC добавляет ссылку в очередь. Можно вызывать poll() или remove().
#собеседование
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
С 30.05 по 12.06
Предыдущий пост(с 23.05 по 29.05)
Запись встреч/видео:
14. Transactional Outbox: как гарантировать публикацию события
Обучающие статьи:
Раздел 11. Работа с файлами, I/O и сетью (NIO.2)
Глава 1. Классический Java I/O (java.io (https://java.io/))
Байтовые потоки: абстрактные классы InputStream и OutputStream
FileInputStream – чтение байтов из файла. Путь данных в памяти JVM
FileOutputStream – запись байтов в файл. Путь данных от heap к диску
Проблема производительности побайтового ввода/вывода. Идея буфера
BufferedInputStream – буферизованное чтение. Путь данных через память JVM
[Совет по Java #045]
Тема: volatile не гарантирует атомарность.
[Совет по Java #046]
Тема: java.lang.Enum не может наследовать другой класс, потому что уже наследует Enum
[Совет по Java #047]
Тема: clone() — опасный метод с неясной семантикой.
[Совет по Java #048]
Тема: finalize() — устаревший и непредсказуемый.
[Совет по Java #049]
Тема: System.gc() не гарантирует запуск сборщика мусора.
Полезные статьи и видео:
Ты не хочешь стать программистом.
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
Предыдущий пост(с 23.05 по 29.05)
Запись встреч/видео:
14. Transactional Outbox: как гарантировать публикацию события
Обучающие статьи:
Раздел 11. Работа с файлами, I/O и сетью (NIO.2)
Глава 1. Классический Java I/O (java.io (https://java.io/))
Байтовые потоки: абстрактные классы InputStream и OutputStream
FileInputStream – чтение байтов из файла. Путь данных в памяти JVM
FileOutputStream – запись байтов в файл. Путь данных от heap к диску
Проблема производительности побайтового ввода/вывода. Идея буфера
BufferedInputStream – буферизованное чтение. Путь данных через память JVM
[Совет по Java #045]
Тема: volatile не гарантирует атомарность.
[Совет по Java #046]
Тема: java.lang.Enum не может наследовать другой класс, потому что уже наследует Enum
[Совет по Java #047]
Тема: clone() — опасный метод с неясной семантикой.
[Совет по Java #048]
Тема: finalize() — устаревший и непредсказуемый.
[Совет по Java #049]
Тема: System.gc() не гарантирует запуск сборщика мусора.
Полезные статьи и видео:
Ты не хочешь стать программистом.
Как и всегда, задачи можно найти под тегом - #Tasks, вопросы с собеседований - #собеседование
👍2
Forwarded from ChatRoom (Java for Beginner) (Первожрец Java)
Я вот сижу продумываю систему оценки статей на deforge. Есть идеи? Как по вашему как это красиво реализовать? Чем хороши или плохи системы оценок и комментариев на Reddit StackOverflow или Хабр?
👍1