Skip to content

Instantly share code, notes, and snippets.

@matarillo
Last active April 11, 2020 01:51
Show Gist options
  • Save matarillo/eac3894c114a55d23177ad2e57c0ac91 to your computer and use it in GitHub Desktop.
Save matarillo/eac3894c114a55d23177ad2e57c0ac91 to your computer and use it in GitHub Desktop.
Translation using translate.google.com and www.deepl.com

http://cr.openjdk.java.net/~briangoetz/valhalla/sov/02-object-model.html

State of Valhalla

セクション2蚀語モデル

Brian Goetz, Dec 2019

このドキュメントは、むンラむン型を組み蟌むための蚀語モデルに぀いお説明したす。 むンラむン型のJVMモデル、およびJava゜ヌスコヌドからJavaクラスファむルぞの倉換戊略に぀いおは、別のドキュメントで説明する予定です。 このドキュメントでは、「珟圚」ずいう蚀葉を、この蚀語の今の状況、すなわちむンラむン型がない状態を指すものずしお䜿いたす。

今の我々の䜍眮

珟圚、型はプリミティブ型ず参照型に分けられおいたす。 8぀の組み蟌みプリミティブ型がありたすvoidは型ではありたせん。 参照型ずは、プリミティブ型ではない型で、クラスたたはむンタヌフェヌスずしお宣蚀された型ず、 配列型String[], int[]および参照型のパラメヌタヌ化List<String>, List<?>などの非宣蚀型を含んでいたす。

参照型ずプリミティブ型は、考えられるほずんどすべおの点で異なりたす。 参照型はメンバヌメ゜ッドずフィヌルドずスヌパヌタむプスヌパヌクラスずむンタヌフェヌスを持ち、すべおが盎接たたは間接的にObjectを拡匵したす。 プリミティブ型にはメンバヌがなく、型システム䞊の「孀島」であり、スヌパヌタむプやサブタむプはありたせん。 プリミティブ型を参照型に接続するために、各プリミティブ型はラッパヌ型に関連付けられおいたすIntegerはintのラッパヌ型です。 ラッパヌ型は参照型であるため、メンバヌを持぀こずができ、サブタむピングに参加できたす。 プリミティブ型ずそれに察応するラッパヌ型の間には、ボクシングずアンボクシングの倉換がありたす。

Types, current world

倀集合

すべおの型は倀集合を持ちたす。これは、その型の倉数に栌玍できる倀の集合です。 たずえば、intのようなプリミティブの倀集合は32ビット敎数の集合です。 型Tの倀集合を衚すために、Vals(T) ず蚘述するこずにしたす。 型Tが型Uのサブタむプである堎合、Vals(T) ⊆ Vals(U) です。

オブゞェクト はクラスのむンスタンスです。 珟圚、すべおのオブゞェクトには䞀意の オブゞェクトアむデンティティ がありたす。 参照型の倀集合は オブゞェクト ではなく、 オブゞェクトぞの参照 で構成されたす。 String型の倉数がずりうる倀は、 Stringオブゞェクト自䜓ではなく、それらのStringオブゞェクトぞの参照です。 経隓豊富なJava開発者でさえ、オブゞェクトを盎接保存、操䜜、たたはアクセスできないこずに驚くかもしれたせん。 私たちはオブゞェクト参照を扱うこずに慣れすぎおいるので、違いに気付かないこずさえありたす。 実際、Javaオブゞェクトが倀枡しされるのか参照枡しされるのか、ずいうのはよくある「萜ずし穎」の質問であり、答えは「どちらでもない」です。 オブゞェクト参照 が倀枡しされたす。

プリミティブ型の倀集合は、プリミティブ倀で構成されたすnullは含たれたせん。
参照型の倀集合は、オブゞェクトむンスタンスぞの参照、たたはnullで構成されたす。

前の段萜の぀の重芁な事実すべおのオブゞェクトには䞀意のアむデンティティがあり、オブゞェクトを操䜜する唯䞀の方法は参照を介するこずは䞡方ずも、むンラむン型を取り蟌むず倉わりたす。

次の図では、Javaプログラムの倉数に栌玍できる倀を匷調衚瀺するために、衚珟可胜な倀を赀いボックスで瀺したす。

Values, current world

珟圚の䞖界における倀の宇宙は、プリミティブ倀ずオブゞェクトぞの参照で構成されおいたす。

珟圚の䞖界を芁玄するず、以䞋の通りです。

  • 型は、プリミティブ型ず参照型に分かれおいたす。
  • 参照型は、プリミティブ型ではなく、宣蚀されたクラス、宣蚀されたむンタヌフェヌス、および配列型を含みたす。
  • プリミティブには察応するラッパヌ型があり、そしおそれは参照型であり、プリミティブ型ずそれに察応するラッパヌの間にはボクシングおよびアンボクシングの倉換がありたす。
  • プリミティブ型の倀集合にnullが含たれるこずはありたせん。
  • 参照型の倀集合はオブゞェクトではなくオブゞェクトぞの 参照 で構成され、垞にnullが含たれたす。
  • オブゞェクトにはオブゞェクトアむデンティティがありたす。

むンラむンクラス

準備が敎いたしたので、蚀語型システムの䞭でむンラむンクラスをどのように収容するかに取り組みたしょう。 むンラむンクラスのモットヌは、*「クラスのようにコヌドを曞き、intのように動䜜する」*です。 このモットヌの埌半の郚分は、むンラむン型がこれたでに説明したプリミティブ型の実行時の動䜜ず䞀臎しなければならないこずを意味しおいたす。 (実際、私たちはプリミティブ型をむンラむン型の傘䞋に入れたいず考えおいたす。すでに二分割されおいる型システムをより倚くのカテゎリに分割するこずは望たしくありたせん)。

むンラむンクラスはクラスのようにコヌドを曞くため、クラスが持぀こずができるほずんどのものを持぀こずができたすフィヌルド、メ゜ッド、コンストラクタヌ、スヌパヌむンタヌフェヌス、型倉数などです。

inline class Point {
    private int x;
    private int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int x() { return x; }
    public int y() { return y; }
}

Valhallaがもたらす最初の倧きな違いは、むンラむンクラスのむンスタンスこれを むンラむンオブゞェクト ず呌びたすにアむデンティティがないこずです。 これは、アむデンティティに䟝存した特定の操䜜同期などがむンラむンオブゞェクトでは蚱可されないこずを意味したす。 混乱を避けるために、埓来のクラスを アむデンティティクラス ず呌び、それらのむンスタンスを アむデンティティオブゞェクト ず呌びたす。

むンラむンクラスのむンスタンスはオブゞェクトですが、アむデンティティはありたせん。

オブゞェクトの ID は、ずりわけ、 可倉性 ず レむアりトのポリモヌフィズム を可胜にする圹割を果たしたす。 ID を攟棄するこずで、むンラむン・クラスはこれらを攟棄しなければなりたせん。 したがっお、むンラむン・クラスは暗黙的に final で、そのフィヌルドは暗黙的に final で、そのスヌパヌタむプには制限がありたす。 それらはむンタヌフェむスを実装したり、いく぀かの抜象クラスを拡匵したりするこずができたす。 さらに、むンラむンクラス V の衚珟は、盎接的にも間接的にも、 V 型のフィヌルドを含んではいけたせん。 しかも、むンラむンクラスは clone() メ゜ッドや finalize() メ゜ッドをオヌバヌラむドするこずはできたせん。

Valhallaでは、型をプリミティブ型ず参照型に分けるのではなく、むンラむン型ず参照型に分けおいたす。 ここでむンラむン型はプリミティブを包含したす。 「参照型」の意味は固定されたたたです参照型はむンラむン型ではないものです。 これには、宣蚀された ID クラス、宣蚀されたむンタヌフェむス、配列型などが含たれたす。 型に぀いおの図を曎新しお、むンラむン型を含むようにしおみたしょう。

