Hacker News Digest

Тег: #jvm

Постов: 8

Writing your own BEAM (martin.janiczek.cz)

Автор исследует, сколько усилий требуется для реализации собственных примитивов BEAM, создавая упрощенную версию виртуальной машины на Elm. Используя стиль передачи продолжений (CPS), он избегает необходимости писать парсер, CLI и другие компоненты полноценного компилятора, сосредоточившись на ядре системы. Этот подход позволяет сосредоточиться на основных концепциях, таких как планировщик, процессы и их взаимодействие.

Начав с базовых инструкций End (завершение программы) и Work (имитация выполнения работы), автор добавляет примитив Spawn для создания процессов, что требует изменения структуры планировщика для отслеживания нескольких процессов. В планах реализация обмена сообщениями, выборочного приема и связывания процессов для создания деревьев надзора. Ключевой особенностью подхода является использование CPS для упрощения реализации, где продолжения обрабатывают управление потоком выполнения.

by cbzbc • 09 ноября 2025 г. в 18:29 • 250 points

ОригиналHN

#beam#elm#cps#processes#scheduling#linux#jvm#nix

Комментарии (79)

  • Обсуждение в основном вращается вокруг BEAM: его происхождение, ограничения и будущее.
  • Участники обсуждают, что BEAM не переносим между дистрибутивами Linux, в отличие от JVM, и требует компиляции из исходников.
  • Поднимается вопрос о том, что написание статьи не объясняет читателям, что такое BEAM, и что это значит для них.
  • Некоторые участники предлагают использовать Nix или статически слинкованный BEAM для решения проблемы портируемости.
  • Также обсуждается, что исходный код BEAM доступен, и что ранние версии BEAM, возможно, были бы полезны для изучения.

JVM exceptions are weird: a decompiler perspective (purplesyringa.moe)

Автор исследует сложность обработки исключений JVM при декомпиляции Java-байткода. Изначально предполагалось, что метод декомпиляции управляющих потоков, разработанный автором, можно легко расширить для обработки исключений, но оказалось, что множество крайних случаев значительно усложняют задачу. JVM использует стековую архитектуру, где обычные управляющие конструкции реализуются явно, а исключения обрабатываются неявно через отдельную таблицу исключений. Эта таблица связывает регионы инструкций с обработчиками, но JVM не требует соблюдения иерархической вложенности обработчиков, что приводит к пересекающимся диапазонам и нарушает интуитивные ожидания.

Реальные Java-файлы часто содержат такие "неестественные" конструкции, что делает проблему важной для любого декомпилятора. Автор также отмечает сложность обработки try...finally блоков, где код finally должен выполняться независимо от возникновения исключения, но передача управления после его завершения зависит от контекста. Эти особенности байткода и компилятора javac создают значительные препятствия для создания корректного декомпилятора, особенно при попытке восстановления исходной структуры кода.

by vrnvu • 04 ноября 2025 г. в 09:08 • 146 points

ОригиналHN

#java#jvm#decompilation#bytecode#exceptions#javac#csharp

Комментарии (46)

  • Обсуждение началось с примера кода, который выглядит как баг, но на самом деле является корректным поведением в Java и других языках, где finally блок не может перехватить return/throw, но может перехватить continue/break.
  • Участники обсудили, что в действительности это не баг, а фича, и что в большинстве языков finally не может перехватить return/throw, но может перехватить continue/break.
  • Обсуждались также вопросы, что в некоторых языках, таких как C#, такие конструкции вообще не допускаются.
  • Также было отмечено, что в Java 25 такой код будет компилироваться и работать, но в более ранних версиях Java это вызовет ошибку компиляции.

ECL Runs Maxima in a Browser (mailman3.common-lisp.net)

by seansh • 03 ноября 2025 г. в 06:21 • 107 points

ОригиналHN

#common-lisp#abcl#maxima#android#ndk#jvm

Комментарии (11)

  • ABCL не поддерживает Android, а Maxima и другие легаси-проекты были удалены из Play Store.
  • Пользователи жалуются на производительность ABCL и отсутствие нативных библиотек.
  • Некоторые предпочитают NDK-инструменты, чтобы избежать любой зависимости от JVM.
  • Проект в браузере выглядит как open-source-альтернатива Mathematica/Maple, но без четкой документации.

Effect Systems vs. Print Debugging: A Pragmatic Solution (blog.flix.dev)

Системы эффектов в языках программирования, такие как в Flix, строго контролируют побочные действия вроде вывода в консоль, что мешает привычной отладке с помощью println. Ложь системе эффектов через unchecked_cast приводит к проблемам: компилятор удаляет «бесполезный» код без видимых эффектов или ломает семантику при оптимизациях.

Flix ищет прагматичный баланс между строгостью и удобством, предлагая временные решения для отладки без нарушения гарантий. Например, вводят функцию dprintln, которая обманывает систему эффектов, но рискует быть удалённой оптимизатором. Ключевой вывод: языки должны позволять гибкость там, где она нужна, без компромисса с безопасностью.

