If you are concerned about the amount of memory, you can move this field to a companion object.
Yes, every instance of the Foo class will have a pi value - the Scala compiler will not delete this declaration. JVM reflection allows you to remove the final modifiers for class members, and the Unsafe object even allows you to modify them. Thus, the Scala compiler can get code with unexpected results by deleting this field, so this optimization is not applied.
... 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 ...
In fact, some compiler transformations (e.g., specialization) may even remove the final modifiers for members under the hood, so something that feels final in Scala code may not be final at the bytecode level.
It:
class Foo[@specialized T] { final val pi: T = null.asInstanceOf[T] }
becomes:
... public final T pi; flags: ACC_PUBLIC, ACC_FINAL Signature: #9 // TT; public T pi(); flags: ACC_PUBLIC LineNumberTable: line 243: 0 ...
Above, the pi access method (i.e., its recipient) is no longer final.
And none of the JITs in the Oracle JVM removes this member from the representation of the object in memory at run time - the size of the runtime of the Foo object on the 32-bit JVM will be 16 bytes (8 bytes of the object header + 4 bytes for an integer field, rounded to the border of 8 bytes). However, the JIT may decide to include a constant value from the final field in the code part, so that some field entries will be eliminated.
axel22
source share