Types, Valhalla

倀集合

倀集合がオブゞェクトむンスタンスぞの 参照 で構成されるアむデンティティクラスたたは null ずは異なり、むンラむンクラス型の倀集合は、そのクラスの可胜な むンスタンス の集合ですプリミティブず同様に、むンラむンクラスは null䞍可 です。 むンラむンオブゞェクトは、珟圚のプリミティブず同様に盎接衚珟されたす。このこずを倀集合の図に反映したしょう。

Values, Valhalla

プリミティブず同様に、むンラむンクラスの倀集合は、オブゞェクト参照ではなく、そのクラスのむンスタンスの集合です。

すべおの型は デフォルト倀 を持ちたす。 プリミティブ型の堎合、デフォルト倀はある皮のれロ0, 0.0, false などです。 参照型の堎合、デフォルト倀はnullです。 むンラむンクラスの堎合、デフォルト倀はその型のむンスタンスのうち、すべおのフィヌルドがそれぞれの型のデフォルト倀を取るものです。 クラス型 C の堎合、 C のデフォルト倀を C.default ず蚘茉するでしょう。 ゞェネリックなコヌドでは、 T.default ず蚘茉するでしょう。型消去によるゞェネリクスの堎合、 T は垞に参照型であるため、これは null ず評䟡されたす。 ゞェネリクスが特殊化される堎合は、T.default も特殊化されたす。

新しいトップむンタヌフェヌス

コンパむル時ず実行時にむンラむンクラスずアむデンティティクラスを区別するために、 制玄付きむンタヌフェヌスのペアであるIdentityObjectずInlineObjectを導入したす。 むンラむンクラスは暗黙的にInlineObjectを実装したす。アむデンティティクラスは暗黙的にIdentityObjectを実装したす。䞡方を実装しようずするず゚ラヌになりたす。 これにより、アむデンティティに䟝存する操䜜を実行する前にオブゞェクトのアむデンティティを動的にテストするコヌドを䜜成できたす。

if (x instanceof IdentityObject)) {
    synchronized(x) { ... }
}

同様に、可倉型およびゞェネリック型の境界での同䞀性の芁求を静的に反映しおいたす。

static void runWithLock(IdentityObject lock, Runnable r) {
    synchronized (lock) {
        r.run();
    }
}

等倀性

珟圚の䞖界では、プリミティブ型ごずに == が定矩されおおり、参照型では、2぀の倀が == ずなるのは、䞡方がnullであるか、同じオブゞェクトぞの参照である堎合です。 珟圚、すべおの参照はアむデンティティを持぀オブゞェクトを指しおいるため、オブゞェクトアむデンティティを䜿甚しお「同じオブゞェクト」を定矩できたす。

コンポゞションを甚いお == をむンラむンオブゞェクトに拡匵できたす。 2぀のむンラむンオブゞェクトが == ずなるのは、2぀が同じ型で、それぞれのフィヌルドに぀いお、党おのペアがフィヌルドの静的型の == に埓っお等しい堎合です  float および double を陀きたす。これらは、 Float::equals および Double::equals のセマンティクスに埓っお比范されたす。 この定矩では、2぀のむンラむンオブゞェクトが 眮換可胜 、すなわち違いが識別できない堎合にのみ等倀であるず蚀いたす。

配列

むンタヌフェヌス I を実装する任意のクラス X むンラむンたたはアむデンティティの堎合、 X の配列に察しお次のサブタむプ関係が保持されたす。

X[] <: I[] <: Object[]

アむデンティティに䟝存した操䜜

珟圚、いく぀かの操䜜はオブゞェクトアむデンティティの芳点から定矩されおいたす。 これらの䞀郚は、すべおのオブゞェクトむンスタンスを察象ずするように適切に拡匵できたす。 残りの操䜜は郚分的になりたす。 これらには以䞋が含たれたす。

  • 等倀性。 Object 䞊で == を党域化したす。 ぀たり、珟圚においお意味がある堎合、新しい定矩はその意味ず䞀臎したす。 次のセクションで説明するように、むンラむンオブゞェクト ぞの参照 に関連する远加の䜜業がいく぀かありたす。
  • System::identityHashCode。 identityHashCode の䞻な甚途は、IdentityHashMapなどのデヌタ構造の実装です。 等倀性を党域化するのず同じ方法で identityHashCode を党域化できたす - すべおのフィヌルドのハッシュからむンラむン・オブゞェクトのハッシュを導出したす。
  • 同期。 これは郚分的な操䜜になりたす。 同期が実行時に倱敗するこずを静的に怜出できる堎合むンラむンクラスでsynchronizedメ゜ッドを宣蚀するなど、コンパむル゚ラヌを発行できたす。 そうでない堎合、むンラむンむンスタンスをロックしようずするず、実行時に IllegalMonitorStateException ずなりたす。これが正圓化できるのは、察象オブゞェクトのロックプロトコルを明確に理解しおいないのにそれをロックするずいうのは本質的に䞍泚意によるものだからです。任意の Object たたはむンタヌフェヌスむンスタンスをロックするずいうのは、たさにそういうこずなのです。
  • Object::wait および Object::notify。 同期ず同じです。
  • 匱い参照。 これに぀いおはどちらにするこずもできたす。Objectの匱参照を䜜成するこずを郚分化もできたすが、これは厄介な結果になりたす匱参照はほずんど圹に立たなくなりたす。なぜなら、䜕らかの匱いデヌタ構造を維持したいすべおのクラスは、アむデンティティオブゞェクトずむンラむンオブゞェクトの別々のパスに分岐する必芁が出おくるためです これはidentityHashCodeの郚分化に䌌おいたす。䞀方、単玔な動䜜むンラむンオブゞェクトを保持する匱参照は決しお消去されないなどを遞択するず、初めは存圚しおいた、匱参照を䜿甚する目的ずなるGCフレンドリヌな振る舞いの䞀郚が倱われたす。この件はさらなる分析が必芁です。

むンラむン型ず参照型

これたでのずころ、「プログラム可胜なプリミティブ」に非垞によく䌌たむンラむン型を構築しおきたした。 しかし、プリミティブの最倧の欠点は、静的にも動的にも、プリミティブずオブゞェクトの間ではっきり分かれおいる点です。 「プログラム可胜な」郚分は、むンラむン型がメンバヌずスヌパヌタむプを持぀こずができるずいう点で、いく぀かのギャップを狭めたす。 しかし、このギャップをさらに狭くしたいず思いたす。

珟圚の䞖界では、 ボクシング倉換を介しおプリミティブ型から参照型に倉換しおいたす。 これは、より倚くの倚態的なコヌドを曞くこずができるので䟿利です。 サブタむプたたはボクシングを介しお、任意の倀を Object で衚すこずができたす。 しかし、ボクシングにはいく぀かの重倧な欠点がありたす。 ボックス型は、特泚の手䜜りクラスであり、プリミティブ型ぞの蚀語的接続は限られおいたす - これは、むンラむンクラスに確実に察応したせん。 さらに悪いこずに、結果のボックスには「偶発的な」オブゞェクトアむデンティティがあり、倚くのVM最適化の劚げになりたす。 「ボクシングは遅い」ずいう信念は、この偶然のアむデンティティに由来するものです。

私たちがやりたいのは、実行時のアドホックで軜量な方法でむンラむン型の䞖界を参照型の䞖界に接続するこずです。

ボクシングは死んだ、むンラむン拡倧よ栄えよ

むンラむンクラスの倀集合はオブゞェクトむンスタンスで構成されたすが、アむデンティティクラスの倀集合はオブゞェクトむンスタンス ぞの参照 で構成されたす。 この衚珟の違いは、珟圚の䞖界のプリミティブずオブゞェクトの違いの䞻な原因の1぀です。

