8317356: Fix missing null checks in the ClassFile API

Co-authored-by: Nizar Benalla <nbenalla@openjdk.org>
Reviewed-by: asotona
This commit is contained in:
Chen Liang 2024-10-14 17:21:10 +00:00
parent 60713463c7
commit a2c775222e
36 changed files with 249 additions and 116 deletions

View file

@ -42,6 +42,8 @@ import java.util.List;
import jdk.internal.classfile.impl.Util; import jdk.internal.classfile.impl.Util;
import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.PreviewFeature;
import static java.util.Objects.requireNonNull;
/** /**
* Models an {@code element_value} structure, or a value of an element-value * Models an {@code element_value} structure, or a value of an element-value
* pair of an annotation, as defined in JVMS {@jvms 4.7.16.1}. * pair of an annotation, as defined in JVMS {@jvms 4.7.16.1}.
@ -488,6 +490,8 @@ public sealed interface AnnotationValue {
*/ */
static OfEnum ofEnum(Utf8Entry className, static OfEnum ofEnum(Utf8Entry className,
Utf8Entry constantName) { Utf8Entry constantName) {
requireNonNull(className);
requireNonNull(constantName);
return new AnnotationImpl.OfEnumImpl(className, constantName); return new AnnotationImpl.OfEnumImpl(className, constantName);
} }
@ -506,6 +510,7 @@ public sealed interface AnnotationValue {
* @param className the descriptor string of the class * @param className the descriptor string of the class
*/ */
static OfClass ofClass(Utf8Entry className) { static OfClass ofClass(Utf8Entry className) {
requireNonNull(className);
return new AnnotationImpl.OfClassImpl(className); return new AnnotationImpl.OfClassImpl(className);
} }
@ -522,6 +527,7 @@ public sealed interface AnnotationValue {
* @param value the string * @param value the string
*/ */
static OfString ofString(Utf8Entry value) { static OfString ofString(Utf8Entry value) {
requireNonNull(value);
return new AnnotationImpl.OfStringImpl(value); return new AnnotationImpl.OfStringImpl(value);
} }
@ -538,6 +544,7 @@ public sealed interface AnnotationValue {
* @param value the double value * @param value the double value
*/ */
static OfDouble ofDouble(DoubleEntry value) { static OfDouble ofDouble(DoubleEntry value) {
requireNonNull(value);
return new AnnotationImpl.OfDoubleImpl(value); return new AnnotationImpl.OfDoubleImpl(value);
} }
@ -554,6 +561,7 @@ public sealed interface AnnotationValue {
* @param value the float value * @param value the float value
*/ */
static OfFloat ofFloat(FloatEntry value) { static OfFloat ofFloat(FloatEntry value) {
requireNonNull(value);
return new AnnotationImpl.OfFloatImpl(value); return new AnnotationImpl.OfFloatImpl(value);
} }
@ -570,6 +578,7 @@ public sealed interface AnnotationValue {
* @param value the long value * @param value the long value
*/ */
static OfLong ofLong(LongEntry value) { static OfLong ofLong(LongEntry value) {
requireNonNull(value);
return new AnnotationImpl.OfLongImpl(value); return new AnnotationImpl.OfLongImpl(value);
} }
@ -586,6 +595,7 @@ public sealed interface AnnotationValue {
* @param value the int value * @param value the int value
*/ */
static OfInt ofInt(IntegerEntry value) { static OfInt ofInt(IntegerEntry value) {
requireNonNull(value);
return new AnnotationImpl.OfIntImpl(value); return new AnnotationImpl.OfIntImpl(value);
} }
@ -602,6 +612,7 @@ public sealed interface AnnotationValue {
* @param value the short value * @param value the short value
*/ */
static OfShort ofShort(IntegerEntry value) { static OfShort ofShort(IntegerEntry value) {
requireNonNull(value);
return new AnnotationImpl.OfShortImpl(value); return new AnnotationImpl.OfShortImpl(value);
} }
@ -618,6 +629,7 @@ public sealed interface AnnotationValue {
* @param value the char value * @param value the char value
*/ */
static OfChar ofChar(IntegerEntry value) { static OfChar ofChar(IntegerEntry value) {
requireNonNull(value);
return new AnnotationImpl.OfCharImpl(value); return new AnnotationImpl.OfCharImpl(value);
} }
@ -634,6 +646,7 @@ public sealed interface AnnotationValue {
* @param value the byte value * @param value the byte value
*/ */
static OfByte ofByte(IntegerEntry value) { static OfByte ofByte(IntegerEntry value) {
requireNonNull(value);
return new AnnotationImpl.OfByteImpl(value); return new AnnotationImpl.OfByteImpl(value);
} }
@ -650,6 +663,7 @@ public sealed interface AnnotationValue {
* @param value the boolean value * @param value the boolean value
*/ */
static OfBoolean ofBoolean(IntegerEntry value) { static OfBoolean ofBoolean(IntegerEntry value) {
requireNonNull(value);
return new AnnotationImpl.OfBooleanImpl(value); return new AnnotationImpl.OfBooleanImpl(value);
} }
@ -667,6 +681,7 @@ public sealed interface AnnotationValue {
* @param value the annotation * @param value the annotation
*/ */
static OfAnnotation ofAnnotation(Annotation value) { static OfAnnotation ofAnnotation(Annotation value) {
requireNonNull(value);
return new AnnotationImpl.OfAnnotationImpl(value); return new AnnotationImpl.OfAnnotationImpl(value);
} }
@ -784,6 +799,6 @@ public sealed interface AnnotationValue {
} else if (value instanceof Enum<?> e) { } else if (value instanceof Enum<?> e) {
return ofEnum(ClassDesc.ofDescriptor(e.getDeclaringClass().descriptorString()), e.name()); return ofEnum(ClassDesc.ofDescriptor(e.getDeclaringClass().descriptorString()), e.name());
} }
throw new IllegalArgumentException("Illegal annotation constant value type " + (value == null ? null : value.getClass())); throw new IllegalArgumentException("Illegal annotation constant value type " + requireNonNull(value).getClass());
} }
} }

View file

@ -33,6 +33,8 @@ import java.lang.classfile.attribute.RecordComponentInfo;
import jdk.internal.classfile.impl.AbstractUnboundModel; import jdk.internal.classfile.impl.AbstractUnboundModel;
import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.PreviewFeature;
import static java.util.Objects.requireNonNull;
/** /**
* A {@link ClassFileElement} describing an entity that has attributes, such * A {@link ClassFileElement} describing an entity that has attributes, such
* as a class, field, method, code attribute, or record component. * as a class, field, method, code attribute, or record component.
@ -58,6 +60,7 @@ public sealed interface AttributedElement extends ClassFileElement
* is not present * is not present
*/ */
default <T extends Attribute<T>> Optional<T> findAttribute(AttributeMapper<T> attr) { default <T extends Attribute<T>> Optional<T> findAttribute(AttributeMapper<T> attr) {
requireNonNull(attr);
for (Attribute<?> la : attributes()) { for (Attribute<?> la : attributes()) {
if (la.attributeMapper() == attr) { if (la.attributeMapper() == attr) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -76,6 +79,7 @@ public sealed interface AttributedElement extends ClassFileElement
* is not present * is not present
*/ */
default <T extends Attribute<T>> List<T> findAttributes(AttributeMapper<T> attr) { default <T extends Attribute<T>> List<T> findAttributes(AttributeMapper<T> attr) {
requireNonNull(attr);
var list = new ArrayList<T>(); var list = new ArrayList<T>();
for (var a : attributes()) { for (var a : attributes()) {
if (a.attributeMapper() == attr) { if (a.attributeMapper() == attr) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -39,6 +39,8 @@ import jdk.internal.classfile.impl.ClassHierarchyImpl.StaticClassHierarchyResolv
import jdk.internal.classfile.impl.Util; import jdk.internal.classfile.impl.Util;
import static java.lang.constant.ConstantDescs.CD_Object; import static java.lang.constant.ConstantDescs.CD_Object;
import static java.util.Objects.requireNonNull;
import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.PreviewFeature;
/** /**
@ -106,6 +108,7 @@ public interface ClassHierarchyResolver {
* other resolver in cases where this resolver returns {@code null}. * other resolver in cases where this resolver returns {@code null}.
*/ */
default ClassHierarchyResolver orElse(ClassHierarchyResolver other) { default ClassHierarchyResolver orElse(ClassHierarchyResolver other) {
requireNonNull(other);
return new ClassHierarchyResolver() { return new ClassHierarchyResolver() {
@Override @Override
public ClassHierarchyInfo getClassInfo(ClassDesc classDesc) { public ClassHierarchyInfo getClassInfo(ClassDesc classDesc) {
@ -170,7 +173,7 @@ public interface ClassHierarchyResolver {
* @return the {@linkplain ClassHierarchyResolver} * @return the {@linkplain ClassHierarchyResolver}
*/ */
static ClassHierarchyResolver ofResourceParsing(Function<ClassDesc, InputStream> classStreamResolver) { static ClassHierarchyResolver ofResourceParsing(Function<ClassDesc, InputStream> classStreamResolver) {
return new ClassHierarchyImpl.ResourceParsingClassHierarchyResolver(classStreamResolver); return new ClassHierarchyImpl.ResourceParsingClassHierarchyResolver(requireNonNull(classStreamResolver));
} }
/** /**
@ -181,6 +184,7 @@ public interface ClassHierarchyResolver {
* @return the {@linkplain ClassHierarchyResolver} * @return the {@linkplain ClassHierarchyResolver}
*/ */
static ClassHierarchyResolver ofResourceParsing(ClassLoader loader) { static ClassHierarchyResolver ofResourceParsing(ClassLoader loader) {
requireNonNull(loader);
return ofResourceParsing(new Function<>() { return ofResourceParsing(new Function<>() {
@Override @Override
public InputStream apply(ClassDesc classDesc) { public InputStream apply(ClassDesc classDesc) {
@ -210,6 +214,7 @@ public interface ClassHierarchyResolver {
* @return the class hierarchy resolver * @return the class hierarchy resolver
*/ */
static ClassHierarchyResolver ofClassLoading(ClassLoader loader) { static ClassHierarchyResolver ofClassLoading(ClassLoader loader) {
requireNonNull(loader);
return new ClassLoadingClassHierarchyResolver(new Function<>() { return new ClassLoadingClassHierarchyResolver(new Function<>() {
@Override @Override
public Class<?> apply(ClassDesc cd) { public Class<?> apply(ClassDesc cd) {
@ -232,6 +237,7 @@ public interface ClassHierarchyResolver {
* @return the class hierarchy resolver * @return the class hierarchy resolver
*/ */
static ClassHierarchyResolver ofClassLoading(MethodHandles.Lookup lookup) { static ClassHierarchyResolver ofClassLoading(MethodHandles.Lookup lookup) {
requireNonNull(lookup);
return new ClassLoadingClassHierarchyResolver(new Function<>() { return new ClassLoadingClassHierarchyResolver(new Function<>() {
@Override @Override
public Class<?> apply(ClassDesc cd) { public Class<?> apply(ClassDesc cd) {

View file

@ -32,6 +32,8 @@ import java.lang.classfile.attribute.CodeAttribute;
import jdk.internal.classfile.impl.TransformImpl; import jdk.internal.classfile.impl.TransformImpl;
import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.PreviewFeature;
import static java.util.Objects.requireNonNull;
/** /**
* A transformation on streams of {@link ClassElement}. * A transformation on streams of {@link ClassElement}.
* *
@ -63,7 +65,7 @@ public non-sealed interface ClassTransform
* @return the stateful class transform * @return the stateful class transform
*/ */
static ClassTransform ofStateful(Supplier<ClassTransform> supplier) { static ClassTransform ofStateful(Supplier<ClassTransform> supplier) {
return new TransformImpl.SupplierClassTransform(supplier); return new TransformImpl.SupplierClassTransform(requireNonNull(supplier));
} }
/** /**
@ -74,6 +76,7 @@ public non-sealed interface ClassTransform
* @return the class transform * @return the class transform
*/ */
static ClassTransform endHandler(Consumer<ClassBuilder> finisher) { static ClassTransform endHandler(Consumer<ClassBuilder> finisher) {
requireNonNull(finisher);
return new ClassTransform() { return new ClassTransform() {
@Override @Override
public void accept(ClassBuilder builder, ClassElement element) { public void accept(ClassBuilder builder, ClassElement element) {
@ -95,6 +98,7 @@ public non-sealed interface ClassTransform
* @return the class transform * @return the class transform
*/ */
static ClassTransform dropping(Predicate<ClassElement> filter) { static ClassTransform dropping(Predicate<ClassElement> filter) {
requireNonNull(filter);
return (b, e) -> { return (b, e) -> {
if (!filter.test(e)) if (!filter.test(e))
b.with(e); b.with(e);
@ -111,7 +115,7 @@ public non-sealed interface ClassTransform
*/ */
static ClassTransform transformingMethods(Predicate<MethodModel> filter, static ClassTransform transformingMethods(Predicate<MethodModel> filter,
MethodTransform xform) { MethodTransform xform) {
return new TransformImpl.ClassMethodTransform(xform, filter); return new TransformImpl.ClassMethodTransform(requireNonNull(xform), requireNonNull(filter));
} }
/** /**
@ -122,7 +126,7 @@ public non-sealed interface ClassTransform
* @return the class transform * @return the class transform
*/ */
static ClassTransform transformingMethods(MethodTransform xform) { static ClassTransform transformingMethods(MethodTransform xform) {
return transformingMethods(mm -> true, xform); return transformingMethods(_ -> true, xform);
} }
/** /**
@ -157,7 +161,7 @@ public non-sealed interface ClassTransform
* @return the class transform * @return the class transform
*/ */
static ClassTransform transformingFields(FieldTransform xform) { static ClassTransform transformingFields(FieldTransform xform) {
return new TransformImpl.ClassFieldTransform(xform, f -> true); return new TransformImpl.ClassFieldTransform(requireNonNull(xform), _ -> true);
} }
/** /**
@ -169,6 +173,6 @@ public non-sealed interface ClassTransform
*/ */
@Override @Override
default ClassTransform andThen(ClassTransform t) { default ClassTransform andThen(ClassTransform t) {
return new TransformImpl.ChainedClassTransform(this, t); return new TransformImpl.ChainedClassTransform(this, requireNonNull(t));
} }
} }

View file

@ -30,6 +30,8 @@ import java.util.function.Supplier;
import jdk.internal.classfile.impl.TransformImpl; import jdk.internal.classfile.impl.TransformImpl;
import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.PreviewFeature;
import static java.util.Objects.requireNonNull;
/** /**
* A transformation on streams of {@link CodeElement}. * A transformation on streams of {@link CodeElement}.
* *
@ -61,7 +63,7 @@ public non-sealed interface CodeTransform
* @return the stateful code transform * @return the stateful code transform
*/ */
static CodeTransform ofStateful(Supplier<CodeTransform> supplier) { static CodeTransform ofStateful(Supplier<CodeTransform> supplier) {
return new TransformImpl.SupplierCodeTransform(supplier); return new TransformImpl.SupplierCodeTransform(requireNonNull(supplier));
} }
/** /**
@ -72,6 +74,7 @@ public non-sealed interface CodeTransform
* @return the code transform * @return the code transform
*/ */
static CodeTransform endHandler(Consumer<CodeBuilder> finisher) { static CodeTransform endHandler(Consumer<CodeBuilder> finisher) {
requireNonNull(finisher);
return new CodeTransform() { return new CodeTransform() {
@Override @Override
public void accept(CodeBuilder builder, CodeElement element) { public void accept(CodeBuilder builder, CodeElement element) {
@ -94,6 +97,6 @@ public non-sealed interface CodeTransform
*/ */
@Override @Override
default CodeTransform andThen(CodeTransform t) { default CodeTransform andThen(CodeTransform t) {
return new TransformImpl.ChainedCodeTransform(this, t); return new TransformImpl.ChainedCodeTransform(this, requireNonNull(t));
} }
} }

View file

@ -31,6 +31,8 @@ import java.util.function.Supplier;
import jdk.internal.classfile.impl.TransformImpl; import jdk.internal.classfile.impl.TransformImpl;
import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.PreviewFeature;
import static java.util.Objects.requireNonNull;
/** /**
* A transformation on streams of {@link FieldElement}. * A transformation on streams of {@link FieldElement}.
* *
@ -62,7 +64,7 @@ public non-sealed interface FieldTransform
* @return the stateful field transform * @return the stateful field transform
*/ */
static FieldTransform ofStateful(Supplier<FieldTransform> supplier) { static FieldTransform ofStateful(Supplier<FieldTransform> supplier) {
return new TransformImpl.SupplierFieldTransform(supplier); return new TransformImpl.SupplierFieldTransform(requireNonNull(supplier));
} }
/** /**
@ -73,6 +75,7 @@ public non-sealed interface FieldTransform
* @return the field transform * @return the field transform
*/ */
static FieldTransform endHandler(Consumer<FieldBuilder> finisher) { static FieldTransform endHandler(Consumer<FieldBuilder> finisher) {
requireNonNull(finisher);
return new FieldTransform() { return new FieldTransform() {
@Override @Override
public void accept(FieldBuilder builder, FieldElement element) { public void accept(FieldBuilder builder, FieldElement element) {
@ -94,6 +97,7 @@ public non-sealed interface FieldTransform
* @return the field transform * @return the field transform
*/ */
static FieldTransform dropping(Predicate<FieldElement> filter) { static FieldTransform dropping(Predicate<FieldElement> filter) {
requireNonNull(filter);
return (b, e) -> { return (b, e) -> {
if (!filter.test(e)) if (!filter.test(e))
b.with(e); b.with(e);
@ -109,6 +113,6 @@ public non-sealed interface FieldTransform
*/ */
@Override @Override
default FieldTransform andThen(FieldTransform t) { default FieldTransform andThen(FieldTransform t) {
return new TransformImpl.ChainedFieldTransform(this, t); return new TransformImpl.ChainedFieldTransform(this, requireNonNull(t));
} }
} }

View file

@ -31,6 +31,8 @@ import java.util.function.Supplier;
import jdk.internal.classfile.impl.TransformImpl; import jdk.internal.classfile.impl.TransformImpl;
import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.PreviewFeature;
import static java.util.Objects.requireNonNull;
/** /**
* A transformation on streams of {@link MethodElement}. * A transformation on streams of {@link MethodElement}.
* *
@ -62,6 +64,7 @@ public non-sealed interface MethodTransform
* @return the stateful method transform * @return the stateful method transform
*/ */
static MethodTransform ofStateful(Supplier<MethodTransform> supplier) { static MethodTransform ofStateful(Supplier<MethodTransform> supplier) {
requireNonNull(supplier);
return new TransformImpl.SupplierMethodTransform(supplier); return new TransformImpl.SupplierMethodTransform(supplier);
} }
@ -73,6 +76,7 @@ public non-sealed interface MethodTransform
* @return the method transform * @return the method transform
*/ */
static MethodTransform endHandler(Consumer<MethodBuilder> finisher) { static MethodTransform endHandler(Consumer<MethodBuilder> finisher) {
requireNonNull(finisher);
return new MethodTransform() { return new MethodTransform() {
@Override @Override
public void accept(MethodBuilder builder, MethodElement element) { public void accept(MethodBuilder builder, MethodElement element) {
@ -94,6 +98,7 @@ public non-sealed interface MethodTransform
* @return the method transform * @return the method transform
*/ */
static MethodTransform dropping(Predicate<MethodElement> filter) { static MethodTransform dropping(Predicate<MethodElement> filter) {
requireNonNull(filter);
return (b, e) -> { return (b, e) -> {
if (!filter.test(e)) if (!filter.test(e))
b.with(e); b.with(e);
@ -108,7 +113,7 @@ public non-sealed interface MethodTransform
* @return the class transform * @return the class transform
*/ */
static MethodTransform transformingCode(CodeTransform xform) { static MethodTransform transformingCode(CodeTransform xform) {
return new TransformImpl.MethodCodeTransform(xform); return new TransformImpl.MethodCodeTransform(requireNonNull(xform));
} }
/** /**
@ -120,6 +125,6 @@ public non-sealed interface MethodTransform
*/ */
@Override @Override
default MethodTransform andThen(MethodTransform t) { default MethodTransform andThen(MethodTransform t) {
return new TransformImpl.ChainedMethodTransform(this, t); return new TransformImpl.ChainedMethodTransform(this, requireNonNull(t));
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -36,6 +36,8 @@ import java.lang.classfile.MethodTransform;
import jdk.internal.classfile.impl.ClassRemapperImpl; import jdk.internal.classfile.impl.ClassRemapperImpl;
import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.PreviewFeature;
import static java.util.Objects.requireNonNull;
/** /**
* {@code ClassRemapper} is a {@link ClassTransform}, {@link FieldTransform}, * {@code ClassRemapper} is a {@link ClassTransform}, {@link FieldTransform},
* {@link MethodTransform} and {@link CodeTransform} * {@link MethodTransform} and {@link CodeTransform}
@ -64,6 +66,7 @@ public sealed interface ClassRemapper extends ClassTransform permits ClassRemapp
* @return new instance of {@code ClassRemapper} * @return new instance of {@code ClassRemapper}
*/ */
static ClassRemapper of(Map<ClassDesc, ClassDesc> classMap) { static ClassRemapper of(Map<ClassDesc, ClassDesc> classMap) {
requireNonNull(classMap);
return of(desc -> classMap.getOrDefault(desc, desc)); return of(desc -> classMap.getOrDefault(desc, desc));
} }
@ -75,7 +78,7 @@ public sealed interface ClassRemapper extends ClassTransform permits ClassRemapp
* @return new instance of {@code ClassRemapper} * @return new instance of {@code ClassRemapper}
*/ */
static ClassRemapper of(Function<ClassDesc, ClassDesc> mapFunction) { static ClassRemapper of(Function<ClassDesc, ClassDesc> mapFunction) {
return new ClassRemapperImpl(mapFunction); return new ClassRemapperImpl(requireNonNull(mapFunction));
} }
/** /**

View file

@ -33,6 +33,8 @@ import java.lang.classfile.Label;
import jdk.internal.classfile.impl.CodeRelabelerImpl; import jdk.internal.classfile.impl.CodeRelabelerImpl;
import jdk.internal.javac.PreviewFeature; import jdk.internal.javac.PreviewFeature;
import static java.util.Objects.requireNonNull;
/** /**
* A code relabeler is a {@link CodeTransform} replacing all occurrences * A code relabeler is a {@link CodeTransform} replacing all occurrences
* of {@link java.lang.classfile.Label} in the transformed code with new instances. * of {@link java.lang.classfile.Label} in the transformed code with new instances.
@ -62,6 +64,7 @@ public sealed interface CodeRelabeler extends CodeTransform permits CodeRelabele
* @return a new instance of CodeRelabeler * @return a new instance of CodeRelabeler
*/ */
static CodeRelabeler of(Map<Label, Label> map) { static CodeRelabeler of(Map<Label, Label> map) {
requireNonNull(map);
return of((l, cob) -> map.computeIfAbsent(l, ll -> cob.newLabel())); return of((l, cob) -> map.computeIfAbsent(l, ll -> cob.newLabel()));
} }
@ -72,6 +75,6 @@ public sealed interface CodeRelabeler extends CodeTransform permits CodeRelabele
* @return a new instance of CodeRelabeler * @return a new instance of CodeRelabeler
*/ */
static CodeRelabeler of(BiFunction<Label, CodeBuilder, Label> mapFunction) { static CodeRelabeler of(BiFunction<Label, CodeBuilder, Label> mapFunction) {
return new CodeRelabelerImpl(mapFunction); return new CodeRelabelerImpl(requireNonNull(mapFunction));
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it

View file

@ -54,6 +54,7 @@ import java.lang.classfile.CodeBuilder;
import java.lang.classfile.TypeKind; import java.lang.classfile.TypeKind;
import jdk.internal.constant.ConstantUtils; import jdk.internal.constant.ConstantUtils;
import jdk.internal.loader.ClassLoaders;
import jdk.internal.module.Modules; import jdk.internal.module.Modules;
import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection; import jdk.internal.reflect.Reflection;
@ -371,7 +372,8 @@ public class MethodHandleProxies {
*/ */
private static byte[] createTemplate(ClassLoader loader, ClassDesc proxyDesc, ClassDesc ifaceDesc, private static byte[] createTemplate(ClassLoader loader, ClassDesc proxyDesc, ClassDesc ifaceDesc,
String methodName, List<MethodInfo> methods) { String methodName, List<MethodInfo> methods) {
return ClassFile.of(ClassHierarchyResolverOption.of(ClassHierarchyResolver.ofClassLoading(loader))) return ClassFile.of(ClassHierarchyResolverOption.of(ClassHierarchyResolver.ofClassLoading(loader == null ?
ClassLoaders.platformClassLoader() : loader)))
.build(proxyDesc, clb -> { .build(proxyDesc, clb -> {
clb.withSuperclass(CD_Object) clb.withSuperclass(CD_Object)
.withFlags(ACC_FINAL | ACC_SYNTHETIC) .withFlags(ACC_FINAL | ACC_SYNTHETIC)

View file

@ -66,6 +66,8 @@ import java.lang.classfile.Label;
import java.lang.classfile.Opcode; import java.lang.classfile.Opcode;
import java.lang.classfile.TypeKind; import java.lang.classfile.TypeKind;
import static java.util.Objects.requireNonNull;
public abstract sealed class AbstractInstruction public abstract sealed class AbstractInstruction
extends AbstractElement extends AbstractElement
implements Instruction { implements Instruction {
@ -247,6 +249,9 @@ public abstract sealed class AbstractInstruction
public record SwitchCaseImpl(int caseValue, Label target) public record SwitchCaseImpl(int caseValue, Label target)
implements SwitchCase { implements SwitchCase {
public SwitchCaseImpl {
requireNonNull(target);
}
} }
public static final class BoundLookupSwitchInstruction public static final class BoundLookupSwitchInstruction
@ -892,7 +897,7 @@ public abstract sealed class AbstractInstruction
public UnboundBranchInstruction(Opcode op, Label target) { public UnboundBranchInstruction(Opcode op, Label target) {
super(op); super(op);
this.target = target; this.target = requireNonNull(target);
} }
@Override @Override
@ -919,7 +924,7 @@ public abstract sealed class AbstractInstruction
public UnboundLookupSwitchInstruction(Label defaultTarget, List<SwitchCase> cases) { public UnboundLookupSwitchInstruction(Label defaultTarget, List<SwitchCase> cases) {
super(Opcode.LOOKUPSWITCH); super(Opcode.LOOKUPSWITCH);
this.defaultTarget = defaultTarget; this.defaultTarget = requireNonNull(defaultTarget);
this.cases = List.copyOf(cases); this.cases = List.copyOf(cases);
} }
@ -955,7 +960,7 @@ public abstract sealed class AbstractInstruction
super(Opcode.TABLESWITCH); super(Opcode.TABLESWITCH);
this.lowValue = lowValue; this.lowValue = lowValue;
this.highValue = highValue; this.highValue = highValue;
this.defaultTarget = defaultTarget; this.defaultTarget = requireNonNull(defaultTarget);
this.cases = List.copyOf(cases); this.cases = List.copyOf(cases);
} }
@ -1030,7 +1035,7 @@ public abstract sealed class AbstractInstruction
public UnboundFieldInstruction(Opcode op, public UnboundFieldInstruction(Opcode op,
FieldRefEntry fieldEntry) { FieldRefEntry fieldEntry) {
super(op); super(op);
this.fieldEntry = fieldEntry; this.fieldEntry = requireNonNull(fieldEntry);
} }
@Override @Override
@ -1055,7 +1060,7 @@ public abstract sealed class AbstractInstruction
public UnboundInvokeInstruction(Opcode op, MemberRefEntry methodEntry) { public UnboundInvokeInstruction(Opcode op, MemberRefEntry methodEntry) {
super(op); super(op);
this.methodEntry = methodEntry; this.methodEntry = requireNonNull(methodEntry);
} }
@Override @Override
@ -1095,7 +1100,7 @@ public abstract sealed class AbstractInstruction
public UnboundInvokeDynamicInstruction(InvokeDynamicEntry indyEntry) { public UnboundInvokeDynamicInstruction(InvokeDynamicEntry indyEntry) {
super(Opcode.INVOKEDYNAMIC); super(Opcode.INVOKEDYNAMIC);
this.indyEntry = indyEntry; this.indyEntry = requireNonNull(indyEntry);
} }
@Override @Override
@ -1120,7 +1125,7 @@ public abstract sealed class AbstractInstruction
public UnboundNewObjectInstruction(ClassEntry classEntry) { public UnboundNewObjectInstruction(ClassEntry classEntry) {
super(Opcode.NEW); super(Opcode.NEW);
this.classEntry = classEntry; this.classEntry = requireNonNull(classEntry);
} }
@Override @Override
@ -1145,7 +1150,7 @@ public abstract sealed class AbstractInstruction
public UnboundNewPrimitiveArrayInstruction(TypeKind typeKind) { public UnboundNewPrimitiveArrayInstruction(TypeKind typeKind) {
super(Opcode.NEWARRAY); super(Opcode.NEWARRAY);
this.typeKind = typeKind; this.typeKind = requireNonNull(typeKind);
} }
@Override @Override
@ -1170,7 +1175,7 @@ public abstract sealed class AbstractInstruction
public UnboundNewReferenceArrayInstruction(ClassEntry componentTypeEntry) { public UnboundNewReferenceArrayInstruction(ClassEntry componentTypeEntry) {
super(Opcode.ANEWARRAY); super(Opcode.ANEWARRAY);
this.componentTypeEntry = componentTypeEntry; this.componentTypeEntry = requireNonNull(componentTypeEntry);
} }
@Override @Override
@ -1197,7 +1202,7 @@ public abstract sealed class AbstractInstruction
public UnboundNewMultidimensionalArrayInstruction(ClassEntry arrayTypeEntry, public UnboundNewMultidimensionalArrayInstruction(ClassEntry arrayTypeEntry,
int dimensions) { int dimensions) {
super(Opcode.MULTIANEWARRAY); super(Opcode.MULTIANEWARRAY);
this.arrayTypeEntry = arrayTypeEntry; this.arrayTypeEntry = requireNonNull(arrayTypeEntry);
this.dimensions = dimensions; this.dimensions = dimensions;
} }
@ -1255,7 +1260,7 @@ public abstract sealed class AbstractInstruction
public UnboundTypeCheckInstruction(Opcode op, ClassEntry typeEntry) { public UnboundTypeCheckInstruction(Opcode op, ClassEntry typeEntry) {
super(op); super(op);
this.typeEntry = typeEntry; this.typeEntry = requireNonNull(typeEntry);
} }
@Override @Override
@ -1357,7 +1362,7 @@ public abstract sealed class AbstractInstruction
public UnboundLoadConstantInstruction(Opcode op, LoadableConstantEntry constant) { public UnboundLoadConstantInstruction(Opcode op, LoadableConstantEntry constant) {
super(op); super(op);
this.constant = constant; this.constant = requireNonNull(constant);
} }
@Override @Override
@ -1405,7 +1410,7 @@ public abstract sealed class AbstractInstruction
public UnboundJsrInstruction(Opcode op, Label target) { public UnboundJsrInstruction(Opcode op, Label target) {
super(op); super(op);
this.target = target; this.target = requireNonNull(target);
} }
@Override @Override

View file

@ -56,6 +56,8 @@ import jdk.internal.access.SharedSecrets;
import jdk.internal.util.ArraysSupport; import jdk.internal.util.ArraysSupport;
import jdk.internal.vm.annotation.Stable; import jdk.internal.vm.annotation.Stable;
import static java.util.Objects.requireNonNull;
public abstract sealed class AbstractPoolEntry { public abstract sealed class AbstractPoolEntry {
/* /*
Invariant: a {CP,BSM} entry for pool P refer only to {CP,BSM} entries Invariant: a {CP,BSM} entry for pool P refer only to {CP,BSM} entries
@ -439,7 +441,7 @@ public abstract sealed class AbstractPoolEntry {
inflate(); inflate();
switch (state) { switch (state) {
case STRING: case STRING:
return stringValue.equals(s); return stringValue.equals(requireNonNull(s));
case CHAR: case CHAR:
if (charLen != s.length() || contentHash != s.hashCode()) if (charLen != s.length() || contentHash != s.hashCode())
return false; return false;

View file

@ -36,6 +36,8 @@ import java.lang.classfile.instruction.LocalVariableType;
import java.lang.classfile.Label; import java.lang.classfile.Label;
import java.lang.classfile.PseudoInstruction; import java.lang.classfile.PseudoInstruction;
import static java.util.Objects.requireNonNull;
public abstract sealed class AbstractPseudoInstruction public abstract sealed class AbstractPseudoInstruction
extends AbstractElement extends AbstractElement
implements PseudoInstruction { implements PseudoInstruction {
@ -55,17 +57,14 @@ public abstract sealed class AbstractPseudoInstruction
public ExceptionCatchImpl(Label handler, Label tryStart, Label tryEnd, public ExceptionCatchImpl(Label handler, Label tryStart, Label tryEnd,
ClassEntry catchTypeEntry) { ClassEntry catchTypeEntry) {
this.catchTypeEntry = catchTypeEntry; this.catchTypeEntry = catchTypeEntry;
this.handler = handler; this.handler = requireNonNull(handler);
this.tryStart = tryStart; this.tryStart = requireNonNull(tryStart);
this.tryEnd = tryEnd; this.tryEnd = requireNonNull(tryEnd);
} }
public ExceptionCatchImpl(Label handler, Label tryStart, Label tryEnd, public ExceptionCatchImpl(Label handler, Label tryStart, Label tryEnd,
Optional<ClassEntry> catchTypeEntry) { Optional<ClassEntry> catchTypeEntry) {
this.catchTypeEntry = catchTypeEntry.orElse(null); this(handler, tryStart, tryEnd, catchTypeEntry.orElse(null));
this.handler = handler;
this.tryStart = tryStart;
this.tryEnd = tryEnd;
} }
@Override @Override
@ -115,8 +114,8 @@ public abstract sealed class AbstractPseudoInstruction
public UnboundCharacterRange(Label startScope, Label endScope, int characterRangeStart, public UnboundCharacterRange(Label startScope, Label endScope, int characterRangeStart,
int characterRangeEnd, int flags) { int characterRangeEnd, int flags) {
this.startScope = startScope; this.startScope = requireNonNull(startScope);
this.endScope = endScope; this.endScope = requireNonNull(endScope);
this.characterRangeStart = characterRangeStart; this.characterRangeStart = characterRangeStart;
this.characterRangeEnd = characterRangeEnd; this.characterRangeEnd = characterRangeEnd;
this.flags = flags; this.flags = flags;
@ -165,10 +164,10 @@ public abstract sealed class AbstractPseudoInstruction
public AbstractLocalPseudo(int slot, Utf8Entry name, Utf8Entry descriptor, Label startScope, Label endScope) { public AbstractLocalPseudo(int slot, Utf8Entry name, Utf8Entry descriptor, Label startScope, Label endScope) {
BytecodeHelpers.validateSlot(slot); BytecodeHelpers.validateSlot(slot);
this.slot = slot; this.slot = slot;
this.name = name; this.name = requireNonNull(name);
this.descriptor = descriptor; this.descriptor = requireNonNull(descriptor);
this.startScope = startScope; this.startScope = requireNonNull(startScope);
this.endScope = endScope; this.endScope = requireNonNull(endScope);
} }
public int slot() { public int slot() {

View file

@ -29,9 +29,12 @@ import java.lang.classfile.constantpool.*;
import java.util.List; import java.util.List;
import static java.util.Objects.requireNonNull;
public record AnnotationImpl(Utf8Entry className, List<AnnotationElement> elements) public record AnnotationImpl(Utf8Entry className, List<AnnotationElement> elements)
implements Annotation { implements Annotation {
public AnnotationImpl { public AnnotationImpl {
requireNonNull(className);
elements = List.copyOf(elements); elements = List.copyOf(elements);
} }
@ -50,6 +53,11 @@ public record AnnotationImpl(Utf8Entry className, List<AnnotationElement> elemen
public record AnnotationElementImpl(Utf8Entry name, public record AnnotationElementImpl(Utf8Entry name,
AnnotationValue value) AnnotationValue value)
implements AnnotationElement { implements AnnotationElement {
public AnnotationElementImpl {
requireNonNull(name);
requireNonNull(value);
}
@Override @Override
public String toString() { public String toString() {
return name + "=" + value; return name + "=" + value;

View file

@ -33,6 +33,8 @@ import java.lang.classfile.instruction.LabelTarget;
import java.util.Objects; import java.util.Objects;
import java.lang.classfile.Instruction; import java.lang.classfile.Instruction;
import static java.util.Objects.requireNonNull;
public final class BlockCodeBuilderImpl public final class BlockCodeBuilderImpl
extends NonterminalCodeBuilder extends NonterminalCodeBuilder
implements CodeBuilder.BlockCodeBuilder { implements CodeBuilder.BlockCodeBuilder {
@ -80,7 +82,7 @@ public final class BlockCodeBuilderImpl
@Override @Override
public CodeBuilder with(CodeElement element) { public CodeBuilder with(CodeElement element) {
parent.with(element); parent.with(requireNonNull(element));
hasInstructions |= element instanceof Instruction; hasInstructions |= element instanceof Instruction;

View file

@ -38,6 +38,8 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.function.Consumer; import java.util.function.Consumer;
import static java.util.Objects.requireNonNull;
public final class BufferedCodeBuilder public final class BufferedCodeBuilder
implements TerminalCodeBuilder { implements TerminalCodeBuilder {
private final SplitConstantPool constantPool; private final SplitConstantPool constantPool;
@ -121,7 +123,7 @@ public final class BufferedCodeBuilder
public CodeBuilder with(CodeElement element) { public CodeBuilder with(CodeElement element) {
if (finished) if (finished)
throw new IllegalStateException("Can't add elements after traversal"); throw new IllegalStateException("Can't add elements after traversal");
elements.add(element); elements.add(requireNonNull(element));
return this; return this;
} }

View file

@ -34,6 +34,8 @@ import java.lang.classfile.*;
import java.lang.classfile.constantpool.ConstantPoolBuilder; import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.lang.classfile.constantpool.Utf8Entry; import java.lang.classfile.constantpool.Utf8Entry;
import static java.util.Objects.requireNonNull;
public final class BufferedFieldBuilder public final class BufferedFieldBuilder
implements TerminalFieldBuilder { implements TerminalFieldBuilder {
private final SplitConstantPool constantPool; private final SplitConstantPool constantPool;
@ -49,8 +51,8 @@ public final class BufferedFieldBuilder
Utf8Entry type) { Utf8Entry type) {
this.constantPool = constantPool; this.constantPool = constantPool;
this.context = context; this.context = context;
this.name = name; this.name = requireNonNull(name);
this.desc = type; this.desc = requireNonNull(type);
this.flags = new AccessFlagsImpl(AccessFlag.Location.FIELD); this.flags = new AccessFlagsImpl(AccessFlag.Location.FIELD);
} }
@ -61,7 +63,7 @@ public final class BufferedFieldBuilder
@Override @Override
public FieldBuilder with(FieldElement element) { public FieldBuilder with(FieldElement element) {
elements.add(element); elements.add(requireNonNull(element));
if (element instanceof AccessFlags f) this.flags = f; if (element instanceof AccessFlags f) this.flags = f;
return this; return this;
} }

View file

@ -43,6 +43,8 @@ import java.lang.classfile.MethodElement;
import java.lang.classfile.MethodModel; import java.lang.classfile.MethodModel;
import java.lang.classfile.constantpool.Utf8Entry; import java.lang.classfile.constantpool.Utf8Entry;
import static java.util.Objects.requireNonNull;
public final class BufferedMethodBuilder public final class BufferedMethodBuilder
implements TerminalMethodBuilder { implements TerminalMethodBuilder {
private final List<MethodElement> elements; private final List<MethodElement> elements;
@ -63,15 +65,15 @@ public final class BufferedMethodBuilder
this.elements = new ArrayList<>(); this.elements = new ArrayList<>();
this.constantPool = constantPool; this.constantPool = constantPool;
this.context = context; this.context = context;
this.name = nameInfo; this.name = requireNonNull(nameInfo);
this.desc = typeInfo; this.desc = requireNonNull(typeInfo);
this.flags = new AccessFlagsImpl(AccessFlag.Location.METHOD, flags); this.flags = new AccessFlagsImpl(AccessFlag.Location.METHOD, flags);
this.original = original; this.original = original;
} }
@Override @Override
public MethodBuilder with(MethodElement element) { public MethodBuilder with(MethodElement element) {
elements.add(element); elements.add(requireNonNull(element));
if (element instanceof AccessFlags f) this.flags = checkFlags(f); if (element instanceof AccessFlags f) this.flags = checkFlags(f);
return this; return this;
} }

View file

@ -47,6 +47,7 @@ import java.lang.classfile.constantpool.MethodHandleEntry;
import java.lang.classfile.constantpool.NameAndTypeEntry; import java.lang.classfile.constantpool.NameAndTypeEntry;
import java.util.Objects; import java.util.Objects;
import static java.util.Objects.requireNonNull;
import static jdk.internal.classfile.impl.RawBytecodeHelper.*; import static jdk.internal.classfile.impl.RawBytecodeHelper.*;
/** /**
@ -463,7 +464,7 @@ public class BytecodeHelpers {
if (opcode == Opcode.RET && (slot & ~0xFF) == 0 || if (opcode == Opcode.RET && (slot & ~0xFF) == 0 ||
opcode == Opcode.RET_W && (slot & ~0xFFFF) == 0) opcode == Opcode.RET_W && (slot & ~0xFFFF) == 0)
return; return;
Objects.requireNonNull(opcode); requireNonNull(opcode);
throw slotOutOfBounds(opcode, slot); throw slotOutOfBounds(opcode, slot);
} }
@ -551,7 +552,7 @@ public class BytecodeHelpers {
} if (constantValue instanceof DynamicConstantDesc<?> value) { } if (constantValue instanceof DynamicConstantDesc<?> value) {
return handleConstantDescToHandleInfo(constantPool, value); return handleConstantDescToHandleInfo(constantPool, value);
} }
throw new UnsupportedOperationException("not yet: " + constantValue); throw new UnsupportedOperationException("not yet: " + requireNonNull(constantValue));
} }
public static ConstantDesc intrinsicConstantValue(Opcode opcode) { public static ConstantDesc intrinsicConstantValue(Opcode opcode) {

View file

@ -31,6 +31,8 @@ import java.lang.classfile.*;
import java.lang.classfile.constantpool.ConstantPoolBuilder; import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.lang.classfile.constantpool.Utf8Entry; import java.lang.classfile.constantpool.Utf8Entry;
import static java.util.Objects.requireNonNull;
public final class ChainedClassBuilder public final class ChainedClassBuilder
implements ClassBuilder, Consumer<ClassElement> { implements ClassBuilder, Consumer<ClassElement> {
private final DirectClassBuilder terminal; private final DirectClassBuilder terminal;
@ -47,7 +49,7 @@ public final class ChainedClassBuilder
@Override @Override
public ClassBuilder with(ClassElement element) { public ClassBuilder with(ClassElement element) {
consumer.accept(element); consumer.accept(requireNonNull(element));
return this; return this;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -31,6 +31,8 @@ import java.lang.classfile.Label;
import java.util.function.Consumer; import java.util.function.Consumer;
import static java.util.Objects.requireNonNull;
public final class ChainedCodeBuilder public final class ChainedCodeBuilder
extends NonterminalCodeBuilder extends NonterminalCodeBuilder
implements CodeBuilder { implements CodeBuilder {
@ -59,7 +61,7 @@ public final class ChainedCodeBuilder
@Override @Override
public CodeBuilder with(CodeElement element) { public CodeBuilder with(CodeElement element) {
consumer.accept(element); consumer.accept(requireNonNull(element));
return this; return this;
} }
} }

View file

@ -30,6 +30,8 @@ import java.lang.classfile.FieldBuilder;
import java.lang.classfile.FieldElement; import java.lang.classfile.FieldElement;
import java.lang.classfile.constantpool.ConstantPoolBuilder; import java.lang.classfile.constantpool.ConstantPoolBuilder;
import static java.util.Objects.requireNonNull;
public final class ChainedFieldBuilder implements FieldBuilder { public final class ChainedFieldBuilder implements FieldBuilder {
private final TerminalFieldBuilder terminal; private final TerminalFieldBuilder terminal;
private final Consumer<FieldElement> consumer; private final Consumer<FieldElement> consumer;
@ -50,7 +52,7 @@ public final class ChainedFieldBuilder implements FieldBuilder {
@Override @Override
public FieldBuilder with(FieldElement element) { public FieldBuilder with(FieldElement element) {
consumer.accept(element); consumer.accept(requireNonNull(element));
return this; return this;
} }

View file

@ -33,6 +33,8 @@ import java.lang.classfile.MethodBuilder;
import java.lang.classfile.MethodElement; import java.lang.classfile.MethodElement;
import java.lang.classfile.constantpool.ConstantPoolBuilder; import java.lang.classfile.constantpool.ConstantPoolBuilder;
import static java.util.Objects.requireNonNull;
public final class ChainedMethodBuilder implements MethodBuilder { public final class ChainedMethodBuilder implements MethodBuilder {
final TerminalMethodBuilder terminal; final TerminalMethodBuilder terminal;
final Consumer<MethodElement> consumer; final Consumer<MethodElement> consumer;
@ -48,7 +50,7 @@ public final class ChainedMethodBuilder implements MethodBuilder {
@Override @Override
public MethodBuilder with(MethodElement element) { public MethodBuilder with(MethodElement element) {
consumer.accept(element); consumer.accept(requireNonNull(element));
return this; return this;
} }

View file

@ -40,6 +40,8 @@ import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.lang.classfile.constantpool.Utf8Entry; import java.lang.classfile.constantpool.Utf8Entry;
import jdk.internal.classfile.impl.verifier.VerifierImpl; import jdk.internal.classfile.impl.verifier.VerifierImpl;
import static java.util.Objects.requireNonNull;
public final class ClassFileImpl implements ClassFile { public final class ClassFileImpl implements ClassFile {
private Option stackMapsOption; private Option stackMapsOption;
@ -123,7 +125,7 @@ public final class ClassFileImpl implements ClassFile {
} else if (o instanceof AttributeMapperOption oo) { } else if (o instanceof AttributeMapperOption oo) {
amo = oo; amo = oo;
} else { // null or unknown Option type } else { // null or unknown Option type
throw new IllegalArgumentException("Invalid option: " + o); throw new IllegalArgumentException("Invalid option: " + requireNonNull(o));
} }
} }
return new ClassFileImpl(smo, deo, lno, apo, cpso, sjo, dco, dlo, chro, amo); return new ClassFileImpl(smo, deo, lno, apo, cpso, sjo, dco, dlo, chro, amo);

View file

@ -205,9 +205,9 @@ public final class ClassHierarchyImpl {
map = HashMap.newHashMap(interfaceNames.size() + classToSuperClass.size() + 1); map = HashMap.newHashMap(interfaceNames.size() + classToSuperClass.size() + 1);
map.put(CD_Object, ClassHierarchyInfoImpl.OBJECT_INFO); map.put(CD_Object, ClassHierarchyInfoImpl.OBJECT_INFO);
for (var e : classToSuperClass.entrySet()) for (var e : classToSuperClass.entrySet())
map.put(e.getKey(), ClassHierarchyInfo.ofClass(e.getValue())); map.put(requireNonNull(e.getKey()), ClassHierarchyInfo.ofClass(e.getValue()));
for (var i : interfaceNames) for (var i : interfaceNames)
map.put(i, ClassHierarchyInfo.ofInterface()); map.put(requireNonNull(i), ClassHierarchyInfo.ofInterface());
} }
@Override @Override

View file

@ -61,6 +61,7 @@ import java.lang.classfile.instruction.*;
import java.lang.classfile.CompoundElement; import java.lang.classfile.CompoundElement;
import java.lang.classfile.FieldModel; import java.lang.classfile.FieldModel;
import static java.lang.classfile.constantpool.PoolEntry.*; import static java.lang.classfile.constantpool.PoolEntry.*;
import static java.util.Objects.requireNonNull;
import static jdk.internal.classfile.impl.ClassPrinterImpl.Style.*; import static jdk.internal.classfile.impl.ClassPrinterImpl.Style.*;
public final class ClassPrinterImpl { public final class ClassPrinterImpl {
@ -564,6 +565,7 @@ public final class ClassPrinterImpl {
private record ExceptionHandler(int start, int end, int handler, String catchType) {} private record ExceptionHandler(int start, int end, int handler, String catchType) {}
public static MapNode modelToTree(CompoundElement<?> model, Verbosity verbosity) { public static MapNode modelToTree(CompoundElement<?> model, Verbosity verbosity) {
requireNonNull(verbosity); // we are using == checks in implementations
return switch(model) { return switch(model) {
case ClassModel cm -> classToTree(cm, verbosity); case ClassModel cm -> classToTree(cm, verbosity);
case FieldModel fm -> fieldToTree(fm, verbosity); case FieldModel fm -> fieldToTree(fm, verbosity);

View file

@ -26,11 +26,7 @@
package jdk.internal.classfile.impl; package jdk.internal.classfile.impl;
import java.lang.constant.ClassDesc;
import java.lang.constant.ConstantDescs; import java.lang.constant.ConstantDescs;
import java.lang.constant.MethodTypeDesc;
import java.lang.reflect.AccessFlag;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -50,6 +46,8 @@ import java.lang.classfile.MethodModel;
import java.lang.classfile.MethodTransform; import java.lang.classfile.MethodTransform;
import java.lang.classfile.constantpool.Utf8Entry; import java.lang.classfile.constantpool.Utf8Entry;
import static java.util.Objects.requireNonNull;
public final class DirectClassBuilder public final class DirectClassBuilder
extends AbstractDirectBuilder<ClassModel> extends AbstractDirectBuilder<ClassModel>
implements ClassBuilder { implements ClassBuilder {
@ -87,7 +85,7 @@ public final class DirectClassBuilder
if (element instanceof AbstractElement ae) { if (element instanceof AbstractElement ae) {
ae.writeTo(this); ae.writeTo(this);
} else { } else {
writeAttribute((CustomAttribute<?>) element); writeAttribute((CustomAttribute<?>) requireNonNull(element));
} }
return this; return this;
} }

View file

@ -64,6 +64,7 @@ import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import static java.util.Objects.requireNonNull;
import static jdk.internal.classfile.impl.BytecodeHelpers.*; import static jdk.internal.classfile.impl.BytecodeHelpers.*;
import static jdk.internal.classfile.impl.RawBytecodeHelper.*; import static jdk.internal.classfile.impl.RawBytecodeHelper.*;
@ -147,7 +148,7 @@ public final class DirectCodeBuilder
if (element instanceof AbstractElement ae) { if (element instanceof AbstractElement ae) {
ae.writeTo(this); ae.writeTo(this);
} else { } else {
writeAttribute((CustomAttribute<?>) element); writeAttribute((CustomAttribute<?>) requireNonNull(element));
} }
return this; return this;
} }

View file

@ -33,6 +33,8 @@ import java.lang.classfile.FieldElement;
import java.lang.classfile.FieldModel; import java.lang.classfile.FieldModel;
import java.lang.classfile.constantpool.Utf8Entry; import java.lang.classfile.constantpool.Utf8Entry;
import static java.util.Objects.requireNonNull;
public final class DirectFieldBuilder public final class DirectFieldBuilder
extends AbstractDirectBuilder<FieldModel> extends AbstractDirectBuilder<FieldModel>
implements TerminalFieldBuilder, Util.Writable { implements TerminalFieldBuilder, Util.Writable {
@ -48,8 +50,8 @@ public final class DirectFieldBuilder
FieldModel original) { FieldModel original) {
super(constantPool, context); super(constantPool, context);
setOriginal(original); setOriginal(original);
this.name = name; this.name = requireNonNull(name);
this.desc = type; this.desc = requireNonNull(type);
this.flags = flags; this.flags = flags;
} }
@ -58,7 +60,7 @@ public final class DirectFieldBuilder
if (element instanceof AbstractElement ae) { if (element instanceof AbstractElement ae) {
ae.writeTo(this); ae.writeTo(this);
} else { } else {
writeAttribute((CustomAttribute<?>) element); writeAttribute((CustomAttribute<?>) requireNonNull(element));
} }
return this; return this;
} }

View file

@ -38,6 +38,8 @@ import java.lang.classfile.MethodElement;
import java.lang.classfile.MethodModel; import java.lang.classfile.MethodModel;
import java.lang.classfile.constantpool.Utf8Entry; import java.lang.classfile.constantpool.Utf8Entry;
import static java.util.Objects.requireNonNull;
public final class DirectMethodBuilder public final class DirectMethodBuilder
extends AbstractDirectBuilder<MethodModel> extends AbstractDirectBuilder<MethodModel>
implements TerminalMethodBuilder, Util.Writable { implements TerminalMethodBuilder, Util.Writable {
@ -55,8 +57,8 @@ public final class DirectMethodBuilder
MethodModel original) { MethodModel original) {
super(constantPool, context); super(constantPool, context);
setOriginal(original); setOriginal(original);
this.name = nameInfo; this.name = requireNonNull(nameInfo);
this.desc = typeInfo; this.desc = requireNonNull(typeInfo);
this.flags = flags; this.flags = flags;
} }
@ -114,7 +116,7 @@ public final class DirectMethodBuilder
if (element instanceof AbstractElement ae) { if (element instanceof AbstractElement ae) {
ae.writeTo(this); ae.writeTo(this);
} else { } else {
writeAttribute((CustomAttribute<?>) element); writeAttribute((CustomAttribute<?>) requireNonNull(element));
} }
return this; return this;
} }

View file

@ -38,6 +38,7 @@ import java.lang.classfile.constantpool.*;
import jdk.internal.constant.ConstantUtils; import jdk.internal.constant.ConstantUtils;
import static java.lang.classfile.constantpool.PoolEntry.*; import static java.lang.classfile.constantpool.PoolEntry.*;
import static java.util.Objects.requireNonNull;
public final class SplitConstantPool implements ConstantPoolBuilder { public final class SplitConstantPool implements ConstantPoolBuilder {
@ -122,6 +123,7 @@ public final class SplitConstantPool implements ConstantPoolBuilder {
@Override @Override
public boolean canWriteDirect(ConstantPool other) { public boolean canWriteDirect(ConstantPool other) {
requireNonNull(other);
return this == other || parent == other; return this == other || parent == other;
} }

View file

@ -42,6 +42,7 @@ import java.util.Objects;
import static java.lang.classfile.ClassFile.*; import static java.lang.classfile.ClassFile.*;
import static java.lang.classfile.attribute.StackMapFrameInfo.VerificationTypeInfo.*; import static java.lang.classfile.attribute.StackMapFrameInfo.VerificationTypeInfo.*;
import static java.util.Objects.requireNonNull;
public class StackMapDecoder { public class StackMapDecoder {
@ -245,6 +246,9 @@ public class StackMapDecoder {
public static record ObjectVerificationTypeInfoImpl( public static record ObjectVerificationTypeInfoImpl(
ClassEntry className) implements ObjectVerificationTypeInfo { ClassEntry className) implements ObjectVerificationTypeInfo {
public ObjectVerificationTypeInfoImpl {
requireNonNull(className);
}
@Override @Override
public int tag() { return ITEM_OBJECT; } public int tag() { return ITEM_OBJECT; }
@ -270,6 +274,9 @@ public class StackMapDecoder {
} }
public static record UninitializedVerificationTypeInfoImpl(Label newTarget) implements UninitializedVerificationTypeInfo { public static record UninitializedVerificationTypeInfoImpl(Label newTarget) implements UninitializedVerificationTypeInfo {
public UninitializedVerificationTypeInfoImpl {
requireNonNull(newTarget);
}
@Override @Override
public int tag() { return ITEM_UNINITIALIZED; } public int tag() { return ITEM_UNINITIALIZED; }
@ -292,6 +299,7 @@ public class StackMapDecoder {
List<VerificationTypeInfo> stack) List<VerificationTypeInfo> stack)
implements StackMapFrameInfo { implements StackMapFrameInfo {
public StackMapFrameImpl { public StackMapFrameImpl {
requireNonNull(target);
locals = List.copyOf(locals); locals = List.copyOf(locals);
stack = List.copyOf(stack); stack = List.copyOf(stack);
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,6 @@
package jdk.internal.classfile.impl; package jdk.internal.classfile.impl;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.lang.classfile.Label; import java.lang.classfile.Label;
import java.lang.classfile.TypeAnnotation.*; import java.lang.classfile.TypeAnnotation.*;
@ -37,7 +36,6 @@ public final class TargetInfoImpl {
} }
private static TargetType checkValid(TargetType targetType, int rangeFrom, int rangeTo) { private static TargetType checkValid(TargetType targetType, int rangeFrom, int rangeTo) {
Objects.requireNonNull(targetType);
if (targetType.targetTypeValue() < rangeFrom || targetType.targetTypeValue() > rangeTo) if (targetType.targetTypeValue() < rangeFrom || targetType.targetTypeValue() > rangeTo)
throw new IllegalArgumentException("Wrong target type specified " + targetType); throw new IllegalArgumentException("Wrong target type specified " + targetType);
return targetType; return targetType;

View file

@ -50,6 +50,7 @@ import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.constant.MethodTypeDesc; import java.lang.constant.MethodTypeDesc;
import java.util.List; import java.util.List;
import java.util.Objects;
public final class TemporaryConstantPool implements ConstantPoolBuilder { public final class TemporaryConstantPool implements ConstantPoolBuilder {
@ -187,6 +188,7 @@ public final class TemporaryConstantPool implements ConstantPoolBuilder {
@Override @Override
public boolean canWriteDirect(ConstantPool constantPool) { public boolean canWriteDirect(ConstantPool constantPool) {
Objects.requireNonNull(constantPool);
return false; return false;
} }
} }

View file

@ -92,6 +92,8 @@ import java.lang.classfile.constantpool.Utf8Entry;
import jdk.internal.access.SharedSecrets; import jdk.internal.access.SharedSecrets;
import static java.util.Objects.requireNonNull;
public abstract sealed class UnboundAttribute<T extends Attribute<T>> public abstract sealed class UnboundAttribute<T extends Attribute<T>>
extends AbstractElement extends AbstractElement
implements Attribute<T>, Util.Writable { implements Attribute<T>, Util.Writable {
@ -149,7 +151,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public UnboundConstantValueAttribute(ConstantValueEntry entry) { public UnboundConstantValueAttribute(ConstantValueEntry entry) {
super(Attributes.constantValue()); super(Attributes.constantValue());
this.entry = entry; this.entry = requireNonNull(entry);
} }
@Override @Override
@ -182,7 +184,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public UnboundSignatureAttribute(Utf8Entry signature) { public UnboundSignatureAttribute(Utf8Entry signature) {
super(Attributes.signature()); super(Attributes.signature());
this.signature = signature; this.signature = requireNonNull(signature);
} }
@Override @Override
@ -214,7 +216,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public UnboundAnnotationDefaultAttribute(AnnotationValue annotationDefault) { public UnboundAnnotationDefaultAttribute(AnnotationValue annotationDefault) {
super(Attributes.annotationDefault()); super(Attributes.annotationDefault());
this.annotationDefault = annotationDefault; this.annotationDefault = requireNonNull(annotationDefault);
} }
@Override @Override
@ -229,7 +231,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public UnboundSourceFileAttribute(Utf8Entry sourceFile) { public UnboundSourceFileAttribute(Utf8Entry sourceFile) {
super(Attributes.sourceFile()); super(Attributes.sourceFile());
this.sourceFile = sourceFile; this.sourceFile = requireNonNull(sourceFile);
} }
@Override @Override
@ -294,7 +296,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public UnboundEnclosingMethodAttribute(ClassEntry classEntry, NameAndTypeEntry method) { public UnboundEnclosingMethodAttribute(ClassEntry classEntry, NameAndTypeEntry method) {
super(Attributes.enclosingMethod()); super(Attributes.enclosingMethod());
this.classEntry = classEntry; this.classEntry = requireNonNull(classEntry);
this.method = method; this.method = method;
} }
@ -332,7 +334,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public UnboundModuleTargetAttribute(Utf8Entry moduleTarget) { public UnboundModuleTargetAttribute(Utf8Entry moduleTarget) {
super(Attributes.moduleTarget()); super(Attributes.moduleTarget());
this.moduleTarget = moduleTarget; this.moduleTarget = requireNonNull(moduleTarget);
} }
@Override @Override
@ -348,7 +350,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public UnboundModuleMainClassAttribute(ClassEntry mainClass) { public UnboundModuleMainClassAttribute(ClassEntry mainClass) {
super(Attributes.moduleMainClass()); super(Attributes.moduleMainClass());
this.mainClass = mainClass; this.mainClass = requireNonNull(mainClass);
} }
@Override @Override
@ -365,7 +367,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public UnboundModuleHashesAttribute(Utf8Entry algorithm, List<ModuleHashInfo> hashes) { public UnboundModuleHashesAttribute(Utf8Entry algorithm, List<ModuleHashInfo> hashes) {
super(Attributes.moduleHashes()); super(Attributes.moduleHashes());
this.algorithm = algorithm; this.algorithm = requireNonNull(algorithm);
this.hashes = List.copyOf(hashes); this.hashes = List.copyOf(hashes);
} }
@ -451,7 +453,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public UnboundNestHostAttribute(ClassEntry hostEntry) { public UnboundNestHostAttribute(ClassEntry hostEntry) {
super(Attributes.nestHost()); super(Attributes.nestHost());
this.hostEntry = hostEntry; this.hostEntry = requireNonNull(hostEntry);
} }
@Override @Override
@ -467,7 +469,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public UnboundCompilationIDAttribute(Utf8Entry idEntry) { public UnboundCompilationIDAttribute(Utf8Entry idEntry) {
super(Attributes.compilationId()); super(Attributes.compilationId());
this.idEntry = idEntry; this.idEntry = requireNonNull(idEntry);
} }
@Override @Override
@ -483,7 +485,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public UnboundSourceIDAttribute(Utf8Entry idEntry) { public UnboundSourceIDAttribute(Utf8Entry idEntry) {
super(Attributes.sourceId()); super(Attributes.sourceId());
this.idEntry = idEntry; this.idEntry = requireNonNull(idEntry);
} }
@Override @Override
@ -499,7 +501,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public UnboundSourceDebugExtensionAttribute(byte[] contents) { public UnboundSourceDebugExtensionAttribute(byte[] contents) {
super(Attributes.sourceDebugExtension()); super(Attributes.sourceDebugExtension());
this.contents = contents; this.contents = requireNonNull(contents);
} }
@Override @Override
@ -611,7 +613,13 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
public UnboundRuntimeVisibleParameterAnnotationsAttribute(List<List<Annotation>> elements) { public UnboundRuntimeVisibleParameterAnnotationsAttribute(List<List<Annotation>> elements) {
super(Attributes.runtimeVisibleParameterAnnotations()); super(Attributes.runtimeVisibleParameterAnnotations());
this.elements = List.copyOf(elements); // deep copy
var array = elements.toArray().clone();
for (int i = 0; i < array.length; i++) {
array[i] = List.copyOf((List<?>) array[i]);
}
this.elements = SharedSecrets.getJavaUtilCollectionAccess().listFromTrustedArray(array);
} }
@Override @Override
@ -684,7 +692,13 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
Optional<ClassEntry> outerClass, Optional<ClassEntry> outerClass,
Optional<Utf8Entry> innerName, Optional<Utf8Entry> innerName,
int flagsMask) int flagsMask)
implements InnerClassInfo {} implements InnerClassInfo {
public UnboundInnerClassInfo {
requireNonNull(innerClass);
requireNonNull(outerClass);
requireNonNull(innerName);
}
}
public record UnboundLineNumberInfo(int startPc, int lineNumber) public record UnboundLineNumberInfo(int startPc, int lineNumber)
implements LineNumberInfo { } implements LineNumberInfo { }
@ -693,64 +707,84 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
Utf8Entry name, Utf8Entry name,
Utf8Entry type, Utf8Entry type,
int slot) int slot)
implements LocalVariableInfo { } implements LocalVariableInfo {
public UnboundLocalVariableInfo {
requireNonNull(name);
requireNonNull(type);
}
}
public record UnboundLocalVariableTypeInfo(int startPc, int length, public record UnboundLocalVariableTypeInfo(int startPc, int length,
Utf8Entry name, Utf8Entry name,
Utf8Entry signature, Utf8Entry signature,
int slot) int slot)
implements LocalVariableTypeInfo { } implements LocalVariableTypeInfo {
public UnboundLocalVariableTypeInfo {
requireNonNull(name);
requireNonNull(signature);
}
}
public record UnboundMethodParameterInfo(Optional<Utf8Entry> name, int flagsMask) public record UnboundMethodParameterInfo(Optional<Utf8Entry> name, int flagsMask)
implements MethodParameterInfo {} implements MethodParameterInfo {
public UnboundMethodParameterInfo {
requireNonNull(name);
}
}
public record UnboundModuleExportInfo(PackageEntry exportedPackage, public record UnboundModuleExportInfo(PackageEntry exportedPackage,
int exportsFlagsMask, int exportsFlagsMask,
List<ModuleEntry> exportsTo) List<ModuleEntry> exportsTo)
implements ModuleExportInfo { implements ModuleExportInfo {
public UnboundModuleExportInfo(PackageEntry exportedPackage, int exportsFlagsMask, public UnboundModuleExportInfo {
List<ModuleEntry> exportsTo) { requireNonNull(exportedPackage);
this.exportedPackage = exportedPackage; exportsTo = List.copyOf(exportsTo);
this.exportsFlagsMask = exportsFlagsMask;
this.exportsTo = List.copyOf(exportsTo);
} }
} }
public record UnboundModuleHashInfo(ModuleEntry moduleName, public record UnboundModuleHashInfo(ModuleEntry moduleName,
byte[] hash) implements ModuleHashInfo { } byte[] hash) implements ModuleHashInfo {
public UnboundModuleHashInfo {
requireNonNull(moduleName);
requireNonNull(hash);
}
}
public record UnboundModuleOpenInfo(PackageEntry openedPackage, int opensFlagsMask, public record UnboundModuleOpenInfo(PackageEntry openedPackage, int opensFlagsMask,
List<ModuleEntry> opensTo) List<ModuleEntry> opensTo)
implements ModuleOpenInfo { implements ModuleOpenInfo {
public UnboundModuleOpenInfo(PackageEntry openedPackage, int opensFlagsMask, public UnboundModuleOpenInfo {
List<ModuleEntry> opensTo) { requireNonNull(openedPackage);
this.openedPackage = openedPackage; opensTo = List.copyOf(opensTo);
this.opensFlagsMask = opensFlagsMask;
this.opensTo = List.copyOf(opensTo);
} }
} }
public record UnboundModuleProvideInfo(ClassEntry provides, public record UnboundModuleProvideInfo(ClassEntry provides,
List<ClassEntry> providesWith) List<ClassEntry> providesWith)
implements ModuleProvideInfo { implements ModuleProvideInfo {
public UnboundModuleProvideInfo(ClassEntry provides, List<ClassEntry> providesWith) { public UnboundModuleProvideInfo {
this.provides = provides; requireNonNull(provides);
this.providesWith = List.copyOf(providesWith); providesWith = List.copyOf(providesWith);
} }
} }
public record UnboundModuleRequiresInfo(ModuleEntry requires, int requiresFlagsMask, public record UnboundModuleRequiresInfo(ModuleEntry requires, int requiresFlagsMask,
Optional<Utf8Entry> requiresVersion) Optional<Utf8Entry> requiresVersion)
implements ModuleRequireInfo {} implements ModuleRequireInfo {
public UnboundModuleRequiresInfo {
requireNonNull(requires);
requireNonNull(requiresVersion);
}
}
public record UnboundRecordComponentInfo(Utf8Entry name, public record UnboundRecordComponentInfo(Utf8Entry name,
Utf8Entry descriptor, Utf8Entry descriptor,
List<Attribute<?>> attributes) List<Attribute<?>> attributes)
implements RecordComponentInfo { implements RecordComponentInfo {
public UnboundRecordComponentInfo(Utf8Entry name, Utf8Entry descriptor, List<Attribute<?>> attributes) { public UnboundRecordComponentInfo {
this.name = name; requireNonNull(name);
this.descriptor = descriptor; requireNonNull(descriptor);
this.attributes = List.copyOf(attributes); attributes = List.copyOf(attributes);
} }
} }
@ -759,7 +793,9 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
Annotation annotation) implements TypeAnnotation { Annotation annotation) implements TypeAnnotation {
public UnboundTypeAnnotation { public UnboundTypeAnnotation {
requireNonNull(targetInfo);
targetPath = List.copyOf(targetPath); targetPath = List.copyOf(targetPath);
requireNonNull(annotation);
} }
} }
@ -786,7 +822,7 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
Collection<ModuleProvideInfo> provides) Collection<ModuleProvideInfo> provides)
{ {
super(Attributes.module()); super(Attributes.module());
this.moduleName = moduleName; this.moduleName = requireNonNull(moduleName);
this.moduleFlags = moduleFlags; this.moduleFlags = moduleFlags;
this.moduleVersion = moduleVersion; this.moduleVersion = moduleVersion;
this.requires = List.copyOf(requires); this.requires = List.copyOf(requires);