このトピックについて読んだ多くの本や記事、および「Unsafe」を使用して書いた小さなプログラムは、Java の 1 次元配列が常にメモリ内で連続していることを示しています。それはJLSによって指示されていますか、それとも実装規則ですか? この表示を確認するために質問されます。
4 に答える
いいえ、JVM 仕様にはそのような保証はありません: http://docs.oracle.com/javase/specs/jvms/se5.0/html/Concepts.doc.html#16446
実際にはおそらくそうですが、ワードサイズについても保証されていません。
Unsafe は標準の Java クラスではないため、プログラムでこれを使用する場合、とにかく移植性がありません...
この質問を、Java 言語仕様、Java SE 8 Edition (JLS)およびJava 仮想マシン仕様、Java SE 8 Edition (JVMS)がそれについて述べていることで更新したいと思います。
この質問に答えるには、選択肢が必要です。
- JVM 実装に課せられる制約。これは、仕様の実装が本質的に「禁止されていないものはすべて許可される」という原則を前提としているため、最も信頼できるアプローチです。
- ほとんどの JVM 実装で妥当と思われるもの。
仕様上の制約を指摘します。
第 10 章JLS の配列 (および配列に関連する JLS および JVMS の他の章) を見ると、配列に課せられたメモリ レイアウトの制約についての言及は見つかりませんでした。したがって、配列が連続していない可能性があることは間違いありません。
さらに、JLS は、配列はオブジェクトであると述べています。
第 10 章配列。
Java プログラミング言語では、配列はオブジェクト (§4.3.1) であり、動的に作成され、Object 型の変数に割り当てることができます (§4.3.2)。クラス Object のすべてのメソッドは、配列で呼び出すことができます。...
4.3.1. オブジェクト。
オブジェクトは、クラス インスタンスまたは配列です。(そして配列はオブジェクトです)
同時に、JVMS は、オブジェクトと配列がヒープに格納されていると述べています。
2.5.3. ヒープ
Java 仮想マシンには、すべての Java 仮想マシン スレッド間で共有されるヒープがあります。ヒープは、すべてのクラス インスタンスと配列のメモリが割り当てられるランタイム データ領域です。
しかし、JVMS はヒープ メモリが連続していることを強制しません。
2.5.3. ヒープ
... ヒープのメモリは連続している必要はありません。
すべての配列はヒープに格納され、ヒープが連続していない可能性があるため、配列も連続していない可能性があります。
Java ではメモリ アドレスを操作する実際の方法がないため、メモリ内のオブジェクトのレイアウトがどのように見えるかについても仕様で定義されていません。
Unsafe
ほぼ自動的に使用することは、仕様の領域の外を散歩していることを意味することに注意してください。
そうは言っても、実際にはほとんどの JVM 実装が(1 次元) 配列に線形レイアウトを使用していると思います。
多くのJVMには、ヒープがメモリ内で連続しているという要件があることを考えると、メモリ内のさまざまな場所にプリミティブの1d配列を配置する可能性は低いと思います。
Object []によって参照されるオブジェクトは、メモリ内で連続している可能性は低く、連続している場合でも、警告なしに再配置できます。
注:Unsafeを使用すると、配列内の参照をint
値として読み取って、GCの前後の参照を確認できます。一部のJVMは長い64ビット参照を使用しますが、ほとんどのJVMは32ビット参照を使用します(64ビットJVMの場合でも)