むンラむンクラスを型システムの残りの郚分に接続し、むンタヌフェヌスを実装しお Object を拡匵できるようにしたす。 しかし、むンタヌフェヌス I 、 I を実装するアむデンティティクラス C 、および I を実装するむンラむンクラス V があるずしたす。 I の倀集合は I ですか 明らかに、 C ず V の䞡方の倀集合を含める必芁がありたすが、これらの集合は構造的にたったく異なりたす。 䞀方にはオブゞェクトが含たれ、もう䞀方にはオブゞェクトぞの参照が含たれたす。 これは、橋枡しする必芁があるオブゞェクトずプリミティブの分断です。 珟圚の䞖界は、これを䞍噚甚にボクシングで埋めおいたす。 より均䞀で軜量な方法で橋枡しをしたいず考えおいたす。

むンタヌフェヌスおよび Object は参照型です。぀たり、倀集合はオブゞェクト参照で構成されおいる必芁がありたす。 それが、Valhallaの次の倧きな違いに぀ながりたす。 すなわち、アむデンティティオブゞェクトを操䜜できるのは参照を介しおのみですが、むンラむンオブゞェクトでは、盎接たたはオブゞェクト参照を介しお、 どちらの方法でも 操䜜および保存できたす。

Valhallaの倀の宇宙は、プリミティブ倀、むンラむンオブゞェクト、およびアむデンティティオブゞェクトずむンラむンオブゞェクトの䞡方ぞの参照で構成されおいたす。

Valhallaでは、 むンラむン拡倧倉換 を介しおむンラむンから参照型に倉換したす。 これはボクシングず䌌おいたすが、倧きな違いがありたす 倉換の結果はボックスのようにアむデンティティオブゞェクトではなく、 むンラむンオブゞェクトぞの参照 です。 結果の Object で Object::getClass を呌び出すず、ボックス型ではなく、元のむンラむンオブゞェクトのクラスが報告されたす。 これにより、VMの最適化胜力を損なうこずなく、むンラむン型ず参照型の間で必芁な盞互運甚が可胜になりたす。

むンラむン拡倧倉換は、ボクシングのパフォヌマンスの欠点をほずんど䌎わずに、ボクシングの望たしいセマンティクスを提䟛したす。

挔算子 ref v は、 v がむンラむンオブゞェクトの堎合は v ぞの参照ずしお定矩し、 v が既にオブゞェクト参照である堎合は v 自䜓ずしお定矩するず䟿利です。 そうすれば、 ref はすべおの衚珟可胜な倀の党域で定矩され、垞に参照を返したす。 逆の挔算子 unref は郚分的であり、むンラむンオブゞェクトぞの参照にのみ適甚され、2぀は 射圱ず埋め蟌みのペア を圢成したす。

むンラむン拡倧倉換は、むンラむン型からそれが実装する任意のむンタヌフェヌスおよび Object に存圚し、 ref 挔算子の適甚ずしお定矩されおいたす。 これにより、 I の倀集合に関する質問に答えるこずができたす。 これには、 C のすべおのむンスタンスぞの参照ず、 V のすべおのむンスタンスぞの参照が含たれたす。

むンタヌフェヌスおよび Object の倀集合は、倀 null に加えお、アむデンティティたたはむンラむンオブゞェクトのいずれかであるオブゞェクトぞの参照で構成されたす。 むンタヌフェヌスたたは Object むンスタンスでアむデンティティに䟝存する操䜜を実行するず、実行時に倱敗する堎合がありたす。

これはボクシングに目新しい名前を付けただけでは

この時点で、読者は単に甚語のトリックを挔じただけ、含意のある甚語「ボクシング」をただ含意のない甚語「むンラむン拡倧」に眮き換えただけではないかず疑問に思うかもしれたせん。 実斜したのが単に名前の倉曎だけなのであれば、それは確かにトリックになりたす。 むンラむン拡倧が単に名前倉曎されたボクシングではない理由は、Valhalla JVMでは、むンラむン拡倧および瞮小倉換が、察応するボクシングおよびアンボクシング倉換よりもはるかに軜いためです。 ボクシングの問題は、アドホック蚳泚プリミティブずいう限られた型のみに定矩されおいるこずであり、コストがかかるこずです。 私たちはこれらの䞡方の懞念に察凊しようずしおいたす。

スヌパヌタむプ

むンラむン・クラスはむンタフェヌスを実装するこずができたす。任意のクラスを拡匵するこずはできたせんが、抜象クラスの限られたカテゎリを拡匵するこずができたす。぀たり、フィヌルドを持たず、本䜓が空である匕数なしコンストラクタを持ち、それ以倖のコンストラクタを持たず、むンスタンス初期化子はなく、同期メ゜ッドを持たず、そのスヌパヌクラスがすべお同じ条件を満たしおいるクラスですObject ず Number はそのようなクラスの䟋です。

参照射圱ず倀射圱

䞎えられたむンラむンクラスのオブゞェクトぞの 参照 の集合に null を加えお蚘述できるず䟿利なこずがよくありたす。 むンラむン型 V が䞎えられたずき、倀の集合が次のように䞎えられる参照型 R が欲しいず思いたす。

ValSet(R) = {null} ∪ {ref v : v ∈ ValSet(V)}

このような型 R を V の 参照射圱 ず呌びたす参照型は、それ自身の参照射圱です。

参照射圱は、珟圚の䞖界ではラッパヌクラスが果たす圹割を担っおいたす。しかし、すべおのむンラむンクラスに手曞きのアドホックなラッパヌを持たせたくはありたせん。 むンラむンクラスから参照射圱を機械的に導出し、それを参照するための統䞀された方法を持ちたいのです。 そうすれば、むンラむンクラスずその参照射圱を察応付けたメンタルディクショナリを維持する必芁はありたせん。 任意の型 T に察しお、T.ref は T の参照射圱を衚したす。

むンラむン・クラスの堎合、参照射圱ず倀射圱の䞡方を自動的に䜜成したす。 むンラむンクラス V の堎合、V.ref は V の参照射圱V のむンスタンスぞの参照の集合に null を加えたものを蚘述する型であり、V.val は V の倀射圱V のむンスタンスの集合を参照したす。 そしお埌で述べるような特別な申し立おがない堎合は V は V.val の゚むリアスです。 この参照射圱は、V.val のみをサブタむプずしお蚱可するシヌルされた抜象クラスです。 ぀たり、抜象クラス C を拡匵したむンラむンクラス V の堎合、以䞋のようになりたす。

sealed abstract class V.ref
    extends C
    permits V.val { }

inline class V.val extends V.ref { }

そしお、V は V.val の゚むリアスになりたす。 この皮の゚むリアスは新しいものではありたせん。Stringはjava.lang.Stringの゚むリアスです。 V.valからV.refぞのむンラむン・ワむドニング倉換が自動的に行われたすしたがっお、V から V.ref ぞの倉換も行われたす。 さらに、V.ref から V.val ぞしたがっお、V.refからVぞのむンラむンナロヌむング倉換を定矩したす。 それは unref挔算子を適甚するもので、nullに察しおはNullPointerExceptionをスロヌしたす。

この䞀察の倉換によっお、むンラむンクラスは、歎史的にラッパヌ型ずプリミティブがそうであったように、参照射圱ず同じ関係を持ちたす。 ボクシング倉換オヌトボクシング、条件匏の型付け、オヌバヌロヌドの遞択の芳点から定矩されおいる既存のルヌルは、むンラむンの拡倧ず瞮小の倉換を組み蟌むために、簡単に拡匵するこずができたす。 その結果、既存の蚀語ルヌルず、これらの倉換に関するナヌザヌの盎感は、新しい䞖界でも倉曎されるこずなく前進するこずができたす - しかし、ボックス化の実行時間コストはありたせん。 なぜなら、珟圚のボクシングのように、むンラむンの拡倧は偶然のアむデンティティを持぀新しいオブゞェクトの生成を匷制するものではないからです。

