1 ポイント 投稿者 GN⁺ 2024-11-12 | 1件のコメント | WhatsAppで共有
  • JVMの内部知識を小さな単位に分けて扱う進行中のミニポストシリーズで、各記事は1つのテーマ・テスト・ベンチマーク・観察に集中している
  • 各ポストは5〜10分で読める分量を目標としており、JVMの要素同士が相互に作用することを前提としている
  • 根拠や議論は逸話的である場合があり、誤り・一貫性・文体・文法・重複の見直しが十分でない可能性があるため、そのまま信頼するには注意が必要
  • 全体のまとめはePUB, MOBI, PDFで提供され、PDFは高品質変換のため容量が数十MB級である
  • 個別記事の索引はCompiler、Runtime、GC、Libraryの軸に分かれており、ロック最適化、TLAB、GC停止、String.intern()、safepoint、圧縮参照、条件付き移動のようなJVM内部トピックを扱う

シリーズを読む際の前提

  • JVM Anatomy Quarksは、JVMの基本知識を短い記事単位で整理する進行中のミニポストシリーズである
  • 各ポストは1つのテーマ、テスト、ベンチマーク、観察を深く掘り下げる形式である
  • 単一のポストだけを切り離して見ると文脈が不足することがあり、扱う要素の大半は相互に作用しやすい
  • 記事の根拠や議論は逸話的である場合があり、誤り、一貫性、文体、文法、意味、重複の見直しが十分でない可能性がある
  • 内容を利用または信頼する際は、読者自身がリスクを負う必要がある

まとめファイルと索引構造

  • シリーズ全体のまとめは3つの形式で提供される
    • ePUBは最も小さく1MB未満で、PandocのHTML-to-ePUBベース
    • MOBIは小さく数MB級で、KindleGenのePUB-to-MOBIベース
    • PDFは数十MB級で非常に大きく、wkhtmltopdfのHTML-to-PDFベースの高品質出力
  • 個別索引はCompiler, Runtime, GC, Library分類で構成される

テーマ別記事一覧

  • Compiler中心の項目

    • #1: Lock Coarsening and Loops
    • #14: Constant Variables
    • #15: Just-In-Time Constants
    • #16: Megamorphic Virtual Calls
    • #17: Trust Non-Static Final Fields
    • #18: Scalar Replacement
    • #19: Lock Elision
    • #20: FPU Spills
    • #25: Implicit Null Checks
    • #27: Compiler Blackholes
    • #28: Frequency-Based Code Layout
    • #29: Uncommon Traps
    • #30: Conditional Moves
  • RuntimeとGCの両方にまたがる項目

    • JVM実行中のメモリと停止動作を扱う記事群である
    • #2: Transparent Huge Pages
    • #4: TLAB Allocation
    • #5: TLABs and Heap Parsability
    • #6: New Object Stages
    • #7: Object Initialization Costs
    • #9: JNI Critical and GC Locker
    • #22: Safepoint Polls
  • GC中心の項目

    • コレクタ設計とヒープ動作を中心に扱う
    • #3: GC Design and Pauses
    • #11: Moving GC and Locality
    • #13: Intergenerational Barriers
    • #21: Heap Uncommit
  • Runtime中心の項目

    • JVM実行環境とオブジェクト表現を扱う記事群である
    • #12: Native Memory Tracking
    • #23: Compressed References
    • #24: Object Alignment
    • #26: Identity Hash Code
  • Libraryまたは複合分類の項目

    • Libraryまで含まれる項目として#10: String.intern()がある
    • CompilerとRuntimeが併記される項目として#16#25#29#30がある

