Skip to content

Commit 53c7beb

Browse files
committed
Tweak module initialization to comply with JVM spec
Dmitry learned that we've been relying on a bug in the verifier that will be fixed in JDK 9 under the new classfile format. Assignment to a static final must occur lexically within the <clinit>. We were performing this assignment from the constructor of the module class. This commit moves the assignment to <clinit>. Before: ``` public final class O$ { public static final O$ MODULE$; public static {}; Code: 0: new #2 // class O$ 3: invokespecial #12 // Method "<init>":()V 6: return private O$(); Code: 0: aload_0 1: invokespecial #13 // Method java/lang/Object."<init>":()V 4: aload_0 5: putstatic #15 // Field MODULE$:LO$; 8: return } ``` After: ``` public final class O$ { public static final O$ MODULE$; public static {}; Code: 0: new #2 // class O$ 3: dup 4: invokespecial #12 // Method "<init>":()V 7: putstatic #14 // Field MODULE$:LO$; 10: return private O$(); Code: 0: aload_0 1: invokespecial #15 // Method java/lang/Object."<init>":()V 4: return } ``` The difference is observable is the constructor is called a second time with reflection/setAccessible. That used to overwrite the `MODULE$` field. I think few would argue that the new semantics are a clear improvement.
1 parent 25b29ea commit 53c7beb

File tree

2 files changed

+2
-7
lines changed

2 files changed

+2
-7
lines changed

src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -563,13 +563,6 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder {
563563
fun.symbol.javaSimpleName.toString == INSTANCE_CONSTRUCTOR_NAME &&
564564
isStaticModuleClass(claszSymbol)) {
565565
isModuleInitialized = true
566-
mnode.visitVarInsn(asm.Opcodes.ALOAD, 0)
567-
mnode.visitFieldInsn(
568-
asm.Opcodes.PUTSTATIC,
569-
thisBType.internalName,
570-
strMODULE_INSTANCE_FIELD,
571-
thisBType.descriptor
572-
)
573566
}
574567
}
575568
// 'super' call: Note: since constructors are supposed to

src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,10 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
217217
/* "legacy static initialization" */
218218
if (isCZStaticModule) {
219219
clinit.visitTypeInsn(asm.Opcodes.NEW, thisBType.internalName)
220+
clinit.visitInsn(asm.Opcodes.DUP)
220221
clinit.visitMethodInsn(asm.Opcodes.INVOKESPECIAL,
221222
thisBType.internalName, INSTANCE_CONSTRUCTOR_NAME, "()V", false)
223+
clinit.visitFieldInsn(asm.Opcodes.PUTSTATIC, thisBType.internalName, strMODULE_INSTANCE_FIELD, thisBType.descriptor)
222224
}
223225
if (isCZParcelable) { legacyAddCreatorCode(clinit, cnode, thisBType.internalName) }
224226
clinit.visitInsn(asm.Opcodes.RETURN)

0 commit comments

Comments
 (0)