参照型 R はすでにそれ自身の参照射圱であるためのすべおの芁件を満たしおいるので、 参照型 R に぀いおは、 R.ref を R 自身の゚むリアスにしたす。 これで、すべおの型 T が T.ref ず呌ばれる参照射圱を持぀こずが保蚌されたした。

クラスミラヌ

むンラむンクラス V は、2぀の型V.ref ず V.val 、それに型゚むリアス Vを生成したす。 そしお同じく、2぀のクラスミラヌも生成されたす。 しかし、参照射圱は抜象クラスなので、どのむンスタンスもそれが参照射圱のむンスタンスであるこずを報告するこずはありたせん。 V の倀ぞの非null参照は、V.valのむンスタンスであるこずを報告したす。

むンタヌフェヌス

歎史的には、クラスがむンタヌフェヌスを実装するこずはいく぀かのこずを意味しおいたした。

  • 適合性。 クラスには、メンバヌずしお、むンタヌフェヌスのすべおのメンバヌがありたす。
  • 掚移性。 このクラスのサブクラスもむンタヌフェヌスを実装したす。
  • サブタむピング。 クラス型は、むンタヌフェヌス型のサブタむプです。

むンラむンクラスをサポヌトするために、この最埌の箇条曞きであるサブタむピングを少しだけ掗緎させる必芁がありたす。 むンラむン・クラスの 参照射圱 は、むンタヌフェヌス・タむプのサブタむプであるず蚀いたす。 アむデンティティクラス型はそれ自身の参照射圱なので、この宣蚀はすべおのクラスに適甚されたす。 同様に、むンラむンクラスが抜象クラスを拡匵しおいる堎合、参照射圱は抜象クラスのサブタむプであるこずを意味したす。

オブゞェクト

Object には、すべおのクラス、むンラむン、およびアむデンティティのルヌト型ずしおの圹割があるため、むンタヌフェヌスず倚くの特性を共有しおいたす。 既に述べたように、すべおのむンラむン型から Object ぞのむンラむン拡倧倉換がありたす。

ただし、 Object は具象クラスであるため、残念ながら、コンストラクタヌを介しお Object 盎接むンスタンス化するこずは可胜です。 むンタヌフェヌスは継承されるため、 Object は InlineObject も IdentityObject も実装できたせん。 ですが、 new Object() によるむンスタンス化の結果はアむデンティティ型のむンスタンスである必芁がありたす他の理由で Object をむンスタンス化するポむントがないため。

この眠からはいずり出るには、手の蟌んだ動きが必芁です。 たずは IdentityObject を返す静的ファクトリヌ Object::newIdentity を䜜成し、 それから、さたざたなツヌルコンパむラヌ譊告やJITのマゞックなどを䜿っお、既存の゜ヌスおよびバむナリヌでの new Object() の䜿甚をそちらに移行しようずするこずから始めたしょう。 そしお最終的には、盎接むンスタンス化するための Object コンストラクタヌを protected にしおしたうこずで「廃止」するのです。

等倀性、ふたたび

むンラむンオブゞェクトの == 拡匵は完了しおいたせん。 むンラむンオブゞェクト自䜓に察しおは定矩したしたが、参照型で、倀集合の䞭にむンラむンオブゞェクトぞの参照を持぀可胜性のあるものに぀いおはただ定矩しおいたせん。 これに぀いお、2぀のオブゞェクト参照が等しいずは、䞡方ずもnullであるか、同じアむデンティティオブゞェクトぞの参照であるか、たたは == が成立する2぀のむンラむンオブゞェクトぞの参照である堎合ずしたす。 これにより、 == の 代入可胜性 のセマンティクスがすべおの倀に拡匵されたす。 すなわち、2぀の倀は、 NaN が持぀埓来の動䜜を陀いお、どのような方法でも区別できない堎合にのみ == です。

これにより、 == に぀いお、次の有甚な䞍倉匏 NaN の埓来の動䜜を陀くすべおで成り立぀が埗られたす。

  • == は反射的、すなわちすべおの v に察しお v == v です。
  • 2぀のむンラむン倀が参照に拡倧されるずき、元の倀が == だった堎合にのみ、結果も == ずなりたす。
  • 2぀の参照がむンラむンオブゞェクトに瞮小されるずき、元の参照が == だった堎合にのみ、結果も == ずなりたす。

Object::equals の基本実装は、 == に委任したす。 Object::equals を明瀺的にオヌバヌラむドしないむンラむンクラスでは、それがデフォルトです。 同様に、 Object::hashCode の基本実装は System::identityHashCode に委任したす。これもデフォルトです。

参照射圱が必芁な理由

参照射圱の定矩は意味があり、参照型ずの関係に぀いおの既存の盎芳ず䞀臎しおいたすが、これらの型が非垞に重芁である 理由 をただ十分に動機付けおいたせん。

むンラむン型を䜿甚できない堎合は次のようにいく぀かありたす。

  • 無効倀。 Nullはむンラむン型の倀ではなく、すべおの参照型の倀ですが、「V型のnull倀を蚱可する倀」ずいう抂念を衚珟したい堎合もありたす。
  • 非平坊化。 むンラむン倀はオブゞェクトず配列に芏則正しくフラット化されたす。 通垞、これは私たちが望むものです。 ただし、堎合によっおは、メモリヌ䜿甚率をより现かく制埡する必芁がある堎合がありたす。たずえば、「幅の広い」むンラむンクラス倚くのフィヌルドを持぀クラスがあり、それらの疎な配列が必芁な堎合などです - 平坊化された倀の配列よりも、参照の配列の方がメモリヌを効率的に䜿える堎合がありたす。
  • 再垰衚珟。 むンラむンクラスは、衚珟に぀いお自分自身に再垰的に䟝存するこずはできたせん。 通垞、これは重倧な制限ではありたせんが、参照型でこれをシミュレヌトしたい堎合もありたすたずえば、「次の」フィヌルドを持぀ Node クラス。
  • 型消去によるゞェネリクス。 既存の型消去ゞェネリクスは、型パラメヌタヌが参照型であるこずを前提ずしおいたす - アむデンティティ䟝存の操䜜や、null倀などが蚱可されたす。特殊化されたゞェネリクスが䜿えるようになっお、むンラむン型ず型消去ゞェネリクスの盞互運甚ができるようになるたで、型パラメヌタヌには参照型を䜿甚したいのです。
  • 劥圓なれロがない堎合。 むンラむン型のデフォルト倀は、すべおのフィヌルドがデフォルト倀をずる倀です。 䞀郚の型では、この倀は劥圓です Point のデフォルト倀ずしお (0, 0) は劥圓ですが、堎合によっおは Rational など、この倀は無意味か、たたは危険ですらありたす。 そういった堎合は、初期化されおいない倀を衚すために null を䜿甚できるように、参照型を䜿甚したいこずもありたす。

これらすべおの状況で、むンラむン型の代わりに参照型を䜿甚できたす。 ただし、 Object などの広い参照型を䜿甚するず、倚くの損倱が発生したす - 型安党性が倱われ、クラむアントはむンラむンの䞖界に戻るためにコヌドに未チェックのキャストを挿入する必芁がありたす。 むンラむン型に参照射圱を䜿甚すれば、むンラむンの拡倧ず瞮小の倉換によっお、倀集合が特定のむンラむンクラスの倀集合ず密接に結び付けられた参照型があり、明瀺的な倉換を䜿甚せずにそのむンラむンクラスに自由に倉換できたす – これにより、私たちが望む型の安党性ず利䟿性が救われたす。

䟋ずしお、特殊なむンスタンス化をサポヌトするために Map むンタヌフェヌスを移行する問題を考えおください。 Map::get メ゜ッドは、芁求されたキヌがマップに存圚しない堎合は null を返したすが、 Map の V パラメヌタヌがむンラむン型の堎合、 null は倀集合のメンバヌではありたせん。 get() メ゜ッドを以䞋のように宣蚀すれば、これを捕捉できたす。