1件のコメント

 
GN⁺ 2024-11-12
Hacker Newsのコメント
  • https://shipilev.net/jvm/anatomy-quarks/17-trust-nonstatic-f... は本当に残念な事例
    一部のフレームワークが JNI とリフレクションを乱用し、本来は不変であるべき final フィールドを書き換えてきたため、ユーザーコードはシステム提供クラスでのみ可能な 重要な最適化 を享受できていない
    プラットフォーム、特にコンパイラとランタイムは、将来の最適化の余地を守るために 意味論的制約 を非常に厳格に強制すべき

    • 私たちは integrity by default 戦略 [1] の一環としてこの部分を変更しており、近いうちに関連する JEP が出る予定
      実際に final を変更しなければならないコードは多くなく、今でもその操作は自分のモジュール内のクラス、または明示的に open されたクラスに制限されているので、今後は final を変更しようとするモジュールに対してアプリケーションが権限を付与する方式になる見込み
      最近ネイティブ呼び出しや安全でないメモリアクセスに適用した方式と似ている
      [1]: https://openjdk.org/jeps/8305968
    • Effective Java を盲目的に受け入れ、何にでも final を付けろ という原罪を作った面もあるのではないかと思う
      そのせいで今ではテストで final クラスを簡単にモックできず、モックツールは final クラスをモックするために バイトコード操作 までしなければならない
      例えば Google 社内では Effective Java が要件で、公開 GDrive API にも final クラスがあるが、外部 API こそモックしたい対象
    • System.out の事例は Java 自体の問題
      https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.htm...
      こうした前例があるのだから、他の人たちも許容されるやり方だと考えたとしても不思議ではない
    • フィールド修飾子は セキュリティ制約 ではなく意味論的制約
      適切な回避手順を踏めば、これを回避できるべき
      重要なのは安全性で、変更不可能なものを書き換えて SEGV を引き起こせてしまう可能性があるからであり、アクセス制御子が対処しようとしている懸念もまさにそこ
    • ずっと前に消えた内部ライブラリで面倒なリファクタリングを避けるために、メンバーを “un-final” にして、変更して、再び final のように戻す 邪悪な3行コード を自分で書いたことがあると認める
      できないように塞がれていてほしかったが、ビジネス上の要件があった
  • 少し話は変わるが、Apple が Swift Java ブリッジ を新たに公開し、かなりクール
    JNI と Panama の両方をサポートしており、先週はこれを Android に移植していた
    https://github.com/swiftlang/swift-java

    • これを「モダン」と呼べるなら、最近の クロスプラットフォームのアプローチ は興味深い
      言語間の相互運用性のおかげで、適切な場合には1つのライブラリを複数のプラットフォームで共有できる
      これまでは C++ でのみ、必要なら C API を付ける形でやってきたが、C++ 自体が不要な状況では、当然ながら第一選択の言語ではない
      ただしコストは気になる。モバイルアプリで Swift が Kotlin ライブラリを簡単に呼び出せるなら、iOS アプリは何らかの形で JVM のようなものをロードしなければならないのではないかと思うし、逆に Android アプリで Swift を呼ぶなら Swift ランタイムをロードすることになりそう
      結局オーバーヘッドが発生する
      いつか開発者が Swift ライブラリに依存し、そのライブラリが Kotlin ライブラリに依存して JVM を起動し、さらに JNI で C++ を呼び出す、という構成が当たり前になるのではと心配している
      これは現代のパッケージマネージャのように、直接依存は数個しかなくても、「簡単すぎて気にしなかった」結果、プログラムがあっという間に 100個以上の推移的依存関係 を抱える状況に似ている
  • この良い記事シリーズがここで共有されてうれしい。このシリーズを見て JVM について多くを学んだ
    特に、Java でよく「スタック割り当て」と呼ばれる表現が誤りだとするこの記事が気に入っている: https://shipilev.net/jvm/anatomy-quarks/18-scalar-replacemen...
    JVM が実際にやっているのは エスケープ解析 + スカラ置換

  • これらの記事の 分量 が気に入っている
    数分で1本をさっと読めるし、その気になればベンチマークをローカルで回してみることもできる

  • JVM ベースの言語で数年働いたことがあるなら、この記事シリーズは本当に興味深い
    数年前に初めて読み進めたときのことを覚えている

  • このシリーズ名がなぜ『JVM Anatomy Park』から変わったのか知っている人はいる?

    • Justin Rolland のオンラインでの振る舞いに関する話が最初に知られ始めた頃に名前を変えたようだ
  • Javaはほとんど忘れて過ごすようになった。
    新しいプロジェクトをJavaで始めようとはまったく思わない。
    迅速な開発と柔軟性が必要ならPython、ガベージコレクションのある方式で大量のI/O並行性を扱いたいならGo、コンパイル言語でバランスの取れた良い言語が必要ならSwift、性能と安全性が必要なコンパイル言語ならRustを選ぶと思う。
    個人的な好みにすぎないし、KotlinがJavaをより使いやすくしたことは分かっているが、それでもそう感じる。

    • 自分だけがそうというわけではないだろうが、たぶんJavaが不要な状況なのだと思う。
      Javaの主な強みは、Java経験のある開発者がほぼ無限にいて、既存ライブラリが膨大で、その多くがエンタープライズ志向であり、多くの貢献者がいる非常に大きなコードベースを管理しやすく、数十年にわたって開発されてきた標準VMが非常に堅牢でかなり高速で、事実上あらゆるプラットフォームでサポートされている点だ。
      2000年代初頭ほど、さらにはエンタープライズでさえ、圧倒的な支配力を持っているわけではなく、典型的な「blub」言語ではあるが、エンタープライズ規模を見込んでいて、純粋な性能よりも多数の開発者へ拡張できることのほうが重要なら、十分に合理的な選択だ。
      Rustは好きだが、生活費を稼がせてくれるのはJavaだ。
    • 他の回答に付け加えるなら、Javaはスタートアップに必要な特性も十分に備えているので、新規プロジェクトに使うのも理にかなっている。
      モダンなフレームワークとAI支援のおかげで、そこそこのバックエンドを数日で立ち上げられる。
      1人の技術系共同創業者なら、MVPを素早く作るためにJavaかKotlin、それにフロントエンドスタック程度を知っていればよく、実際にはコーディング以外の作業にずっと多くの時間を使うので、言語機能の差はそれほど重要ではなくなる。
      モバイルネイティブに行くなら、Swiftが第2の言語になるかもしれない。
      また、しばらくの間はスケーラビリティが最初の問題にならない可能性が高い。先に問題になるのはチームの拡大で、性能ボトルネックが目立つのはずっと後になる可能性が高い。
      Javaは大きなチームに向いている。
      ビジネスの観点から、より大きな人材プール、速いデリバリーサイクル、長期的に中核スタックとして残せるものを望むなら、JavaかKotlinがおそらく最善だ。
      特定の開発者層を引きつけるために魅力的な技術を福利厚生のように打ち出したい、あるいは珍しいビジネス事例があるなら、GoやRustを選ぶこともできる。
      Pythonは学界やブートキャンプで人気だが、汎用バックエンドにおけるビジネス価値は正直よく分からない。
    • JVM上にはClojureのような非常に使いやすい言語がたくさんある。
      JVM全体を無視することはしない。JVMは工学的傑作であり、最近も急速に進化している。Loom、Panama、Leydenを見れば分かる。
    • 炎上しやすいコメントに炎上しやすい返答をするなら、Javaはあらゆる面でGoより優れていて、あなたが挙げたほぼすべてのケースの90%はJavaで処理できる。
      だから、ほとんどあらゆるものに対してJavaはかなり明確に良い選択だ。
    • あなただけがそうというわけではないが、全員がそうというわけでもない。
      Java 21+と組み合わせたKotlinは、I/O中心のサービスでも、事実上どんなサービスでも、私の第一選択の組み合わせだ。
      本当に使いやすく、仮想スレッドのおかげでGoと同じくらいシンプルで効率的なコードが書けるうえ、世界最大級で質も高いライブラリエコシステムを活用できる。
      GoやPythonをけなすつもりはない。好みのツールなら十分に良い。
      ただ、Javaは思っているほど無関係な存在にはなっていない。