5

3つ(またはそれ以上)のクラスがあるとしましょう

パブリック クラス A {}

public class B extends A {}

パブリック クラス C を拡張 B を実装 G {}

各クラスには独自の 20 (またはそれ以上) のメソッドがあると仮定します。

C へのキャストと A へのキャストのどちらがパフォーマンスに大きく影響しますか? Java キャスティングは内部でどのように機能しますか?

キャストダウン時にリフレクションによってすべてのメソッドとフィールドの存在をチェックする必要がありますか?

編集: クラスのサイズ (フィールドとメソッドの数) は、キャスト時のパフォーマンスに影響しますか? OpenJREDalvikの両方に興味があります。

参考までに、アップキャストは問題なくできることを知っています。

4

2 に答える 2

4

キャストのパフォーマンスは、JVM の実装によって異なります。

JLS 5.5は、キャストの要件 (再帰アルゴリズムを含む) のみを決定しますが、実装に関する要件は設定しません。実際、5.5.3 のランタイム キャスト ルールも同じ方法で決定されます。提案されたアルゴリズムと同じ結果を生成するすべての JVM 実装は、適切な JVM として受け入れられます。

一般に、JVM はオブジェクトのランタイム タイプを調べる必要があるため、キャスト ダウンにCはもう少し時間がかかります。にキャストする場合、 extendsAであるため、同じチェックを行う理由はありません。BA

実際、JVM はメソッドとフィールドの数を気にしません。リフレクションで調べることができるのと同じように、型階層を比較するだけです(o.getClass()

次のようにサンプル コードを作成しました。1 つはダウンキャスト、次にアップキャストです。

Object o = new Integer(1);
Integer i = (Integer) o;

Object o2 = i;

コンパイルされたバイトコードは次のとおりです。

 0  new java.lang.Integer [16]
 3  dup
 4  iconst_1       <-- 1 as a parameter to the constructor
 5  invokespecial java.lang.Integer(int) [18]   <-- constructor
 8  astore_1 [o]       <-- store in 'o'
 9  aload_1 [o]
10  checkcast java.lang.Integer [16]    <-- DOWNCAST CHECK, SPECIAL BYTECODE
13  astore_2 [i]
14  aload_2 [i]
15  astore_3 [o2]   <-- WITH UPCAST NO CHECK

そのため、特定のクラスでスタックの一番上にある要素をチェックする特定の JVM 命令があります。

アップキャストでは、チェックはまったくありません。

クラスのサイズ (フィールド、メソッド、実際のフットプリントの数)は重要ではありません。これは、キャスティングがClass(実際にはオブジェクトであるメタデータ) を調べるためです。

階層レベルの数、および実装されているインターフェースの数 (インターフェースにキャストする場合)は重要です。これは、トラバース可能な継承/実装ツリーを確認するためです。

このチェックになんらかのキャッシュがないとしたら、私は驚くでしょう。

于 2013-05-24T18:27:17.893 に答える
2

checkcastHotSpot の (ダウンキャスト用の JVM メカニズムとして他の応答で言及された)の詳細なアーキテクチャについては、次のカンファレンス ペーパーをご覧ください。

HotSpot JVM でのサブタイプの高速チェック

アブストラクトからの引用:

実際のベンチマークの実行では、私たちの手法は基本的に常に 3 つの命令 (メモリ参照は 1 つだけ) で完全なサブタイプ チェックを実行します。まれに、より遅いアレイ スキャンに戻ることがあります。メモリ使用量は中程度 (クラスあたり 6 ワード) であり、時間とトレードオフできます。

したがって、多くのキャストを含む非常に低レベルのコードを作成しない場合、影響は無視できます。

于 2015-05-05T08:34:29.180 に答える