public V.ref get(K key);

これは、 Map::get の戻り倀の型が V ぞの参照か、たたは null 参照のどちらかになるずいう抂念を捉えおいたす。

移行

これたでに説明した手法は新しいコヌドには十分ですが、準備しおおきたい移行シナリオがいく぀かありたす。

移行 倀ベヌスのクラスからむンラむンクラスぞ

倀ベヌスのクラスがすでにいく぀も存圚しおいお、それらはむンラむンクラスぞのスムヌズな移行を可胜にするために蚭蚈された䞀連の制限を満たしおいたす。 そのような䟋の1぀に java.util.Optional がありたす。これは、Java 8にむンラむンクラスがあったずしたならむンラむンクラスずしお宣蚀できたはずです。 Optional をむンラむンクラスに移行しお、むンラむンクラスの実行時の利点を掻甚したいず思いたす。  java.util.time パッケヌゞのクラスも同様の状況にありたす。

既存のクラむアントには、倉数の型、メ゜ッドのパラメヌタヌたたは戻り倀の型、型パラメヌタヌなどで、 Optional 型が倚数䜿甚されおいたす。 これらのクラむアントはすべお、 Optional が参照型であるず想定しおおり、参照型はnull可胜です。 したがっお、 Optional を盎接むンラむン型に移行するこずはできたせん。

次善策は、 Optional を䜕らかのむンラむン・クラスの参照射圱ずしお定矩するこずです。 これは、Optional を抜象クラスに移行し、ただ䞀぀のむンラむンクラス倀射圱 Optional.valだけ蚱可するようにシヌルされるように手配するこずを意味したす。

この移行埌、 Optional の むンスタンス はアむデンティティクラスではなくむンラむンクラスになりたすが、既存のコヌドは匕き続き、参照を介しお Optional 倀を栌玍したり枡したりしたす。 それらを盎接衚珟するこずが実際に違いを生むのは、それらがヒヌプに出䌚う堎所、぀たりフィヌルドず配列芁玠です。 そしおそこでは、 Optional のそれら特定の甚途を Optional.val に自由にか぀段階的に移行できたす。 むンラむンの拡倧ず瞮小の倉換によっお、フィヌルドたたは配列を Optional から Optional.val に倉曎するのは、゜ヌス互換の倉曎になりたす。 既存のAPIは、参照射圱である Optional を匕き続き䜿甚する可胜性が高いでしょう。

このトリックを達成するために、Optional のむンラむン・クラスを宣蚀しお参照射圱 Optional.ref ず倀射圱 Optional.val を生成したいのですが、゚むリアス Optional を逆にしお倀射圱ではなく参照射圱を参照するようにしたいのです。 これは、宣蚀を修正しお ref-defaultむンラむン・クラス であるこずを瀺すこずで実珟できたす。

ref-default inline class Optional<T> {
    // current implementation of Optional
}

ref-default修食子が持぀唯䞀の効果は、装食されおいない型名が指し瀺すのは、2぀の射圱のうちどちらかを決定するこずです。

このような移行から生じる可胜性のある非互換モヌドが1぀ありたす - クラむアントが getClass() の結果ず Optioinal.class を比范する堎合です。 移行前は、 Optional むンスタンスは Optional.class クラスを持っおいたす。 Optional が抜象クラスに移行されるず、 Optional むンスタンスは 自分自身が倀射圱 Optional.val のむンスタンスであるず報告するでしょう。

M.class の䜿甚を取り巻くこの非互換性は、ここで抂説する移行アプロヌチの䞻芁な互換性コストです。これは、 getClass() の結果ずむンタヌフェヌスや抜象クラスのクラスリテラルずを == で比范するずきにコンパむル譊告を発行するこずで倚少緩和できたす。実行時に倱敗するこずがわかっおいるためです。

移行: プリミティブ

むンラむン型にプリミティブの抜象化ずいう圹割を割り圓おたしたが、実際にプリミティブをむンラむン型に包含できるようにするために、さらに䜜業が必芁です。

ラッパヌ型である Integer ずその仲間たちを、Optional の移行ず同じ手法を甚いお、シヌルされた抜象クラスに移行するこずから始めたす。 これらのむンタヌフェむスは、プリミティブの参照射圱になりたす。 これを行うには、たず、プリミティブラッパヌのアむデンティティぞの䟝存性をナヌザヌから解攟しなければなりたせん。 これを行うには、パブリックなコンストラクタを非掚奚にしお実際には削陀するのではなくプラむベヌトになりたす、移行期間䞭はInteger のむンスタンスを「氞久にロックされた」状態にしたすここでのアプロヌチに぀いおは JEP 169 を参照しおください。

この動きは、プリミティブラッパヌのアむデンティティに䟝存するコヌドを壊すリスクがありたす。代入可胜性を持った == の定矩を考えれば、 == による比范はほが問題になりたせんが、ラッパヌをロックするコヌドは実行時に倱敗するでしょう。

その埌、プリミティブ型をむンラむンクラスずしお明瀺的に宣蚀できたす。

inline class int { /* implementation */ }

自己参照に぀いおは明らかに倚少の調敎を行う必芁がありたすし、レガシヌラッパヌの名前をプリミティブに合わせるために、さらにいく぀かの修正を加えたしたが、今や、 int にスヌパヌむンタヌフェヌスずむンスタンスメ゜ッドを远加するのも自由ですし、通垞はクラスのように扱うこずができたす。 参照射圱 int.ref は Integer の゚むリアスになっおいお、 Integer.val は int の゚むリアスになっおいたす。 2぀の型の関係は、移行された倀ベヌスのクラスの堎合ず同じです。 プリミティブが真のむンラむン型である堎合でも、配列の間には匕き続き以䞋のサブタむピング関係がありたす。

int[] <: Integer[] <: Object[]

次に、int ず Integer の間で定矩された2組の倉換を調敎しなければなりたせん。 既存のボクシング倉換ず、新たなむンラむン瞮小・拡倧倉換です。 しかし、䟿利なこずに、ラッパヌクラスの偶発的なアむデンティティ非掚奚ですを陀き、これらは同じセマンティクスを持぀ように定矩しおいたす。 ボクシングは、ランタむムが芏則正しい最適化によっお陀去するこずがより単玔になりたすが、その䞀方で、倉換や、オヌバヌロヌド遞択や、掚論にた぀わるすべおの既存ルヌルは維持されたす。 同様に、オヌバヌロヌド遞択でのボクシングの圹割を䞀般化しお、むンラむンの拡倧ず瞮小を代わりに䜿甚できるため、この移行ではオヌバヌロヌド遞択の決定方法は倉曎されたせん。

移行: 特殊化されたゞェネリクス

ゞェネリクスは珟圚、単䞀の参照に型消去されたす。 いずれはゞェネリクスがその衚珟を特殊化できるようにしお、 ArrayList<Point> のようなゞェネリック型も Point[] がもたらす平坊化ず密床の利点を埗るこずができるようにしたいず思っおいたす。 これには远加の時間がかかり、移行互換性の問題がさらに発生したす。 ArrayList を特殊化可胜な型に移行しおも、既存のクラスファむルは 型消去による ArrayList ぞの参照が倚く残されたたたでしょうから、これらは匕き続き動䜜する必芁がありたす。

将来の機胜ずしお、特殊化されたゞェネリクスの䜙地を残そうずしおいたす。 珟圚の型消去されたゞェネリクスは、参照型でのみ機胜し続ける可胜性がありたす。 List<int> や Optional<Point> などの特殊化された型に぀いおは、将来的に自然な衚蚘法を予玄したいず考えおいたす。 これを行うには、型消去されたゞェネリクスでは、参照型のみが型匕数ずしお有効であるこずを芁求したす。 今日、人々は List<Integer> ず曞いおいたす。 これは List<int.ref> および List<Point.ref> ず䞀般化されたす。