by degurechaff • 22 сентября 2025 г. в 17:54 • 76 points

ОригиналHN

#flix#effect-systems#debugging#jvm#java#haskell#optimization#parallelism

Комментарии (35)

  • Обсуждается подход Flix к типизации эффектов, включая системные (например, Debug) и возможность создания пользовательских эффектов.
  • Рассматриваются целевые use-case языка: платформенная независимость, совместимость с JVM/Java, применение в бэкенде и академические цели.
  • Поднимаются вопросы о практичности системы эффектов: необходимость для оптимизаций, потенциальная избыточность и сложность.
  • Обсуждается проблема автоматической параллелизации и оптимизации, включая риски переупорядочивания или удаления операций ввода-вывода.
  • Упоминаются аналогичные реализации в других языках (Haskell, Koka, Roc, Effekt) и их эволюция в моделировании эффектов.

Safepoints and Fil-C (fil-c.org)

Safepoints — это ключевой механизм синхронизации в Fil-C и других виртуальных машинах, обеспечивающий безопасность памяти в многопоточной среде. Они позволяют потокам делать предположения о состоянии VM и сообщать о своём текущем состоянии, что критично для точного сборщика мусора, отладки и профилирования. Без safepoints не было бы возможности безопасно сканировать стеки, обрабатывать сигналы или использовать fork.

Fil-C вставляет pollchecks — проверки на необходимость остановки — на каждом обратном ребре управления в коде. Это короткая инструкция вроде testb, которая при срабатывании переходит к медленному пути обработки. Такой подход гарантирует, что GC может прервать поток только в безопасных точках, избегая проблем с регистрами или векторными инструкциями, и сохраняя корректность без invasive изменений в компиляторе.

by matt_d • 16 сентября 2025 г. в 04:29 • 76 points

ОригиналHN

#fil-c#safepoints#garbage-collection#multithreading#pollchecks#memory-safety#assembly#fork#vfork#jvm

Комментарии (41)

  • Fil-C использует механизм pollchecks для остановки потоков (stop-the-world), что необходимо для корректной работы fork(2), но поддержка vfork(2) пока отсутствует и требует нестандартных решений.
  • Внедрение safepoint-ов в ассемблерный код рискованно и может нарушить предположения Fil-C о безопасности памяти; в долгосрочной перспективе планируется создать способ написания безопасного ассемблерного кода.
  • Подход Fil-C к сборке мусора с опросом точек остановки (polling) создает нагрузку в tight loops, что решается разными оптимизациями (например, разверткой циклов), в отличие от асинхронных сигналов в Go.
  • Мнения о читаемости и понятности реализации Fil-C разделились: одни участники находят ее интересной и хорошо объясненной, другие признаются, что не до конца понимают детали.
  • Утверждение, что Java использует исключительно compacting GC, является упрощением, учитывая множество доступных конфигураций сборщика мусора в разных реализациях JVM.

Java 25's new CPU-Time Profiler (mostlynerdless.de)

Java 25: новый CPU-Profiler (1)

В JDK 25 появился экспериментальный CPU-Profiler — метод-сэмплер, который показывает, сколько процессорного времени тратит каждый метод, а не просто «время выполнения». Это важно: метод, ждущий I/O, занимает процессор лишь доли миллисекунды, и старый sampler не видит разницы между ним и вычислительно тяжёлым кодом.

Старый JFR-сэмплер каждые 10–20 мс выбирает 5 Java-потоков и 1 native, просто пробегая по списку. На 32-ядерной машине это превращает заявленный интервал 10 мс в фактические 53 мс, а при смеси Java и native потоков приоритет всегда получают Java. Результат — искажённая картина.

Новый профилировщик измеряет именно CPU-time, позволяя найти узкие места, которые реально жгут ядра, и повысить throughput без догадок.

by SerCe • 13 сентября 2025 г. в 08:11 • 178 points

ОригиналHN

#java#jvm#profiling#performance#jfr#loom#cpu

Комментарии (98)

  • JVM за последние годы стал двигателем инноваций: виртуальные потоки, Loom и быстрый цикл релизов делают Java снова «весёлой».
  • Большинство участников рады избавлению от реактивного async-кода: «пусть всё будет синхронно и просто».
  • Скептики напоминают: виртуальные потоки всё-таки тратят CPU на GC и не решают проблемы доступа к ограниченным ресурсам.
  • Кто-то жалуется на качество современных Java-разработчиков, другие отвечают: плохие devы есть везде, язык тут не при чём.
  • Автор серии постов анонсировал три продолжения про новый CPU-Tracing в Java 25.

Clojure's Solutions to the Expression Problem (infoq.com)

Clojure и «проблема выражений»

  • Проблема: добавлять новые типы данных и новые операции без перекомпиляции всего кода и без нарушения существующих вызовов.
  • ООП-языки решают лишь половину: легко новый класс, трудно новый метод.
  • Функциональные языки наоборот: легко новая функция, трудно новый вариант данных.

