Move object initialization from <init> to <clinit>

Codegen generates static backing fields for object properties.
  They are initialized in class constructor but some of them are final static
  and such access is prohibited in specification but it's allowed in
  java bytecode <= 1.8. Such access in 1.9 bytecode cause
  "IllegalAccessError: Update to static final field Object.INSTANCE
  attempted from a different method (<init>) than the initializer method <clinit>"

  Added additional hidden field in interface companion to pass out
  companion instance from <clinit>.

 #KT-15894 Fixed
This commit is contained in:
Mikhael Bogdanov
2017-03-14 13:52:07 +01:00
committed by Ilya Gorbunov
parent de004337a2
commit b73be50e5b
13 changed files with 223 additions and 47 deletions
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.util.capitalizeDecapitalize.CapitalizeDecapitalizeKt
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isClassOrEnumClass;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface;
public final class JvmAbi {
public static final String DEFAULT_IMPLS_CLASS_NAME = "DefaultImpls";
@@ -54,6 +55,7 @@ public final class JvmAbi {
private static final String ANNOTATED_TYPEALIAS_METHOD_NAME_SUFFIX = ANNOTATIONS_SUFFIX;
public static final String INSTANCE_FIELD = "INSTANCE";
public static final String HIDDEN_INSTANCE_FIELD = "$$" + INSTANCE_FIELD;
public static final String DEFAULT_MODULE_NAME = "main";
public static final ClassId REFLECTION_FACTORY_IMPL = ClassId.topLevel(new FqName("kotlin.reflect.jvm.internal.ReflectionFactoryImpl"));
@@ -110,6 +112,16 @@ public final class JvmAbi {
public static boolean isCompanionObjectWithBackingFieldsInOuter(@NotNull DeclarationDescriptor companionObject) {
return isCompanionObject(companionObject) &&
isClassOrEnumClass(companionObject.getContainingDeclaration()) &&
!CompanionObjectMapping.INSTANCE.isMappedIntrinsicCompanionObject((ClassDescriptor) companionObject);
!isMappedIntrinsicCompanionObject((ClassDescriptor) companionObject);
}
public static boolean isMappedIntrinsicCompanionObject(@NotNull ClassDescriptor companionObject) {
return CompanionObjectMapping.INSTANCE.isMappedIntrinsicCompanionObject(companionObject);
}
public static boolean isCompanionObjectInInterfaceNotIntrinsic(@NotNull DeclarationDescriptor companionObject) {
return isCompanionObject(companionObject) &&
isInterface(companionObject.getContainingDeclaration()) &&
!isMappedIntrinsicCompanionObject((ClassDescriptor) companionObject);
}
}