たずめ

私たちが取ったアプロヌチは、プリミティブず参照における既存の分断構造を維持する䞀方で、より芏則的でパフォヌマンスの高いものにするこずです。 ボクシングはずっずコストが䜎くなっお圱の䞭に遠ざかり、「むンラむン」は「プリミティブ」の新しい蚀葉であり、プリミティブの集合は拡匵可胜です。 私たちは「重いボクシングを䌎う参照ずプリミティブ」から「軜いボクシングを䌎う参照ずむンラむン」に移行したしたが、2぀の䞖界はほが同型のたたです。

珟圚の䞖界 Valhalla
参照ずプリミティブ 参照ずむンラむンプリミティブはむンラむン
プリミティブにはボックスがありたす むンラむンには参照射圱がありたす
ボックスにはアむデンティティがあり、 getClass() で衚瀺されたす 参照射圱は実行時に衚瀺されたせん
ボクシングずアンボクシングの倉換 むンラむンの瞮小拡倧倉換、ただしルヌルは同じ
プリミティブは組み蟌みで、魔法 プリミティブはほずんど単なるむンラむンクラスで、远加のVMサポヌトを備えおいたす
プリミティブにはメ゜ッドもスヌパヌタむプもありたせん プリミティブはむンラむンクラスであり、むンラむンクラスにはメ゜ッドずスヌパヌタむプがありたす
プリミティブ配列は単盞です むンラむン配列は倚盞です

このドキュメントでは、むンラむン・クラスの Java 仮想マシン・ビュヌに぀いお説明したす。 これは必ずしもJava蚀語ビュヌず同じではないこずに泚意しおください。 読者の方は、このドキュメントから Java 蚀語に぀いおの結論を導き出す際には泚意が必芁です。

むンラむンクラス

Valhalla 以前は、すべおのオブゞェクトクラスや配列のむンスタンスは䞀意のオブゞェクト ID を持っおいたした。 Valhalla では、クラスに ACC_INLINE フラグを付けるこずで、そのむンスタンスが ID を持぀かどうか「identity クラス」、あるいは ID を持たないかどうか「むンラむンクラス」を遞択できるようになりたした。

抜象仮想マシンクラスファむルで蚘述されおいるでは、むンラむン・オブゞェクトずアむデンティティ・オブゞェクトの䞡方が、オブゞェクト参照 を通じお排他的に参照されたす。 しかし、JVMはむンラむンオブゞェクトがアむデンティティを持たないこずを知っおいるため、むンラむンオブゞェクトのレむアりト平坊化、むンスタンス化、メンバヌアクセス、および呌び出し芏玄スカラヌ化を日垞的に最適化するこずができたす。

キャリアず基本型

JVM型蚘述子(JVM仕様 4.3.2)では、基本型 を衚すために先頭の文字を䜿甚したす。 珟圚、8぀の基本型I、Jなどに察応する8぀のプリミティブ型ず、オブゞェクト参照Lに察応する1぀の基本型がありたす。 Vずいう文字は、型蚘述子には珟れたすが、型ずはみなされたせん。

これら9぀の基本型は5぀の キャリア型 int、long、float、double、オブゞェクト参照に察応しおおり、 スタックスロットやロヌカル倉数スロットでの倀の異なる衚珟に察応しおいたす。 これら2぀の集合の違いは、byte、short、char、booleanをintに消去しおIキャリアを䜿甚しおいるこずに由来したす。 プリミティブキャリアは、スタックたたはロヌカル倉数スロットに盎接倀を栌玍しfloat ず double 倀は隣接する 2 ぀のスロットを䜿甚したす、 オブゞェクト参照Lキャリアは、察応するスロットに オブゞェクト参照 を栌玍したす。

むンラむン型を蚘述するために、むンラむンオブゞェクトぞの参照を衚す新しい基本型 Q を远加したす。 Q ディスクリプタは、L ディスクリプタず同じ構文構造䟋えば、Qjava/lang/int;を持っおいたす。

L ディスクリプタの構文圢匏を再利甚するこずに加えお、Q ディスクリプタは L キャリアも再利甚したす。 JVMでは、Q ディスクリプタの䞋の参照がnullにできないずいう事実以倖に、 むンラむンオブゞェクトぞの参照ずIDオブゞェクトぞの参照の間には構造的な違いはありたせん。

L ディスクリプタず Q ディスクリプタの遞択は、名前付きクラスが ID クラスに解決するかむンラむンクラスに解決するかに密接に結び぀いおいたす。 L ディスクリプタがむンラむン・クラスに解決したり、Q ディスクリプタが ID クラスに解決したりするのは、リンケヌゞ・゚ラヌです。 別個の基本型デシグネヌタの必芁性は、フィヌルド・レむアりト時など、むンラむン・クラスは ID クラスよりも積極的にプリロヌドする必芁があるこずに起因しおいたす。

スヌパヌタむプ

むンラむン・クラスはむンタヌフェむスを実装するこずができ、特別なクラスであるObjectず同様に、ある制限された抜象クラスを拡匵するこずができたす。 抜象クラスの制限には、フィヌルドを持たないこずや空のコンストラクタが含たれたす。 ぀たり、むンタヌフェヌス型、適切な抜象クラス型、たたはObjectの倉数は、IDオブゞェクトたたはむンラむンオブゞェクトのいずれかぞの参照である可胜性がありたす。 JVMは、このような拡匵を通垞のサブタむプずしお扱いたすので、むンラむン・オブゞェクトぞの参照は、キャストなしでObject、たたは適切なむンタヌフェむスたたは抜象クラス・タむプぞの参照に拡匵するこずができたす。 むンラむンクラスはコンストラクタを持ちたせん。 代わりに、静的なファクトリメ゜ッド名前は<new>を持っおいたす。

制玄

むンラむン・クラスには、察応するIDクラスず比范しおいく぀かの制限がありたす。 むンラむン・クラスのむンスタンス・フィヌルドには ACC_FINAL ずマヌクする必芁があり、InlineObject むンタフェヌスを実装する必芁がありたす。盎接たたは間接的に IdentityObject を実装するこずはできたせん。 Object 以倖のクラスを拡匵する堎合、そのクラスは抜象化されおいお、フィヌルドを持たず、空のACC_ABSTRACT ずマヌクされおいる可胜性がある無匕数コンストラクタを持぀必芁がありたす。 むンラむンクラスの静的ファクトリは、スヌパヌクラスのコンストラクタを呌び出したせん。なぜなら、定矩䞊は空でなければならないからです。

むンラむンクラス V のフィヌルドは、盎接たたは間接的に V 型のフィヌルドを持぀こずはできたせん。

バむトコヌド

むンラむンクラスの組み蟌みは、倚くのバむトコヌドに圱響を䞎えたす。 いく぀かは新しいものですが、むンラむン型に適甚されたずきに远加の動䜜や制限を埗るものもありたす。

既存の a* バむトコヌドが拡匵され、identityクラスずむンラむンクラスの䞡方ぞの参照を䞀様にサポヌトするようになりたした。

むンラむンクラスのむンスタンスを構築するために䜿甚される2぀の新しいバむトコヌドがありたす。

  • defaultvalue はむンラむンクラスむンスタンスの new のアナログです。
    これは、スタック䞊にむンラむンクラスのデフォルト (すべおれロ) むンスタンスぞの参照を残したす。
    初期化されおいないフィヌルドや配列芁玠も、あたかも defaultvalue によるものであるかのように、その型のデフォルト倀に初期化されたす。
  • withfield はむンラむンクラスのむンスタンスのための putfield のアナログです。
    むンラむンオブゞェクトぞの参照ずスタック䞊の新しいフィヌルド倀を受け取り、指定されたフィヌルド以倖はすべお元のむンスタンスず同じフィヌルドであるむンラむンクラスのむンスタンスぞの参照をスタック䞊に残したす。

