答えて

4

メモリフットプリントが懸念される場合は、このフィールドをコンパニオンオブジェクトに移動することを検討してください。

はい、クラスFooのインスタンスはすべてpiの値になります.Scalaコンパイラはこの宣言を削除しません。 JVMリフレクションでは、クラスメンバーの最終的な修飾子を削除できます。Unsafeオブジェクトでは、これらを変更することもできます。したがって、Scalaコンパイラはこのフィールドを削除することで驚くべき結果をもたらすコードを生成する可能性があるため、この最適化は適用されません。実際に

... 
    minor version: 0 
    major version: 50 
    flags: ACC_PUBLIC, ACC_SUPER 
... 
{ 
    private final int pi; 
    flags: ACC_PRIVATE, ACC_FINAL 


    public final int pi(); 
    flags: ACC_PUBLIC, ACC_FINAL 
    LineNumberTable: 
     line 243: 0 
    LocalVariableTable: 
     Start Length Slot Name Signature 
... 

、いくつかのコンパイラ変換(例えば特殊化)もアンダーフード部材に最終的な改質を除去するかもしれないので、Scalaのコードでfinalを感じるものは、バイトコードレベルでfinalないかもしれません。

この

class Foo[@specialized T] { 
    final val pi: T = null.asInstanceOf[T] 
} 

になる:上記

... 
    public final T pi; 
    flags: ACC_PUBLIC, ACC_FINAL 
    Signature: #9       // TT; 


    public T pi(); 
    flags: ACC_PUBLIC 
    LineNumberTable: 
     line 243: 0 
    ... 

piアクセサメソッド(すなわち、そのゲッタ)はもはや最終あります。

また、Oracle JVMのJITは実行時にメモリ内のオブジェクト表現からこのメンバを削除しません - 32ビットJVM上のFooオブジェクトの実行時サイズは16バイトです(8バイトのオブジェクトヘッダー+ 4バイト整数フィールドの場合、8バイトの境界に丸められます)。しかし、JITは、最終フィールドからの一定値をコードの一部にインライン化して、一部のフィールド書き込みを排除することにします。

3

すべてのインスタンスにフィールドpiがあるだけでなく、値はゼロになります。

piは定数値の定義です。 「アクセサ」は定数を返します。

これは、十分に試してみると、別のコンパイルとインライン展開の条件で問題を引き起こす可能性があります。

{ 
    private final int pi; 
    flags: ACC_PRIVATE, ACC_FINAL 

    public final int pi(); 
    flags: ACC_PUBLIC, ACC_FINAL 
    Code: 
     stack=1, locals=1, args_size=1 
     0: iconst_3  
     1: ireturn  
     LocalVariableTable: 
     Start Length Slot Name Signature 
       0  2  0 this LFoo; 
     LineNumberTable: 
     line 8: 0 

    public Foo(); 
    flags: ACC_PUBLIC 
    Code: 
     stack=1, locals=1, args_size=1 
     0: aload_0  
     1: invokespecial #14     // Method java/lang/Object."<init>":()V 
     4: return   
     LocalVariableTable: 
     Start Length Slot Name Signature 
       0  5  0 this LFoo; 
     LineNumberTable: 
     line 13: 0 
} 

ただ、反射時に、自分自身を納得させる:

scala> res5.tail 
res16: Iterable[reflect.runtime.universe.Symbol] = List(value pi) 

scala> res5.last.asTerm.isAccessor 
res18: Boolean = false 

scala> res5.head.asTerm.isAccessor 
res19: Boolean = true 

scala> res0 reflectField res5.last.asTerm 
res21: reflect.runtime.universe.FieldMirror = field mirror for Foo.pi (bound to [email protected]) 

scala> res21.get 
res22: Any = 0 
関連する問題