diff --git a/src/main/java/org/jboss/jandex/ClassInfo.java b/src/main/java/org/jboss/jandex/ClassInfo.java index bd225e79..ebc589b3 100644 --- a/src/main/java/org/jboss/jandex/ClassInfo.java +++ b/src/main/java/org/jboss/jandex/ClassInfo.java @@ -59,17 +59,15 @@ public final class ClassInfo implements AnnotationTarget { // Not final to allow lazy initialization, immutable once published private short flags; + private boolean hasNoArgsConstructor; private Type[] interfaceTypes; private Type superClassType; - private Type[] typeParameters; private MethodInternal[] methods; private FieldInternal[] fields; - private RecordComponentInternal[] recordComponents; private byte[] methodPositions = EMPTY_POSITIONS; private byte[] fieldPositions = EMPTY_POSITIONS; - private byte[] recordComponentPositions = EMPTY_POSITIONS; - private boolean hasNoArgsConstructor; private NestingInfo nestingInfo; + private ExtraInfo extra; /** Describes the form of nesting used by a class */ public enum NestingType { @@ -86,16 +84,18 @@ public enum NestingType { ANONYMOUS } + // contains fields that are only seldom used, to make the `ClassInfo` class smaller + private static final class ExtraInfo { + private Type[] typeParameters; + private RecordComponentInternal[] recordComponents; + private byte[] recordComponentPositions = EMPTY_POSITIONS; + private ModuleInfo module; + } + private static final class NestingInfo { private DotName enclosingClass; private String simpleName; private EnclosingMethodInfo enclosingMethod; - - // non-null if the class is in fact a module descriptor - // this field would naturally belong to ClassInfo, but is present here - // to make the ClassInfo object smaller in the most common case: - // non-nested class that is not a module descriptor - private ModuleInfo module; } /** @@ -180,7 +180,6 @@ public String toString() { this.flags = flags; this.interfaceTypes = interfaceTypes.length == 0 ? Type.EMPTY_ARRAY : interfaceTypes; this.hasNoArgsConstructor = hasNoArgsConstructor; - this.typeParameters = Type.EMPTY_ARRAY; this.methods = MethodInternal.EMPTY_ARRAY; this.fields = FieldInternal.EMPTY_ARRAY; } @@ -537,12 +536,16 @@ final byte[] fieldPositionArray() { * @return the record component */ public final RecordComponentInfo recordComponent(String name) { + if (extra == null || extra.recordComponents == null) { + return null; + } + RecordComponentInternal key = new RecordComponentInternal(Utils.toUTF8(name), VoidType.VOID); - int i = Arrays.binarySearch(recordComponents, key, RecordComponentInternal.NAME_COMPARATOR); + int i = Arrays.binarySearch(extra.recordComponents, key, RecordComponentInternal.NAME_COMPARATOR); if (i < 0) { return null; } - return new RecordComponentInfo(this, recordComponents[i]); + return new RecordComponentInfo(this, extra.recordComponents[i]); } /** @@ -552,19 +555,27 @@ public final RecordComponentInfo recordComponent(String name) { * @return a list of record components */ public final List recordComponents() { - return new RecordComponentInfoGenerator(this, recordComponents, EMPTY_POSITIONS); + if (extra == null || extra.recordComponents == null) { + return Collections.emptyList(); + } + + return new RecordComponentInfoGenerator(this, extra.recordComponents, EMPTY_POSITIONS); } public final List unsortedRecordComponents() { - return new RecordComponentInfoGenerator(this, recordComponents, recordComponentPositions); + if (extra == null || extra.recordComponents == null) { + return Collections.emptyList(); + } + + return new RecordComponentInfoGenerator(this, extra.recordComponents, extra.recordComponentPositions); } final RecordComponentInternal[] recordComponentArray() { - return recordComponents; + return extra != null && extra.recordComponents != null ? extra.recordComponents : RecordComponentInternal.EMPTY_ARRAY; } final byte[] recordComponentPositionArray() { - return recordComponentPositions; + return extra != null && extra.recordComponentPositions != null ? extra.recordComponentPositions : EMPTY_POSITIONS; } @@ -624,12 +635,20 @@ public final Type superClassType() { * @return the generic type parameters of this class */ public final List typeParameters() { + if (extra == null || extra.typeParameters == null) { + return Collections.emptyList(); + } + // type parameters are always `TypeVariable` - return new ImmutableArrayList(typeParameters); + return new ImmutableArrayList(extra.typeParameters); } final Type[] typeParameterArray() { - return typeParameters; + if (extra == null || extra.typeParameters == null) { + return Type.EMPTY_ARRAY; + } + + return extra.typeParameters; } /** @@ -655,7 +674,7 @@ public final boolean hasNoArgsConstructor() { * @return the nesting type of this class */ public NestingType nestingType() { - if (nestingInfo == null || nestingInfo.module != null) { + if (nestingInfo == null) { return NestingType.TOP_LEVEL; } else if (nestingInfo.enclosingClass != null) { return NestingType.INNER; @@ -708,7 +727,7 @@ public EnclosingMethodInfo enclosingMethod() { * @return the module descriptor for module classes, otherwise null */ public ModuleInfo module() { - return nestingInfo != null ? nestingInfo.module : null; + return extra != null ? extra.module : null; } @Override @@ -802,31 +821,50 @@ void setMethods(List methods, NameTable names) { } void setRecordComponentArray(RecordComponentInternal[] recordComponents) { - this.recordComponents = recordComponents; + if (recordComponents.length == 0) { + return; + } + + if (extra == null) { + extra = new ExtraInfo(); + } + + extra.recordComponents = recordComponents; } void setRecordComponentPositionArray(byte[] recordComponentPositions) { - this.recordComponentPositions = recordComponentPositions; + if (recordComponentPositions.length == 0) { + return; + } + + if (extra == null) { + extra = new ExtraInfo(); + } + + extra.recordComponentPositions = recordComponentPositions; } void setRecordComponents(List recordComponents, NameTable names) { final int size = recordComponents.size(); if (size == 0) { - this.recordComponents = RecordComponentInternal.EMPTY_ARRAY; return; } - this.recordComponents = new RecordComponentInternal[size]; + if (extra == null) { + extra = new ExtraInfo(); + } + + extra.recordComponents = new RecordComponentInternal[size]; for (int i = 0; i < size; i++) { RecordComponentInfo recordComponentInfo = recordComponents.get(i); RecordComponentInternal internal = names.intern(recordComponentInfo.recordComponentInternal()); recordComponentInfo.setRecordComponentInternal(internal); - this.recordComponents[i] = internal; + extra.recordComponents[i] = internal; } - this.recordComponentPositions = sortAndGetPositions(this.recordComponents, RecordComponentInternal.NAME_COMPARATOR, names); + extra.recordComponentPositions = sortAndGetPositions(extra.recordComponents, RecordComponentInternal.NAME_COMPARATOR, names); } /** @@ -879,7 +917,15 @@ void setInterfaceTypes(Type[] interfaceTypes) { } void setTypeParameters(Type[] typeParameters) { - this.typeParameters = typeParameters.length == 0 ? Type.EMPTY_ARRAY : typeParameters; + if (typeParameters.length == 0) { + return; + } + + if (extra == null) { + extra = new ExtraInfo(); + } + + extra.typeParameters = typeParameters; } void setInnerClassInfo(DotName enclosingClass, String simpleName, boolean knownInnerClass) { @@ -916,11 +962,11 @@ void setModule(ModuleInfo module) { return; } - if (nestingInfo == null) { - nestingInfo = new NestingInfo(); + if (extra == null) { + extra = new ExtraInfo(); } - nestingInfo.module = module; + extra.module = module; } void setFlags(short flags) {