withfield バむトコヌドは制限されおいたす。 このバむトコヌドは、倉曎されるむンラむンクラスを宣蚀しおいるクラスのみが実行できたす。 これは新しい倀の生成をカプセル化しおいるので、クラスは実装を゚スケヌプした倀がその䞍倉量に埓っおいるず芋られるこずを保蚌できたす。 new バむトコヌドず putfield バむトコヌドはむンラむン・クラスのむンスタンスでは䜿甚できず、withfield バむトコヌドは ID クラスでは䜿甚できたせん。

aastore 呜什は、むンラむン・クラス・むンスタンスの配列に倀を栌玍する前に、芁玠の倀に察しおヌルチェックを行いたす。

acmp* 呜什は、そのオペランド間でより掗緎された比范を実行したす。 2぀のオブゞェクト参照は、䞡方ずもnullであるか、䞡方ずも同じidentityオブゞェクトぞの参照であるか、䞡方ずも同じ型のむンラむンオブゞェクトぞの参照であり、すべおのフィヌルドが "等䟡"である堎合、等倀ずみなされたす。 等䟡ずは、適切な等倀比范をフィヌルドに再垰的に適甚するこずを意味し、プリミティブには通垞の等倀 Float::equalsずDouble::equalsのセマンティクスで比范されるfloatずdoubleフィヌルドを陀く、参照にはacmpを䜿甚したす。 むンラむンオブゞェクトぞの参照に適甚された堎合、if_acmpnull 呜什は垞に false を返したす。

Q-World から L-World ぞ

Valhalla プロトタむプの以前のむテレヌションでは、Q ディスクリプタは別のキャリアを持っおいたしたが、それは L キャリアずの盞互運甚性がありたせんでした。プリミティブが明瀺的に倉換しないず参照型ずの盞互運甚性がないのず同じように。 たた、プリミティブず同様に、Q 型にはスヌパヌタむプがありたせんでした。むンタヌフェむスずオブゞェクトのメンバぞのアクセスは、L 型のコンパニオンクラスぞの倉換を経なければなりたせんでした。ボックスずしお機胜したすが、珟圚のボックスのような偶然のアむデンティティはありたせん。

同様に、むンラむン クラスは以前は独自のデヌタ移動バむトコヌド (v*) を持っおいたしたが、L-World では、identity ずむンラむン オブゞェクトの䞡方ぞのオブゞェクト参照は䞀様に a* バむトコヌドを介しお移動したす。 最埌に、Q-world では、むンラむンオブゞェクトの配列は Object の配列ず共倉性を持っおいたせんでした。

この区別は、むンラむンクラスを「匷化されたプリミティブ」ずしお扱いたした。 クラスのようにコヌドを曞くこずはできたすが、良い意味でも悪い意味でも int のように振る舞いたす。 このため、既存のアむデンティティ・クラスをむンラむン・クラスに移行したり、アむデンティティ・オブゞェクトずむンラむン・オブゞェクトを統䞀したりするこずが非垞に困難になりたした。 それは、すべおのレベル蚘述子、バむトコヌド、サブタむプ関係でむンラむンクラスずアむデンティティクラスの間に継ぎ目があったからです。 L Worldのデザむンは、このアプロヌチが生み出した課題に倧きく圱響されおいたす。

このドキュメントでは、むンラむン・クラスおよびむンラむン型に察する操䜜が、Java ゜ヌス・コヌドから Java クラスファむルにどのように倉換されるかに぀いお説明したす。

クラス宣蚀

むンラむンクラス宣蚀は、スヌパヌクラスObjectたたは適切な抜象クラスずスヌパヌむンタヌフェヌスを持぀こずができたす。

class C extends A implements I { }

コンパむル時には、゜ヌスレベルの型C.refずC.valに察応するC$refずC$valずいう2぀のクラスファむルが生成され、以䞋のようになりたす。

[ PermittedSubtypes(C$val.class) ]
[ NestMembers(C$val.class) ]
abstract sealed class C$ref
    extends A implements I
    permits C$val {
}

[ NestHost(C$ref.class) ]
ACC_INLINE class C$val extends C$ref {
}

さらに、これによりC型が生成され、これは䞊蚘の型のいずれかの゚むリアスずなりたすCがref-defaultかval-defaultかによっお異なりたす。

ここでシヌリングを䜿甚するずいうこずは、クラスC$refの倀がC$valの倀ぞの参照であるか、null参照になるこずを意味したす 事実䞊、C$refはC$valず区別された倀nullずの接続になりたす。 さらに、生成された2぀のクラスはネストメむトであり、お互いのプラむベヌト・メンバにアクセスするこずができたす。

メンバヌ

Cで宣蚀されたメンバは、C.refずC.valの䞡方のメンバになりたす。 クラス宣蚀のメンバを射圱クラスファむルのメンバに倉換する方法はいく぀か考えられたす。 私たちは、VM がすでに行っおいるこずを利甚しお、重耇や、ブリッゞ・メ゜ッドなどの翻蚳アヌティファクトの必芁性ずいったものを最小限に抑え、将来の移行時の互換性の問題を最小限に抑えるアプロヌチを遞択したす。 このアプロヌチでは、状態関連のメンバフィヌルドずコンストラクタを倀射圱に、動䜜関連のメンバメ゜ッドを参照射圱に゜ヌトしたす。 フィヌルドは暗黙のうちに最終的なものずなり、゜ヌス・レベルのコンストラクタはクラス・ファむル内のファクトリヌ・メ゜ッドにマッピングされたす。

inline class C {
    private int x;

    public C(int x) { this.x = x; }

    public int x() { return x; }
}

これを翻蚳するず、以䞋のようにメンバヌが゜ヌトされ、それを考慮しおメ゜ッド本䜓の翻蚳に様々な調敎が加えられおいたす。

abstract sealed class C$ref permits C$val {
    public int x() { return ((C$val) this).x; }
}

ACC_INLINE class C$val extends C$ref {
    private final int x;

    public static void <new>(int x) {
        defaultvalue C$val
        iload_0
        withfield C$val.x:int
        areturn
    }
}

静的なメンバは参照射圱に倉換されたす。

型の利甚ずメンバヌアクセス

フィヌルド蚘述子やメ゜ッド蚘述子など、ほずんどの堎合、C.refの䜿甚はLC$ref;、C.valの䜿甚はQC$val;ず蚳され、Cの䜿甚は、Cがref-defaultかval-defaultのむンラむンクラスずしお宣蚀されおいるかどうかによっお、これらのいずれかに蚳されたす。

C$valのすべおのむンスタンスメンバぞのアクセス、C$ref䞊のメ゜ッドアクセスは通垞通りに翻蚳されたす(getfield、invokevirtualなど)。 C$refからのフィヌルドアクセスは、最初にC$valにキャストしこの2぀は同じアクセシビリティを持ちたす、倀射圱を通しおフィヌルドにアクセスするこずで倉換されたす。 C$ref のむンスタンス化は、C$val のむンスタンス化に続いお C$ref ぞのキャストが行われるず倉換されたす。 C$valを介した静的メンバぞのアクセスは、C$refぞの展開ずそこにあるメンバぞのアクセスによっお倉換されたす(これはプラむベヌトな静的フィヌルドも扱いたす)。 プラむベヌトメ゜ッドの呌び出しに぀いおも同じこずが蚀えたす継承されないので。 これらの倉換結果はナヌザには透過的です。ナヌザは䞡方のプロゞェクションを、すべおのメンバがCで宣蚀されおいるず芋なしたす。

この翻蚳スキヌムは2぀の目暙を達成するために遞択されたした: クラスファむル内のメンバの重耇を最小限に抑えるこず(抜象メ゜ッドやブリッゞメ゜ッドなど)ず、(修食されない名前の意味を陀いお)val-default vs ref-defaultや、新たなバむナリ互換性の制玄を生み出す可胜性のある他の特性に翻蚳の決定を条件付けしないこずです。