Как Clojure объединяет лучшее

  1. Протоколы

    • Описывают набор методов без привязки к типу.
    • Реализуются для любого существующего класса поздно, «извне».
    • Компилируются в обычный Java-интерфейс, быстрый вызов.
  2. Мультиметоды

    • Выбор реализации по произвольной функции-диспетчеру (тип, значение, метаданные).
    • Позволяют «разрезать» иерархию по другим осям, не только по классу.
  3. Records и types

    • defrecord создает неизменяемую структуру с заранее известными полями и автоматическим доступом по ключам как к карте.
    • deftype даёт полный контроль, поля хранятся примитивно, без лишних обёрток.
  4. reify

    • «Анонимный класс» на Clojure: создаёт объект, реализующий нужные протоколы/интерфейсы, без отдельного файла.

Практический итог

  • Новый тип → defrecord/deftype + реализация нужных протоколов.
  • Новая операция → добавляем метод в протокол и реализуем для всех существующих типов.
  • Старый клиентский код не трогается, компиляция не требуется.

by adityaathalye • 07 сентября 2025 г. в 19:31 • 141 points

ОригиналHN

#clojure#functional-programming#object-oriented-programming#protocols#multimethods#datomic#selenium#immutability#jvm#repl

Комментарии (16)

  • Протоколы в Clojure теперь умеют диспатчиться по метаданным, а не только по типу.
  • Участники скучают по временам, когда посты о продуктивности были про REPL, функциональность, композабельность и иммутабельность.
  • Поделились ссылкой на демонстрацию решения «expression problem» в Clojure.
  • Люди недооценивают готовые решения вроде Datomic и вместо этого пишут свои костыли.
  • Один из участников вспомнил, как в 2013–15 писал тесты на Clojure и расширял фреймворк для Selenium.

Clojure Async Flow Guide (clojure.github.io)

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

Библиотека flow отделяет бизнес-логику от развёртывания: топологии, исполнения, обмена сообщениями, жизненного цикла, мониторинга и обработки ошибок.

step-fn и процессы

Логика описывается функциями step-fn, которые flow заворачивает в процессы, крутящиеся в цикле. step-fn не работают с каналами напрямую и не хранят состояние, поэтому легко тестируются и переиспользуются.

step-fn имеет четыре арности:

describe (step-fn) → descriptor

Возвращает статическое описание :params, :ins, :outs — карты имя → документация. Имена входов и выходов не должны пересекаться.

{:params {:size "Максимальный размер"}
 :ins    {:in  "Входной канал"}
 :outs   {:out "Выходной канал"}}

init (step-fn arg-map) → init-state

Один раз вызывается при старте процесса; превращает параметры из flow-def в начальное состояние.

transition (step-fn state transition) → state'

Вызывается при переходах жизненного цикла (::flow/start, ::flow/stop, ::flow/pause, ::flow/resume). Используется для управления внешними ресурсами.

transform (step-fn state input msg) → [state' {out-id [msgs]}]

Вызывается для каждого входящего сообщения. Возвращает новое состояние и карту выходных сообщений. Выход может быть пустым, но каждое сообщение — не nil. Исключения логируются в :error-chan.

Состояние процесса

Карта с любыми ключами. Дополнительно:

  • ::flow/pid — идентификатор процесса
  • ::flow/in-ports, ::flow/out-ports — карты cid → внешний канал (создаётся в init)
  • ::flow/input-filter — предикат cid для фильтрации входных каналов

Хелперы

  • lift*->step — из f(x) → coll делает step-fn с одним входом и выходом
  • lift1->step — то же, но f(x) → single-value
  • map->step — из карты с ключами :describe, :init, :transition, :transform строит step-fn

Запуск процесса

Функция process принимает step-fn и опции:

  • ::workload:mixed, :io, :compute
  • :compute-timeout-ms — таймаут для :compute (по умолчанию 5000 мс)

by simonpure • 18 августа 2025 г. в 00:52 • 190 points

ОригиналHN

#clojure#core.async#flow#concurrency#functional-programming#jvm#genstage#elixir

Комментарии (74)

  • Участники обсуждают, жив ли Clojure: сообщество стабильно, но менее хайповое; NuBank расширяет core-команду и нанимает Developer Advocate.
  • core.async.flow предлагает декларативный, фиксированный граф каналов для «структурированной конкурентности»; ошибки и паузы можно отслеживать, но изменять топологию на лету пока нельзя.
  • Сравнивают с GenStage (Elixir), Manifold, Trio и missionary/electric; можно использовать как OS-, так и green-потоки.
  • JVM-тулчейн вызывает у новичков страх, но Leiningen/deps.edn упрощают работу, а отладка всё же возможна.
  • Clojure-окосистема активно развивается: Babashka, XTDB, Dyna3 и другие проекты; язык недавно получил мажорный релиз и готовится к виртуальным потокам JVM.