倉換ずサブタむピング

倀射圱ず参照射圱の関係は、蚀語モデルずVMモデルぞの倉換では異なりたす。 蚀語モデルでは、倀射圱は参照射圱のサブタむプではありたせん。その代わり、䞡者はむンラむンの瞮小倉換ず拡倧倉換によっお関係しおいたすが、VMでは、実際のサブタむプ化によっお関係しおいたす。

VMず蚀語ずで違うモデルをわざず遞んでいるのはおかしいず思われるかもしれたせん。 が、芋おの通り、この遞択は蚀語の制玄を蚀語制玄の属する堎所に残したす。 これにより、VM は䞻に効率的な翻蚳タヌゲットずしおの圹割に集䞭するこずができたす。

むンラむンの瞮小ず拡倧の倉換は、意味的には、よりよく知られおいるアンボクシングずボクシングの倉換に䌌おいたすが、ボクシングに関連する負のパフォヌマンスコストの倚くむンダむレクト、割り圓お、偶発的な同䞀性を共有しおいたせん。 C$valをC$refに倉換する堎合、これは蚀語レベルでは倉換ずみなされたすが、VMはすでにC$valをC$refのサブタむプずしお認識しおいるため、この倉換のために実際のバむトコヌドを発行する必芁はありたせん。 逆に、C$refをC$valに絞り蟌むずきに、蚀語コンパむラはチェックキャストバむトコヌドを出力したすが、VMはC$refがC$valだけを蚱可するようにシヌルされおいるこずを知っおいるので、これはヌルチェックに䞋げるこずができたすたたは最適化によっお完党に削陀されたす。 そのため、蚀語レベルではボクシングずアンボクシングのように芋えおいたものが、VM内では「䜕もしない」および「ほが䜕もしないに等しい」状態になっおしたうのです。

それでも、なぜC$valずC$refの間のサブタむプを単玔に蚀語レベルで公開するこずを遞ばなかったのでしょうか それは、蚀語レベルでプリミティブずむンラむンを統䞀する道筋を残したかったからです。 珟圚のずころ、この蚀語では、アドホックなボックス化ずアンボックス化の倉換によっおintずIntegerが関連しおいたす。 蚀語モデルで抂説したように、プリミティブを通垞のむンラむンクラスに移行し、レガシヌなボックス型がそれらのクラスの参照射圱ずなるようにしたいず考えおいたす。 プリミティブに2぀の異なる皮類の「箱」レガシヌな重い箱ず新しい軜い箱で、前者はボクシングを介しお、埌者はサブタむプを介しお関連しおいたすを持たせるこずは、氞久的な欠陥になりたす。 そしお新しい第2の倉換セットサブタむプを持぀こずは既存のオヌバヌロヌド遞択の決定を倉曎するこずず盞容れないかもしれたせん。 この欠陥を取り陀くために、intずInteger間の倉換のセマンティクスを保持し、それをすべおのむンラむンの拡倧/瞮小倉換に拡匵したす。 これはレガシヌなボクシング倉換が通垞のむンラむンの拡倧・瞮小倉換であるようにするためのものです。

さらに、ボクシングの関係は、型掚論やオヌバヌロヌド遞択にも圹割を果たしおいたす。 そしお、むンラむンでの拡倧瞮小の意味合いがボクシングのそれずマッチするように遞択するこずで、 これらの耇雑で広汎な蚀語機胜は、むンラむンクラスに拡匵しおも、プリミティブを特別に扱うこずなく、ナヌザヌが期埅する通りに動䜜し続けるこずができたす。

これは、"ボクシング" の名前を "むンラむン拡倧倉換" に倉曎しただけで、修蟞的なトリックを䜿っおいるように芋えるかもしれたせん。 しかし、違いは新しい翻蚳察象ができたずいうこずです。 これは、むンラむンクラスずその参照射圱のレむアりト、むンスタンス化、呌び出し芏玄を日垞的に最適化できるものです。 効率的な翻蚳タヌゲットに䜿い慣れた蚀語のセマンティクスを移怍しただけで、パフォヌマンス以倖は䜕も倉わっおいないかのような錯芚に陥っおいたす。

プリミティブ

蚀語モデルで議論されおいるように、この話の重芁な目暙は、プリミティブの性胜特性を保持し぀぀、プリミティブが「ほずんどただの」むンラむンクラスになるようにプリミティブを移行させるこずです。 珟圚のプリミティブず参照型の間の区分けは、むンラむン・クラスずアむデンティティ・クラスの間の区分けに移行し、各ドメむンのルヌルおよびそれらの間の関係は、珟圚の区分けの察応する偎のルヌルずほが同じになりたす。 この移行は、おそらく段階的に行われるでしょう。

最初のステップは、蚀語がプリミティブを、暗黙のうちに宣蚀されたむンラむンクラス䟋えば、java.lang.intの倀射圱であるかのように扱い、そのラッパヌクラスを、そのむンラむンクラスの参照射圱であるかのように扱うこずです。 そうするず、int.refはIntegerの゚むリアスになり、Integer.valはintの゚むリアスになりたす。 これにより、型掚論、オヌバヌロヌド遞択、型結合適合性、オヌトボックシングなどのルヌルが、珟圚のプリミティブの扱い方ず完党に䞀臎した方法で、プリミティブずむンラむンを統䞀的に扱うこずができるようになりたす。

埌になっお、実際にintをjava.langで特別なクラスずしお宣蚀し、むンタヌフェむスずメ゜ッドを持぀ようにしお、ゞェネリクスの話が完成したら、最終的にintはComparable<int>を実装するこずができるようになるかもしれたせん。

もちろん、JVM は、プリミティブの盎接サポヌト䟋えば、I キャリアや i* 呜什を継続したす。 蚀語コンパむラには䞀定の自由床があるでしょう。 それは、有益な堎合や移行互換性のために必芁な堎合フィヌルドやメ゜ッド蚘述子などは 生成されたコヌドの䞭でI キャリアずi*呜什を䜿甚し、他の堎所では Qjava/lang/int を䜿甚するずいったものです。

このスキヌムには、動䜜的に互換性のない倉曎が1぀含たれおいたす。 それは、プリミティブなラッパヌクラスの䞀぀のむンスタンス䞊での同期化は IllegalMonitorStateException をスロヌしたす。 これを軜芖しおいるわけではありたせんが、ほずんどの堎合、これを行うこずぱラヌであり、これが完党な゚ラヌではないごく少数のケヌスでは、簡単な回避策が存圚したす。

リフレクション

Q-Worldでは、参照射圱はむンラむンクラスファむルからJVMによっお機械的に導出されおいたため、JVMは参照射圱甚の合成ミラヌも䜜成しなければなりたせんでした。 珟圚では、倀射圱ず参照射圱が実クラスファむルであるため、実クラスミラヌを䜿甚しおリフレクション䜜業のほずんどを行うこずができたす。

むンラむンクラスに関するより倚くの情報このクラスはむンラむンクラスなのか、参照射圱は䜕かなどを提䟛するためにリフレクション APIを拡匵したいず思うかもしれたせん。 たた、ミラヌの䞀方たたは䞡方のリフレクション動䜜を埮調敎しお、より蚀語に近い動䜜をするようにしたい堎合もあるでしょう -- あるいは、そうではなく、単に翻蚳モデルを公開するだけのリフレクションにしたい堎合もあるでしょう。

@matarillo
Copy link
Author

matarillo commented Apr 11, 2020

defaultvalue and withfield implementation in openj9

The initial implementation should operate in the same way that the new bytecode does -- the instance should be allocated on the heap and a reference should be placed on the stack. A later version could consider value type buffering, where new instances are instead allocated in a valuebuffer pointed to from the Java stack, and which disappears when the stack frame is popped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment