diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index 520eb3f9e89..fc53a806c4c 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -479,7 +479,7 @@ protected ObjectInputStream() throws IOException, SecurityException { * stream instead of objects. * @throws IOException Any of the usual Input/Output related exceptions. */ - public final @Nullable Object readObject() + public final Object readObject() throws IOException, ClassNotFoundException { return readObject(Object.class); } diff --git a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java index a5f5a3a9f79..135221bcbc7 100644 --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -612,7 +612,7 @@ public AbstractStringBuilder append(@Nullable StringBuffer sb) { /** * @since 1.8 */ - AbstractStringBuilder append(AbstractStringBuilder asb) { + AbstractStringBuilder append(@Nullable AbstractStringBuilder asb) { if (asb == null) { return appendNull(); } @@ -1676,6 +1676,7 @@ void getBytes(byte[] dst, int dstBegin, byte coder) { } /* for readObject() */ + @SuppressWarnings("nullness:assignment.type.incompatible") // This like a false positive to me void initBytes(char[] value, int off, int len) { if (String.COMPACT_STRINGS) { this.value = StringUTF16.compress(value, off, len); diff --git a/src/java.base/share/classes/java/lang/ApplicationShutdownHooks.java b/src/java.base/share/classes/java/lang/ApplicationShutdownHooks.java index 7d8b25aac94..87a7b5636b5 100644 --- a/src/java.base/share/classes/java/lang/ApplicationShutdownHooks.java +++ b/src/java.base/share/classes/java/lang/ApplicationShutdownHooks.java @@ -25,6 +25,7 @@ package java.lang; import org.checkerframework.checker.interning.qual.UsesObjectEquals; +import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.framework.qual.AnnotatedFor; import java.util.*; @@ -40,7 +41,7 @@ @AnnotatedFor({"interning"}) @UsesObjectEquals class ApplicationShutdownHooks { /* The set of registered hooks */ - private static IdentityHashMap hooks; + private static @Nullable IdentityHashMap hooks; static { try { Shutdown.add(1 /* shutdown hook invocation order */, @@ -95,6 +96,7 @@ static synchronized boolean remove(Thread hook) { * to run in. Hooks are run concurrently and this method waits for * them to finish. */ + @SuppressWarnings("nullness:dereference.of.nullable") // AOSEN: hooks is null only if illegal state exception is thrown static void runHooks() { Collection threads; synchronized(ApplicationShutdownHooks.class) { diff --git a/src/java.base/share/classes/java/lang/Boolean.java b/src/java.base/share/classes/java/lang/Boolean.java index d3b6b532b97..d1804a914af 100644 --- a/src/java.base/share/classes/java/lang/Boolean.java +++ b/src/java.base/share/classes/java/lang/Boolean.java @@ -313,7 +313,7 @@ public boolean equals(@Nullable Object obj) { @Pure @StaticallyExecutable @EnsuresNonNullIf(expression="#1", result=true) - public static boolean getBoolean(@Nullable String name) { + public static boolean getBoolean(String name) { boolean result = false; try { result = parseBoolean(System.getProperty(name)); diff --git a/src/java.base/share/classes/java/lang/Character.java b/src/java.base/share/classes/java/lang/Character.java index 37f024e1d59..1d824c30ff5 100644 --- a/src/java.base/share/classes/java/lang/Character.java +++ b/src/java.base/share/classes/java/lang/Character.java @@ -3813,7 +3813,7 @@ private UnicodeBlock(String idName, String... aliases) { 0x100000, // 100000..10FFFF; Supplementary Private Use Area-B }; - private static final UnicodeBlock[] blocks = { + private static final @Nullable UnicodeBlock[] blocks = { BASIC_LATIN, LATIN_1_SUPPLEMENT, LATIN_EXTENDED_A, @@ -11474,7 +11474,7 @@ static int toUpperCaseEx(int codePoint) { */ @SideEffectFree @StaticallyExecutable - static char[] toUpperCaseCharArray(int codePoint) { + static char @Nullable [] toUpperCaseCharArray(int codePoint) { // As of Unicode 6.0, 1:M uppercasings only happen in the BMP. assert isBmpCodePoint(codePoint); return CharacterData.of(codePoint).toUpperCaseCharArray(codePoint); @@ -11542,7 +11542,7 @@ public static char reverseBytes(char ch) { */ @Pure @StaticallyExecutable - public static String getName(int codePoint) { + public static @Nullable String getName(int codePoint) { if (!isValidCodePoint(codePoint)) { throw new IllegalArgumentException( String.format("Not a valid Unicode code point: 0x%X", codePoint)); diff --git a/src/java.base/share/classes/java/lang/CharacterData.java b/src/java.base/share/classes/java/lang/CharacterData.java index 566dbbabe5d..43a5e68b07d 100644 --- a/src/java.base/share/classes/java/lang/CharacterData.java +++ b/src/java.base/share/classes/java/lang/CharacterData.java @@ -26,6 +26,7 @@ package java.lang; import org.checkerframework.checker.interning.qual.UsesObjectEquals; +import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.common.value.qual.IntRange; import org.checkerframework.framework.qual.AnnotatedFor; @@ -55,7 +56,7 @@ int toUpperCaseEx(int ch) { return toUpperCase(ch); } - char[] toUpperCaseCharArray(int ch) { + char @Nullable [] toUpperCaseCharArray(int ch) { return null; } diff --git a/src/java.base/share/classes/java/lang/CharacterName.java b/src/java.base/share/classes/java/lang/CharacterName.java index 007ddf57a33..8009239b61a 100644 --- a/src/java.base/share/classes/java/lang/CharacterName.java +++ b/src/java.base/share/classes/java/lang/CharacterName.java @@ -26,6 +26,7 @@ package java.lang; import org.checkerframework.checker.interning.qual.UsesObjectEquals; +import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.framework.qual.AnnotatedFor; import java.io.DataInputStream; @@ -54,6 +55,7 @@ private CharacterName() { try (@SuppressWarnings("removal") DataInputStream dis = new DataInputStream(new InflaterInputStream( AccessController.doPrivileged(new PrivilegedAction<>() { + @SuppressWarnings("nullness:return.type.incompatible") public InputStream run() { return getClass().getResourceAsStream("uniName.dat"); } @@ -144,7 +146,7 @@ public static CharacterName getInstance() { return cname; } - public String getName(int cp) { + public @Nullable String getName(int cp) { int off = 0; int bk = bkIndices[cp >> 8]; if (bk == -1 || (off = lookup[(bk << 8) + (cp & 0xff)]) == 0) diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index dbb50a98bb3..eff3ecfc71b 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -302,6 +302,7 @@ public String toString(@GuardSatisfied Class this) { * * @since 1.8 */ + @SuppressWarnings("nullness:dereference.of.nullable") // False positive public String toGenericString() { if (isPrimitive()) { return toString(); @@ -403,7 +404,7 @@ static String typeVarBounds(TypeVariable typeVar) { */ @ForName @CallerSensitive - public static Class forName(@ClassGetName String className) + public static Class forName(@ClassGetName String className) throws ClassNotFoundException { Class caller = Reflection.getCallerClass(); return forName0(className, true, ClassLoader.getClassLoader(caller), caller); @@ -479,7 +480,7 @@ public static Class forName(@ClassGetName String className) * @since 1.2 */ @CallerSensitive - public static Class forName(@ClassGetName String name, boolean initialize, + public static Class forName(@ClassGetName String name, boolean initialize, @Nullable ClassLoader loader) throws ClassNotFoundException { @@ -503,8 +504,8 @@ public static Class forName(@ClassGetName String name, boolean /** Called after security check for system loader access checks have been made. */ private static native Class forName0(String name, boolean initialize, - ClassLoader loader, - Class caller) + @Nullable ClassLoader loader, + @Nullable Class caller) throws ClassNotFoundException; @@ -556,7 +557,7 @@ private static native Class forName0(String name, boolean initialize, */ @SuppressWarnings("removal") @CallerSensitive - public static Class forName(Module module, String name) { + public static @Nullable Class forName(Module module, String name) { Objects.requireNonNull(module); Objects.requireNonNull(name); @@ -569,7 +570,7 @@ public static Class forName(Module module, String name) { // java.base has all permissions sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); } - PrivilegedAction pa = module::getClassLoader; + PrivilegedAction<@Nullable ClassLoader> pa = module::getClassLoader; cl = AccessController.doPrivileged(pa); } else { cl = module.getClassLoader(); @@ -635,7 +636,7 @@ public static Class forName(Module module, String name) { * s.checkPackageAccess()} denies access to the package * of this class. */ - @SuppressWarnings("removal") + @SuppressWarnings({"removal","nullness:return.type.incompatible"}) @CallerSensitive @Deprecated(since="9") public @NonNull T newInstance() @@ -662,7 +663,7 @@ public static Class forName(Module module, String name) { // access check is done with the true caller java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<>() { - public Void run() { + public @NonNull Void run() { c.setAccessible(true); return null; } @@ -676,7 +677,7 @@ public Void run() { try { Class caller = Reflection.getCallerClass(); - return getReflectionFactory().newInstance(tmpConstructor, null, caller); + return getReflectionFactory().3(tmpConstructor, null, caller); } catch (InvocationTargetException e) { Unsafe.getUnsafe().throwException(e.getTargetException()); // Not reached @@ -719,6 +720,7 @@ public Void run() { @Pure @EnsuresNonNullIf(expression={"#1"}, result=true) @IntrinsicCandidate + @SuppressWarnings("flowexpr.parameter.not.final") // AOSEN: I don't understand this warning public native boolean isInstance(@GuardSatisfied Class this, @Nullable Object obj); @@ -1120,6 +1122,7 @@ public TypeVariable>[] getTypeParameters() { * @since 9 * @jls 6.7 Fully Qualified Names */ + @SuppressWarnings("nullness:dereference.of.nullable") // c is not null if isArray() is true public @DotSeparatedIdentifiers String getPackageName() { String pn = this.packageName; if (pn == null) { @@ -1184,7 +1187,7 @@ public TypeVariable>[] getTypeParameters() { * @return an array of interfaces directly implemented by this class */ @SideEffectFree - public Class[] getInterfaces(@GuardSatisfied Class this) { + public Class[] getInterfaces(@GuardSatisfied Class this) { // defensively copy before handing over to user code return getInterfaces(true); } @@ -1272,7 +1275,7 @@ public Type[] getGenericInterfaces() { * @since 1.1 */ @Pure - public @Nullable Class getComponentType(@GuardSatisfied Class this) { + public @Nullable Class getComponentType(@GuardSatisfied Class this) { // Only return for array types. Storage may be reused for Class for instance types. if (isArray()) { return componentType; @@ -1288,7 +1291,7 @@ public Type[] getGenericInterfaces() { * If this class does not represent an array class, then this method returns * {@code null}. */ - private Class elementType() { + private @Nullable Class elementType() { if (!isArray()) return null; Class c = this; @@ -1444,7 +1447,7 @@ private Class elementType() { private native Object[] getEnclosingMethod0(); - private EnclosingMethodInfo getEnclosingMethodInfo() { + private @Nullable EnclosingMethodInfo getEnclosingMethodInfo() { Object[] enclosingInfo = getEnclosingMethod0(); if (enclosingInfo == null) return null; @@ -1547,7 +1550,7 @@ private static Class toClass(Type o) { * @since 1.5 */ @CallerSensitive - public @Nullable Constructor getEnclosingConstructor() throws SecurityException { + public @Nullable Constructor getEnclosingConstructor() throws SecurityException { EnclosingMethodInfo enclosingInfo = getEnclosingMethodInfo(); if (enclosingInfo == null) @@ -1613,7 +1616,7 @@ private static Class toClass(Type o) { * @since 1.1 */ @CallerSensitive - public @Nullable Class getDeclaringClass() throws SecurityException { + public @Nullable Class getDeclaringClass() throws SecurityException { final Class candidate = getDeclaringClass0(); if (candidate != null) { @@ -1645,7 +1648,7 @@ private static Class toClass(Type o) { */ @Pure @CallerSensitive - public @Nullable Class getEnclosingClass() throws SecurityException { + public @Nullable Class getEnclosingClass() throws SecurityException { // There are five kinds of classes (or interfaces): // a) Top level classes // b) Nested classes (static member classes) @@ -1725,6 +1728,7 @@ private String getSimpleName0() { * @return an informative string for the name of this class or interface * @since 1.8 */ + @SuppressWarnings("nullness:dereference.of.nullable") // cl is not null if isArray() is true public String getTypeName() { if (isArray()) { try { @@ -1842,7 +1846,7 @@ public boolean isMemberClass(@GuardSatisfied Class this) { * Returns {@code null} if the underlying class is a top level * class. */ - private String getSimpleBinaryName() { + private @Nullable String getSimpleBinaryName() { if (isTopLevelClass()) return null; String name = getSimpleBinaryName0(); @@ -1904,8 +1908,8 @@ private boolean hasEnclosingMethodInfo() { * * @since 1.1 */ - @SuppressWarnings("removal") @CallerSensitive + @SuppressWarnings({"removal", "nullness:override.return.invalid"}) public Class[] getClasses() { SecurityManager sm = System.getSecurityManager(); if (sm != null) { @@ -2107,7 +2111,7 @@ public Method[] getMethods() throws SecurityException { * @since 1.1 */ @CallerSensitive - public Constructor[] getConstructors() throws SecurityException { + public Constructor[] getConstructors() throws SecurityException { @SuppressWarnings("removal") SecurityManager sm = System.getSecurityManager(); if (sm != null) { @@ -2369,7 +2373,7 @@ public Constructor getConstructor(Class... parameterTypes) * @jls 8.5 Member Type Declarations */ @CallerSensitive - public Class[] getDeclaredClasses() throws SecurityException { + public Class[] getDeclaredClasses() throws SecurityException { @SuppressWarnings("removal") SecurityManager sm = System.getSecurityManager(); if (sm != null) { @@ -2484,7 +2488,7 @@ public Field[] getDeclaredFields() throws SecurityException { * @since 16 */ @CallerSensitive - public RecordComponent[] getRecordComponents() { + public RecordComponent @Nullable [] getRecordComponents() { @SuppressWarnings("removal") SecurityManager sm = System.getSecurityManager(); if (sm != null) { @@ -3007,6 +3011,10 @@ public Constructor getDeclaredConstructor(Class... parameterTypes) * the module. For other callers, then the package needs to be open to * the caller. */ + @SuppressWarnings({"nullness:argument.type.incompatible", "nullness:dereference.of.nullable"}) + // This code is updated in the latest JDK for the first warning + // https://github.com/openjdk/jdk/blob/4a4209ffef8f8d65054cbf46ebf8e169d100c0d8/src/java.base/share/classes/java/lang/Class.java#L2689-L2696 + // The second warning is a false positive because this method is only called by when guarded with getModule().isNamed() private boolean isOpenToCaller(String name, Class caller) { // assert getModule().isNamed(); Module thisModule = getModule(); @@ -3122,7 +3130,7 @@ private void checkMemberAccess(@SuppressWarnings("removal") SecurityManager sm, * * NOTE: this method should only be called if a SecurityManager is active */ - private void checkPackageAccess(@SuppressWarnings("removal") SecurityManager sm, final ClassLoader ccl, + private void checkPackageAccess(@SuppressWarnings("removal") SecurityManager sm, final @Nullable ClassLoader ccl, boolean checkProxyInterfaces) { final ClassLoader cl = getClassLoader0(); @@ -3152,7 +3160,7 @@ private void checkPackageAccess(@SuppressWarnings("removal") SecurityManager sm, * NOTE: this method does not support Proxy classes */ private static void checkPackageAccessForPermittedSubclasses(@SuppressWarnings("removal") SecurityManager sm, - final ClassLoader ccl, Class[] subClasses) { + final @Nullable ClassLoader ccl, Class[] subClasses) { final ClassLoader cl = subClasses[0].getClassLoader0(); if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) { @@ -3315,7 +3323,7 @@ private GenericsFactory getFactory() { // accessor for generic info repository; // generic info is lazily initialized - private ClassRepository getGenericInfo() { + private @Nullable ClassRepository getGenericInfo() { ClassRepository genericInfo = this.genericInfo; if (genericInfo == null) { String signature = getGenericSignature0(); @@ -3519,7 +3527,7 @@ private Method[] privateGetPublicMethods() { // // This method does not copy the returned Field object! - private static Field searchFields(Field[] fields, String name) { + private static @Nullable Field searchFields(Field[] fields, String name) { for (Field field : fields) { if (field.getName().equals(name)) { return field; @@ -3531,7 +3539,7 @@ private static Field searchFields(Field[] fields, String name) { // Returns a "root" Field object. This Field object must NOT // be propagated to the outside world, but must instead be copied // via ReflectionFactory.copyField. - private Field getField0(String name) { + private @Nullable Field getField0(String name) { // Note: the intent is that the search algorithm this routine // uses be equivalent to the ordering imposed by // privateGetPublicFields(). It fetches only the declared @@ -3564,7 +3572,7 @@ private Field getField0(String name) { } // This method does not copy the returned Method object! - private static Method searchMethods(Method[] methods, + private static @Nullable Method searchMethods(Method[] methods, String name, Class[] parameterTypes) { @@ -3587,7 +3595,7 @@ && arrayContentsEq(parameterTypes, // Returns a "root" Method object. This Method object must NOT // be propagated to the outside world, but must instead be copied // via ReflectionFactory.copyMethod. - private Method getMethod0(String name, Class[] parameterTypes) { + private @Nullable Method getMethod0(String name, Class @Nullable [] parameterTypes) { PublicMethods.MethodList res = getMethodsRecursive( name, parameterTypes == null ? EMPTY_CLASS_ARRAY : parameterTypes, @@ -3598,7 +3606,7 @@ private Method getMethod0(String name, Class[] parameterTypes) { // Returns a list of "root" Method objects. These Method objects must NOT // be propagated to the outside world, but must instead be copied // via ReflectionFactory.copyMethod. - private PublicMethods.MethodList getMethodsRecursive(String name, + private PublicMethods.@Nullable MethodList getMethodsRecursive(String name, Class[] parameterTypes, boolean includeStatic) { // 1st check declared public methods @@ -3718,7 +3726,7 @@ private static Constructor[] copyConstructors(Constructor[] arg) { /** * Helper method to get the method name from arguments. */ - private String methodToString(String name, Class[] argTypes) { + private String methodToString(String name, Class @Nullable [] argTypes) { return getName() + '.' + name + ((argTypes == null || argTypes.length == 0) ? "()" : @@ -3778,6 +3786,7 @@ private String methodToString(String name, Class[] argTypes) { * @see java.lang.ClassLoader#setDefaultAssertionStatus * @since 1.4 */ + @SuppressWarnings("contracts.precondition.not.satisfied") public boolean desiredAssertionStatus() { ClassLoader loader = getClassLoader0(); // If the loader is null this is a system class, so ask the VM @@ -3872,7 +3881,7 @@ private static ReflectionFactory getReflectionFactory() { * @since 1.5 * @jls 8.9.1 Enum Constants */ - public @NonNull T @Nullable [] getEnumConstants() { + public T @Nullable [] getEnumConstants() { T[] values = getEnumConstantsShared(); return (values != null) ? values.clone() : null; } @@ -3884,14 +3893,14 @@ private static ReflectionFactory getReflectionFactory() { * uncloned, cached, and shared by all callers. */ @SuppressWarnings("removal") - T[] getEnumConstantsShared() { + T @Nullable [] getEnumConstantsShared() { T[] constants = enumConstants; if (constants == null) { if (!isEnum()) return null; try { final Method values = getMethod("values"); java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<>() { + new java.security.PrivilegedAction<@Nullable Void>() { public Void run() { values.setAccessible(true); return null; @@ -3908,7 +3917,7 @@ public Void run() { } return constants; } - private transient volatile T[] enumConstants; + private transient volatile T @Nullable [] enumConstants; /** * Returns a map from simple name to enum constant. This package-private @@ -3917,7 +3926,8 @@ public Void run() { * efficiently. Note that the map is returned by this method is * created lazily on first use. Typically it won't ever get created. */ - Map enumConstantDirectory() { + @SuppressWarnings("nullness:dereference.of.nullable") // Should we require T to extend @NonNull? + Map enumConstantDirectory() { Map directory = enumConstantDirectory; if (directory == null) { T[] universe = getEnumConstantsShared(); @@ -3951,7 +3961,7 @@ public Void run() { public @PolyNull @Signed T cast(@PolyNull Object obj) { if (obj != null && !isInstance(obj)) throw new ClassCastException(cannotCastMsg(obj)); - return (T) obj; + return (@PolyNull T) obj; } private String cannotCastMsg(Object obj) { @@ -3998,7 +4008,7 @@ public Class asSubclass(Class clazz) { */ @Override @SuppressWarnings("unchecked") - public @Nullable A getAnnotation(Class annotationClass) { + public @Nullable A getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); return (A) annotationData().annotations.get(annotationClass); @@ -4024,7 +4034,7 @@ public boolean isAnnotationPresent(@GuardSatisfied Class this, @GuardSatisfie * @since 1.8 */ @Override - public A[] getAnnotationsByType(Class annotationClass) { + public A[] getAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); AnnotationData annotationData = annotationData(); @@ -4055,7 +4065,7 @@ public Annotation[] getAnnotations() { */ @Override @SuppressWarnings("unchecked") - public @Nullable A getDeclaredAnnotation(Class annotationClass) { + public @Nullable A getDeclaredAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); return (A) annotationData().declaredAnnotations.get(annotationClass); @@ -4070,7 +4080,7 @@ public Annotation[] getAnnotations() { * @since 1.8 */ @Override - public A[] getDeclaredAnnotationsByType(Class annotationClass) { + public A[] getDeclaredAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); return AnnotationSupport.getDirectlyAndIndirectlyPresent(annotationData().declaredAnnotations, @@ -4091,14 +4101,14 @@ public Annotation[] getDeclaredAnnotations() { // annotation data that might get invalidated when JVM TI RedefineClasses() is called private static class AnnotationData { - final Map, Annotation> annotations; - final Map, Annotation> declaredAnnotations; + final Map, Annotation> annotations; + final Map, Annotation> declaredAnnotations; // Value of classRedefinedCount when we created this AnnotationData instance final int redefinedCount; - AnnotationData(Map, Annotation> annotations, - Map, Annotation> declaredAnnotations, + AnnotationData(Map, Annotation> annotations, + Map, Annotation> declaredAnnotations, int redefinedCount) { this.annotations = annotations; this.declaredAnnotations = declaredAnnotations; @@ -4129,15 +4139,15 @@ private AnnotationData annotationData() { } private AnnotationData createAnnotationData(int classRedefinedCount) { - Map, Annotation> declaredAnnotations = + Map, Annotation> declaredAnnotations = AnnotationParser.parseAnnotations(getRawAnnotations(), getConstantPool(), this); Class superClass = getSuperclass(); - Map, Annotation> annotations = null; + Map, Annotation> annotations = null; if (superClass != null) { - Map, Annotation> superAnnotations = + Map, Annotation> superAnnotations = superClass.annotationData().annotations; - for (Map.Entry, Annotation> e : superAnnotations.entrySet()) { - Class annotationClass = e.getKey(); + for (Map.Entry, Annotation> e : superAnnotations.entrySet()) { + Class annotationClass = e.getKey(); if (AnnotationType.getInstance(annotationClass).isInherited()) { if (annotations == null) { // lazy construction annotations = new LinkedHashMap<>((Math.max( @@ -4173,7 +4183,7 @@ AnnotationType getAnnotationType() { return annotationType; } - Map, Annotation> getDeclaredAnnotationMap() { + Map, Annotation> getDeclaredAnnotationMap() { return annotationData().declaredAnnotations; } @@ -4201,7 +4211,7 @@ Map, Annotation> getDeclaredAnnotationMap() { * @return an object representing the superclass * @since 1.8 */ - public AnnotatedType getAnnotatedSuperclass() { + public @Nullable AnnotatedType getAnnotatedSuperclass() { if (this == Object.class || isInterface() || isArray() || @@ -4285,7 +4295,7 @@ public AnnotatedType[] getAnnotatedInterfaces() { * @jvms 5.4.4 Access Control */ @CallerSensitive - public Class getNestHost() { + public Class getNestHost() { if (isPrimitive() || isArray()) { return this; } @@ -4377,7 +4387,7 @@ public boolean isNestmateOf(Class c) { * @jvms 4.7.29 The {@code NestMembers} Attribute */ @CallerSensitive - public Class[] getNestMembers() { + public Class[] getNestMembers() { if (isPrimitive() || isArray()) { return new Class[] { this }; } @@ -4494,7 +4504,7 @@ public String descriptorString() { */ @Override @Pure - public @Nullable Class componentType() { + public @Nullable Class componentType() { return isArray() ? componentType : null; } @@ -4520,6 +4530,7 @@ public Class arrayType() { * @since 12 */ @Override + @SuppressWarnings("nullness:dereference.of.nullable") // False positive, c is only null if isArray() is false public Optional describeConstable() { Class c = isArray() ? elementType() : this; return c.isHidden() ? Optional.empty() @@ -4575,7 +4586,7 @@ public Optional describeConstable() { * @since 17 */ @CallerSensitive - public Class[] getPermittedSubclasses() { + public Class @Nullable [] getPermittedSubclasses() { Class[] subClasses; if (isArray() || isPrimitive() || (subClasses = getPermittedSubclasses0()) == null) { return null; diff --git a/src/java.base/share/classes/java/lang/ClassLoader.java b/src/java.base/share/classes/java/lang/ClassLoader.java index 5e197dfa8e1..481de8af507 100644 --- a/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/src/java.base/share/classes/java/lang/ClassLoader.java @@ -30,6 +30,7 @@ import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.checker.nonempty.qual.NonEmpty; import org.checkerframework.checker.nullness.qual.EnsuresNonNull; +import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.RequiresNonNull; import org.checkerframework.checker.signature.qual.BinaryName; @@ -254,7 +255,7 @@ private final @Nullable ClassLoader parent; // class loader name - private final String name; + private final @Nullable String name; // the unnamed module for this ClassLoader private final Module unnamedModule; @@ -280,6 +281,7 @@ private ParallelLoaders() {} * Returns {@code true} is successfully registered; {@code false} if * loader's super class is not registered. */ + @SuppressWarnings("nullness:argument.type.incompatible") // False positive because set interface is used. static boolean register(Class c) { synchronized (loaderTypes) { if (loaderTypes.contains(c.getSuperclass())) { @@ -373,7 +375,7 @@ private NamedPackage getNamedPackage(String pn, Module m) { return checkCreateClassLoader(null); } - private static Void checkCreateClassLoader(String name) { + private static Void checkCreateClassLoader(@Nullable String name) { if (name != null && name.isEmpty()) { throw new IllegalArgumentException("name must be non-empty or null"); } @@ -386,7 +388,7 @@ private static Void checkCreateClassLoader(String name) { return null; } - private ClassLoader(Void unused, String name, ClassLoader parent) { + private ClassLoader(Void unused, @Nullable String name, @Nullable ClassLoader parent) { this.name = name; this.parent = parent; this.unnamedModule = new Module(this); @@ -507,7 +509,7 @@ protected ClassLoader() { // package-private used by StackTraceElement to avoid // calling the overrideable getName method - final String name() { + final @Nullable String name() { return name; } @@ -640,7 +642,7 @@ protected Class loadClass(@BinaryName String name, boolean resolve) * this class loader, or {@code null} if the class could not be found. */ @ForName - final Class loadClass(Module module, @BinaryName String name) { + final @Nullable Class loadClass(Module module, @BinaryName String name) { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class c = findLoadedClass(name); @@ -701,7 +703,7 @@ private void checkPackageAccess(Class cls, ProtectionDomain pd) { final String packageName = cls.getPackageName(); if (!packageName.isEmpty()) { - AccessController.doPrivileged(new PrivilegedAction<>() { + AccessController.doPrivileged(new PrivilegedAction<@Nullable Void>() { public Void run() { sm.checkPackageAccess(packageName); return null; @@ -759,7 +761,7 @@ protected Class findClass(@BinaryName String name) throws ClassNotFoundExcept * * @since 9 */ - protected Class findClass(String moduleName, String name) { + protected @Nullable Class findClass(@Nullable String moduleName, String name) { if (moduleName == null) { try { return findClass(name); @@ -1122,12 +1124,12 @@ protected final Class defineClass(@Nullable @BinaryName String name, java.nio return c; } - static native Class defineClass1(ClassLoader loader, @BinaryName String name, byte[] b, int off, int len, - ProtectionDomain pd, String source); + static native Class defineClass1(ClassLoader loader, @BinaryName @Nullable String name, byte[] b, int off, int len, + @Nullable ProtectionDomain pd, @Nullable String source); - static native Class defineClass2(ClassLoader loader, @BinaryName String name, java.nio.ByteBuffer b, - int off, int len, ProtectionDomain pd, - String source); + static native Class defineClass2(ClassLoader loader, @BinaryName @Nullable String name, java.nio.ByteBuffer b, + int off, int len, @Nullable ProtectionDomain pd, + @Nullable String source); /** * Defines a class of the given flags via Lookup.defineClass. @@ -1182,7 +1184,7 @@ private void checkCerts(String name, @Nullable CodeSource cs) { * check to make sure the certs for the new class (certs) are the same as * the certs for the first class inserted in the package (pcerts) */ - private boolean compareCerts(Certificate[] pcerts, Certificate @Nullable [] certs) { + private boolean compareCerts(Certificate[] pcerts, Certificate[] certs) { // empty array fast-path if (certs.length == 0) return pcerts.length == 0; @@ -1357,7 +1359,7 @@ protected final void setSigners(Class c, Object[] signers) { * @see java.lang.module.ModuleReader#find(String) * @since 9 */ - protected URL findResource(String moduleName, String name) throws IOException { + protected @Nullable URL findResource(@Nullable String moduleName, String name) throws IOException { if (moduleName == null) { return findResource(name); } else { @@ -1977,6 +1979,7 @@ static ClassLoader getBuiltinAppClassLoader() { * * @see java.lang.System#initPhase3 */ + @SuppressWarnings("nullness:dereference.of.nullable") // AOSEN: I think this is a real possible NPE. static synchronized ClassLoader initSystemClassLoader() { if (VM.initLevel() != 3) { throw new InternalError("system class loader cannot be set at initLevel " + @@ -2088,7 +2091,7 @@ static void checkClassLoaderPermission(ClassLoader cl, Class caller) { * * This method does not throw IllegalArgumentException. */ - Package definePackage(Class c) { + @Nullable Package definePackage(Class c) { if (c.isPrimitive() || c.isArray()) { return null; } @@ -2120,7 +2123,7 @@ Package definePackage(String name, Module m) { /* * Returns a Package object for the named package */ - private Package toPackage(String name, NamedPackage p, Module m) { + private Package toPackage(String name, @Nullable NamedPackage p, Module m) { // define Package object if the named package is not yet defined if (p == null) return NamedPackage.toPackage(name, m); @@ -2245,7 +2248,7 @@ protected Package definePackage(@FullyQualifiedName String name, @Nullable Strin * * @since 9 */ - public final Package getDefinedPackage(String name) { + public final @Nullable Package getDefinedPackage(String name) { Objects.requireNonNull(name, "name cannot be null"); NamedPackage p = packages.get(name); @@ -2477,14 +2480,14 @@ static long findNative(@Nullable ClassLoader loader, String entryName) { // none of this ClassLoader's assertion status modification methods have // been invoked. // @GuardedBy("assertionLock") - private @Nullable Map<@Nullable String, Boolean> packageAssertionStatus = null; + private @MonotonicNonNull Map<@Nullable String, Boolean> packageAssertionStatus = null; // Maps String fullyQualifiedClassName to Boolean assertionStatus If this // field is null then we are delegating assertion status queries to the VM, // i.e., none of this ClassLoader's assertion status modification methods // have been invoked. // @GuardedBy("assertionLock") - @Nullable Map classAssertionStatus = null; + @MonotonicNonNull Map classAssertionStatus = null; /** * Sets the default assertion status for this class loader. This setting @@ -2632,6 +2635,7 @@ public void clearAssertionStatus() { * @since 1.4 */ @RequiresNonNull({"classAssertionStatus", "packageAssertionStatus"}) + @SuppressWarnings("nullness:argument.type.incompatible") // False positive because map interface is used. boolean desiredAssertionStatus(String className) { synchronized (assertionLock) { // assert classAssertionStatus != null; @@ -2726,6 +2730,9 @@ private boolean trySetObjectField(String name, Object obj) { /** * Called by the VM, during -Xshare:dump */ + @SuppressWarnings({"nullness:assignment.type.incompatible","nullness:dereference.of.nullable"}) + // classLoaderValueMap is null only when reset + // AOSEN: parallelLockMap.clear(); is this a real NPE? private void resetArchivedStates() { parallelLockMap.clear(); packages.clear(); diff --git a/src/java.base/share/classes/java/lang/ClassNotFoundException.java b/src/java.base/share/classes/java/lang/ClassNotFoundException.java index 6c719b216cd..0ca108ce7a1 100644 --- a/src/java.base/share/classes/java/lang/ClassNotFoundException.java +++ b/src/java.base/share/classes/java/lang/ClassNotFoundException.java @@ -104,7 +104,7 @@ public ClassNotFoundException(@Nullable String s, @Nullable Throwable ex) { * @return the {@code Exception} that was raised while loading a class * @since 1.2 */ - public Throwable getException() { + public @Nullable Throwable getException() { return super.getCause(); } diff --git a/src/java.base/share/classes/java/lang/ClassValue.java b/src/java.base/share/classes/java/lang/ClassValue.java index c92e4f4749f..d7181c3ab03 100644 --- a/src/java.base/share/classes/java/lang/ClassValue.java +++ b/src/java.base/share/classes/java/lang/ClassValue.java @@ -26,6 +26,8 @@ package java.lang; import org.checkerframework.checker.interning.qual.UsesObjectEquals; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.checker.nullness.qual.PolyNull; import org.checkerframework.framework.qual.AnnotatedFor; import java.util.WeakHashMap; @@ -101,9 +103,10 @@ protected ClassValue() { * @see #remove * @see #computeValue */ + @SuppressWarnings("nullness:dereference.of.nullable") // Could the entry be null? public T get(Class type) { // non-racing this.hashCodeForCache : final int - Entry[] cache; + @Nullable Entry[] cache; Entry e = probeHomeLocation(cache = getCacheCarefully(type), this); // racing e : current value <=> stale value from current cache or from stale cache // invariant: e is null or an Entry with readable Entry.version and Entry.value @@ -189,7 +192,7 @@ public void remove(Class type) { /// -------- /** Return the cache, if it exists, else a dummy empty cache. */ - private static Entry[] getCacheCarefully(Class type) { + private static @Nullable Entry[] getCacheCarefully(Class type) { // racing type.classValueMap{.cacheArray} : null => new Entry[X] <=> new Entry[Y] ClassValueMap map = type.classValueMap; if (map == null) return EMPTY_CACHE; @@ -199,7 +202,7 @@ private static Entry[] getCacheCarefully(Class type) { } /** Initial, one-element, empty cache used by all Class instances. Must never be filled. */ - private static final Entry[] EMPTY_CACHE = { null }; + private static final @Nullable Entry[] EMPTY_CACHE = { null }; /** * Slow tail of ClassValue.get to retry at nearby locations in the cache, @@ -207,7 +210,7 @@ private static Entry[] getCacheCarefully(Class type) { * Called only if the first probe was empty or a collision. * This is a separate method, so compilers can process it independently. */ - private T getFromBackup(Entry[] cache, Class type) { + private T getFromBackup(@Nullable Entry[] cache, Class type) { Entry e = probeBackupLocations(cache, this); if (e != null) return e.value(); @@ -216,7 +219,7 @@ private T getFromBackup(Entry[] cache, Class type) { // Hack to suppress warnings on the (T) cast, which is a no-op. @SuppressWarnings("unchecked") - Entry castEntry(Entry e) { return (Entry) e; } + @PolyNull Entry castEntry(@PolyNull Entry e) { return (Entry) e; } /** Called when the fast path of get fails, and cache reprobe also fails. */ @@ -242,7 +245,7 @@ private T getFromHashMap(Class type) { } /** Check that e is non-null, matches this ClassValue, and is live. */ - boolean match(Entry e) { + boolean match(@Nullable Entry e) { // racing e.version : null (blank) => unique Version token => null (GC-ed version) // non-racing this.version : v1 => v2 => ... (updates are read faithfully from volatile) return (e != null && e.get() == this.version); @@ -326,8 +329,8 @@ static class Version { * into the dead state. */ static class Entry extends WeakReference> { - final Object value; // usually of type T, but sometimes (Entry)this - Entry(Version version, T value) { + final @Nullable Object value; // usually of type T, but sometimes (Entry)this + Entry(@Nullable Version version, T value) { super(version); this.value = value; // for a regular entry, value is of type T } @@ -341,8 +344,8 @@ static class Entry extends WeakReference> { @SuppressWarnings("unchecked") // if !isPromise, type is T T value() { assertNotPromise(); return (T) value; } boolean isPromise() { return value == this; } - Version version() { return get(); } - ClassValue classValueOrNull() { + @Nullable Version version() { return get(); } + @Nullable ClassValue classValueOrNull() { Version v = version(); return (v == null) ? null : v.classValue(); } @@ -395,7 +398,7 @@ private static ClassValueMap initializeMap(Class type) { return map; } - static Entry makeEntry(Version explicitVersion, T value) { + static Entry makeEntry(@Nullable Version explicitVersion, T value) { // Note that explicitVersion might be different from this.version. return new Entry<>(explicitVersion, value); @@ -474,7 +477,7 @@ Entry startEntry(ClassValue classValue) { /** Finish a query. Overwrite a matching placeholder. Drop stale incoming values. */ synchronized - Entry finishEntry(ClassValue classValue, Entry e) { + @Nullable Entry finishEntry(ClassValue classValue, Entry e) { @SuppressWarnings("unchecked") // one map has entries for all value types Entry e0 = (Entry) get(classValue.identity); if (e == e0) { @@ -545,7 +548,7 @@ void changeEntry(ClassValue classValue, T value) { // Statics do not need synchronization. /** Load the cache entry at the given (hashed) location. */ - static Entry loadFromCache(Entry[] cache, int i) { + static @Nullable Entry loadFromCache(@Nullable Entry[] cache, int i) { // non-racing cache.length : constant // racing cache[i & (mask)] : null <=> Entry return cache[i & (cache.length-1)]; @@ -553,12 +556,12 @@ static Entry loadFromCache(Entry[] cache, int i) { } /** Look in the cache, at the home location for the given ClassValue. */ - static Entry probeHomeLocation(Entry[] cache, ClassValue classValue) { + static @Nullable Entry probeHomeLocation(@Nullable Entry[] cache, ClassValue classValue) { return classValue.castEntry(loadFromCache(cache, classValue.hashCodeForCache)); } /** Given that first probe was a collision, retry at nearby locations. */ - static Entry probeBackupLocations(Entry[] cache, ClassValue classValue) { + static @Nullable Entry probeBackupLocations(@Nullable Entry[] cache, ClassValue classValue) { if (PROBE_LIMIT <= 0) return null; // Probe the cache carefully, in a range of slots. int mask = (cache.length-1); @@ -594,7 +597,7 @@ static Entry probeBackupLocations(Entry[] cache, ClassValue classVa } /** How far out of place is e? */ - private static int entryDislocation(Entry[] cache, int pos, Entry e) { + private static int entryDislocation(@Nullable Entry[] cache, int pos, Entry e) { ClassValue cv = e.classValueOrNull(); if (cv == null) return 0; // entry is not live! int mask = (cache.length-1); @@ -636,7 +639,7 @@ private void reduceCacheLoad() { /** Remove stale entries in the given range. * Should be executed under a Map lock. */ - private void removeStaleEntries(Entry[] cache, int begin, int count) { + private void removeStaleEntries(@Nullable Entry[] cache, int begin, int count) { if (PROBE_LIMIT <= 0) return; int mask = (cache.length-1); int removed = 0; @@ -660,7 +663,7 @@ private void removeStaleEntries(Entry[] cache, int begin, int count) { * to be found via reprobes. Find an entry after cache[begin] * to plug into the hole, or return null if none is needed. */ - private Entry findReplacement(Entry[] cache, int home1) { + private @Nullable Entry findReplacement(@Nullable Entry[] cache, int home1) { Entry replacement = null; int haveReplacement = -1, replacementPos = 0; int mask = (cache.length-1); @@ -741,7 +744,7 @@ private void addToCache(ClassValue classValue, Entry e) { /** Store the given entry. Update cacheLoad, and return any live victim. * 'Gently' means return self rather than dislocating a live victim. */ - private Entry placeInCache(Entry[] cache, int pos, Entry e, boolean gently) { + private @Nullable Entry placeInCache(Entry[] cache, int pos, Entry e, boolean gently) { Entry e2 = overwrittenEntry(cache[pos]); if (gently && e2 != null) { // do not overwrite a live entry @@ -758,7 +761,7 @@ private Entry placeInCache(Entry[] cache, int pos, Entry e, boolean gen * because the caller is going to store something * in its place. */ - private Entry overwrittenEntry(Entry e2) { + private @Nullable Entry overwrittenEntry(Entry e2) { if (e2 == null) cacheLoad += 1; else if (e2.isLive()) return e2; return null; diff --git a/src/java.base/share/classes/java/lang/ConditionalSpecialCasing.java b/src/java.base/share/classes/java/lang/ConditionalSpecialCasing.java index 386cbe416cc..6e81de8b2c0 100644 --- a/src/java.base/share/classes/java/lang/ConditionalSpecialCasing.java +++ b/src/java.base/share/classes/java/lang/ConditionalSpecialCasing.java @@ -26,6 +26,7 @@ package java.lang; import org.checkerframework.checker.interning.qual.UsesObjectEquals; +import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.framework.qual.AnnotatedFor; import java.text.BreakIterator; @@ -137,11 +138,11 @@ static int toUpperCaseEx(String src, int index, Locale locale) { } } - static char[] toLowerCaseCharArray(String src, int index, Locale locale) { + static char @Nullable [] toLowerCaseCharArray(String src, int index, Locale locale) { return lookUpTable(src, index, locale, true); } - static char[] toUpperCaseCharArray(String src, int index, Locale locale) { + static char @Nullable [] toUpperCaseCharArray(String src, int index, Locale locale) { char[] result = lookUpTable(src, index, locale, false); if (result != null) { return result; @@ -150,7 +151,7 @@ static char[] toUpperCaseCharArray(String src, int index, Locale locale) { } } - private static char[] lookUpTable(String src, int index, Locale locale, boolean bLowerCasing) { + private static char @Nullable [] lookUpTable(String src, int index, Locale locale, boolean bLowerCasing) { HashSet set = entryTable.get(src.codePointAt(index)); char[] ret = null; @@ -430,10 +431,10 @@ static class Entry { int ch; char [] lower; char [] upper; - String lang; + @Nullable String lang; int condition; - Entry(int ch, char[] lower, char[] upper, String lang, int condition) { + Entry(int ch, char[] lower, char[] upper, @Nullable String lang, int condition) { this.ch = ch; this.lower = lower; this.upper = upper; @@ -453,7 +454,7 @@ char[] getUpperCase() { return upper; } - String getLanguage() { + @Nullable String getLanguage() { return lang; } diff --git a/src/java.base/share/classes/java/lang/Enum.java b/src/java.base/share/classes/java/lang/Enum.java index 3628f0f3bf3..89c2c97929b 100644 --- a/src/java.base/share/classes/java/lang/Enum.java +++ b/src/java.base/share/classes/java/lang/Enum.java @@ -235,7 +235,7 @@ public final int compareTo(@UnknownKeyFor @Tainted E o) { * enum type */ @SuppressWarnings("unchecked") - public final Class<@Tainted E> getDeclaringClass() { + public final @Nullable Class<@Tainted E> getDeclaringClass() { Class clazz = getClass(); Class zuper = clazz.getSuperclass(); return (zuper == Enum.class) ? (Class)clazz : (Class)zuper; @@ -250,6 +250,7 @@ public final int compareTo(@UnknownKeyFor @Tainted E o) { * @since 12 */ @Override + @SuppressWarnings("nullness:dereference.of.nullable") // AOSEN: is this a real NPE? public final Optional> describeConstable() { return getDeclaringClass() .describeConstable() diff --git a/src/java.base/share/classes/java/lang/InheritableThreadLocal.java b/src/java.base/share/classes/java/lang/InheritableThreadLocal.java index f54101e2659..4c504934f37 100644 --- a/src/java.base/share/classes/java/lang/InheritableThreadLocal.java +++ b/src/java.base/share/classes/java/lang/InheritableThreadLocal.java @@ -84,7 +84,7 @@ protected T childValue(T parentValue) { * * @param t the current thread */ - ThreadLocalMap getMap(Thread t) { + @Nullable ThreadLocalMap getMap(Thread t) { return t.inheritableThreadLocals; } diff --git a/src/java.base/share/classes/java/lang/Integer.java b/src/java.base/share/classes/java/lang/Integer.java index 7917ad6dbe9..dceb7e8158e 100644 --- a/src/java.base/share/classes/java/lang/Integer.java +++ b/src/java.base/share/classes/java/lang/Integer.java @@ -1353,7 +1353,7 @@ public boolean equals(@Nullable Object obj) { */ @SideEffectFree @StaticallyExecutable - public static @Nullable Integer getInteger(@Nullable String nm) { + public static @Nullable Integer getInteger(String nm) { return getInteger(nm, null); } @@ -1401,7 +1401,7 @@ public boolean equals(@Nullable Object obj) { */ @SideEffectFree @StaticallyExecutable - public static Integer getInteger(@Nullable String nm, int val) { + public static Integer getInteger(String nm, int val) { Integer result = getInteger(nm, null); return (result == null) ? Integer.valueOf(val) : result; } @@ -1445,7 +1445,7 @@ public static Integer getInteger(@Nullable String nm, int val) { */ @SideEffectFree @StaticallyExecutable - public static @PolyNull Integer getInteger(@Nullable String nm, @PolyNull Integer val) { + public static @PolyNull Integer getInteger(String nm, @PolyNull Integer val) { String v = null; try { v = System.getProperty(nm); diff --git a/src/java.base/share/classes/java/lang/LayerInstantiationException.java b/src/java.base/share/classes/java/lang/LayerInstantiationException.java index 6c1469df79b..5bdafbc1241 100644 --- a/src/java.base/share/classes/java/lang/LayerInstantiationException.java +++ b/src/java.base/share/classes/java/lang/LayerInstantiationException.java @@ -25,6 +25,8 @@ package java.lang; +import org.checkerframework.checker.nullness.qual.Nullable; + /** * Thrown when creating a {@linkplain ModuleLayer module layer} fails. * @@ -48,7 +50,7 @@ public LayerInstantiationException() { * @param msg * The detail message; can be {@code null} */ - public LayerInstantiationException(String msg) { + public LayerInstantiationException(@Nullable String msg) { super(msg); } diff --git a/src/java.base/share/classes/java/lang/Long.java b/src/java.base/share/classes/java/lang/Long.java index 33abaa3d59d..63153e1ab37 100644 --- a/src/java.base/share/classes/java/lang/Long.java +++ b/src/java.base/share/classes/java/lang/Long.java @@ -1575,7 +1575,7 @@ public boolean equals(@Nullable Object obj) { */ @SideEffectFree @StaticallyExecutable - public static @Nullable Long getLong(@Nullable String nm) { + public static @Nullable Long getLong(String nm) { return getLong(nm, null); } @@ -1622,7 +1622,7 @@ public boolean equals(@Nullable Object obj) { */ @SideEffectFree @StaticallyExecutable - public static Long getLong(@Nullable String nm, long val) { + public static Long getLong(String nm, long val) { Long result = Long.getLong(nm, null); return (result == null) ? Long.valueOf(val) : result; } @@ -1673,7 +1673,7 @@ public static Long getLong(@Nullable String nm, long val) { */ @SideEffectFree @StaticallyExecutable - public static @PolyNull Long getLong(@Nullable String nm, @PolyNull Long val) { + public static @PolyNull Long getLong(String nm, @PolyNull Long val) { String v = null; try { v = System.getProperty(nm); diff --git a/src/java.base/share/classes/java/lang/Module.java b/src/java.base/share/classes/java/lang/Module.java index ab7d2103850..febbfeba30b 100644 --- a/src/java.base/share/classes/java/lang/Module.java +++ b/src/java.base/share/classes/java/lang/Module.java @@ -25,6 +25,10 @@ package java.lang; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.checker.nullness.qual.EnsuresNonNull; +import org.checkerframework.dataflow.qual.Pure; + import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; @@ -100,14 +104,14 @@ public final class Module implements AnnotatedElement { // the layer that contains this module, can be null - private final ModuleLayer layer; + private final @Nullable ModuleLayer layer; // module name and loader, these fields are read by VM - private final String name; - private final ClassLoader loader; + private final @Nullable String name; + private final @Nullable ClassLoader loader; // the module descriptor - private final ModuleDescriptor descriptor; + private final @Nullable ModuleDescriptor descriptor; // true, if this module allows restricted native access private volatile boolean enableNativeAccess; @@ -117,10 +121,10 @@ public final class Module implements AnnotatedElement { * VM but will not read any other modules, will not have any exports setup * and will not be registered in the service catalog. */ - Module(ModuleLayer layer, + Module(@Nullable ModuleLayer layer, ClassLoader loader, ModuleDescriptor descriptor, - URI uri) + @Nullable URI uri) { this.layer = layer; this.name = descriptor.name(); @@ -147,7 +151,7 @@ public final class Module implements AnnotatedElement { * * @see ClassLoader#getUnnamedModule */ - Module(ClassLoader loader) { + Module(@Nullable ClassLoader loader) { this.layer = null; this.name = null; this.loader = loader; @@ -160,7 +164,7 @@ public final class Module implements AnnotatedElement { * * @apiNote This constructor is for VM white-box testing. */ - Module(ClassLoader loader, ModuleDescriptor descriptor) { + Module(@Nullable ClassLoader loader, ModuleDescriptor descriptor) { this.layer = null; this.name = descriptor.name(); this.loader = loader; @@ -176,6 +180,9 @@ public final class Module implements AnnotatedElement { * @see ClassLoader#getUnnamedModule() * @jls 7.7.5 Unnamed Modules */ + @SuppressWarnings({"contracts.postcondition.not.satisfied"}) + @EnsuresNonNull({"name", "descriptor"}) // Named modules always have non-null name and descriptor + @Pure public boolean isNamed() { return name != null; } @@ -186,7 +193,8 @@ public boolean isNamed() { * * @return The module name */ - public String getName() { + @Pure + public @Nullable String getName() { return name; } @@ -203,7 +211,7 @@ public String getName() { * @throws SecurityException * If denied by the security manager */ - public ClassLoader getClassLoader() { + public @Nullable ClassLoader getClassLoader() { @SuppressWarnings("removal") SecurityManager sm = System.getSecurityManager(); if (sm != null) { @@ -218,11 +226,11 @@ public ClassLoader getClassLoader() { * * @return The module descriptor for this module */ - public ModuleDescriptor getDescriptor() { + public @Nullable ModuleDescriptor getDescriptor() { return descriptor; } - /** + /**1 * Returns the module layer that contains this module or {@code null} if * this module is not in a module layer. * @@ -237,7 +245,7 @@ public ModuleDescriptor getDescriptor() { * * @see java.lang.reflect.Proxy */ - public ModuleLayer getLayer() { + public @Nullable ModuleLayer getLayer() { if (isNamed()) { ModuleLayer layer = this.layer; if (layer != null) @@ -1124,6 +1132,7 @@ public Set getPackages() { * If the module cannot be defined to the VM or its packages overlap * with another module mapped to the same class loader */ + @SuppressWarnings("nullness:assignment.type.incompatible") // toArray returns a non-null element array static Map defineModules(Configuration cf, Function clf, ModuleLayer layer) @@ -1273,7 +1282,7 @@ static Map defineModules(Configuration cf, * Find the runtime Module corresponding to the given ResolvedModule * in the given parent layer (or its parents). */ - private static Module findModule(ModuleLayer parent, + private static @Nullable Module findModule(ModuleLayer parent, ResolvedModule resolvedModule) { Configuration cf = resolvedModule.configuration(); String dn = resolvedModule.name(); @@ -1296,6 +1305,7 @@ private static Module findModule(ModuleLayer parent, * @param m the module * @param nameToModule map of module name to Module (for qualified exports) */ + @SuppressWarnings("nullness:dereference.of.nullable") // AOSEN: is this a NPE? private static void initExports(Module m, Map nameToModule) { Map> exportedPackages = new HashMap<>(); @@ -1334,6 +1344,7 @@ private static void initExports(Module m, Map nameToModule) { * under construction * @param parents the parent layers */ + @SuppressWarnings("nullness:dereference.of.nullable") // AOSEN: is this a NPE? private static void initExportsAndOpens(Module m, Map nameToSource, Map nameToModule, @@ -1413,7 +1424,7 @@ private static void initExportsAndOpens(Module m, * @param nameToModule The modules in the layer under construction * @param parents The parent layers */ - private static Module findModule(String target, + private static @Nullable Module findModule(String target, Map nameToSource, Map nameToModule, List parents) { @@ -1441,7 +1452,7 @@ private static Module findModule(String target, * declaration annotation. */ @Override - public T getAnnotation(Class annotationClass) { + public @Nullable T getAnnotation(Class annotationClass) { return moduleInfoClass().getDeclaredAnnotation(annotationClass); } @@ -1482,7 +1493,7 @@ private Class moduleInfoClass() { clazz = this.moduleInfoClass; if (clazz == null) { if (isNamed()) { - PrivilegedAction> pa = this::loadModuleInfoClass; + PrivilegedAction<@Nullable Class> pa = this::loadModuleInfoClass; clazz = AccessController.doPrivileged(pa); } if (clazz == null) { @@ -1495,7 +1506,7 @@ class DummyModuleInfo { } } } - private Class loadModuleInfoClass() { + private @Nullable Class loadModuleInfoClass() { Class clazz = null; try (InputStream in = getResourceAsStream("module-info.class")) { if (in != null) @@ -1541,7 +1552,7 @@ public void visitAttribute(Attribute attr) { // drop non-annotation attributes } @Override - public ModuleVisitor visitModule(String name, int flags, String version) { + public @Nullable ModuleVisitor visitModule(String name, int flags, String version) { // drop Module attribute return null; } @@ -1642,7 +1653,9 @@ protected Class loadClass(String cn, boolean resolve) * @see Class#getResourceAsStream(String) */ @CallerSensitive - public InputStream getResourceAsStream(String name) throws IOException { + @SuppressWarnings("nullness:argument.type.incompatible") // This code is updated in the latest JDK. + //https://github.com/openjdk/jdk/blob/4a4209ffef8f8d65054cbf46ebf8e169d100c0d8/src/java.base/share/classes/java/lang/Module.java#L1688C21-L1695C22 + public @Nullable InputStream getResourceAsStream(String name) throws IOException { if (name.startsWith("/")) { name = name.substring(1); } @@ -1707,7 +1720,7 @@ public String toString() { * Returns the module that a given caller class is a member of. Returns * {@code null} if the caller is {@code null}. */ - private Module getCallerModule(Class caller) { + private @Nullable Module getCallerModule(Class caller) { return (caller != null) ? caller.getModule() : null; } @@ -1717,12 +1730,12 @@ private Module getCallerModule(Class caller) { // JVM_DefineModule private static native void defineModule0(Module module, boolean isOpen, - String version, - String location, + @Nullable String version, + @Nullable String location, Object[] pns); // JVM_AddReadsModule - private static native void addReads0(Module from, Module to); + private static native void addReads0(Module from, @Nullable Module to); // JVM_AddModuleExports private static native void addExports0(Module from, String pn, Module to); diff --git a/src/java.base/share/classes/java/lang/ModuleLayer.java b/src/java.base/share/classes/java/lang/ModuleLayer.java index 6cecfe6d388..6a347fe5c76 100644 --- a/src/java.base/share/classes/java/lang/ModuleLayer.java +++ b/src/java.base/share/classes/java/lang/ModuleLayer.java @@ -25,6 +25,8 @@ package java.lang; +import org.checkerframework.checker.nullness.qual.Nullable; + import java.lang.module.Configuration; import java.lang.module.ModuleDescriptor; import java.lang.module.ResolvedModule; @@ -171,9 +173,10 @@ public final class ModuleLayer { /** * Creates a new module layer from the modules in the given configuration. */ + @SuppressWarnings("nullness:argument.type.incompatible") // AOSEN: there could be possible NPE if clf is null private ModuleLayer(Configuration cf, List parents, - Function clf) + @Nullable Function clf) { this.cf = cf; this.parents = parents; // no need to do defensive copy @@ -880,7 +883,7 @@ public Optional findModule(String name) { * * @throws SecurityException if denied by the security manager */ - public ClassLoader findLoader(String name) { + public @Nullable ClassLoader findLoader(String name) { Optional om = findModule(name); // can't use map(Module::getClassLoader) as class loader can be null diff --git a/src/java.base/share/classes/java/lang/NamedPackage.java b/src/java.base/share/classes/java/lang/NamedPackage.java index 6234b949e65..335beb2e66c 100644 --- a/src/java.base/share/classes/java/lang/NamedPackage.java +++ b/src/java.base/share/classes/java/lang/NamedPackage.java @@ -24,6 +24,8 @@ */ package java.lang; +import org.checkerframework.checker.nullness.qual.Nullable; + import java.lang.module.Configuration; import java.lang.module.ModuleReference; import java.net.URI; @@ -70,7 +72,8 @@ Module module() { * Returns the location of the module if this named package is in * a named module; otherwise, returns null. */ - URI location() { + @SuppressWarnings({"nullness:dereference.of.nullable", "nullness:argument.type.incompatible"}) // The problem does not apply to named packages + @Nullable URI location() { if (module.isNamed() && module.getLayer() != null) { Configuration cf = module.getLayer().configuration(); ModuleReference mref diff --git a/src/java.base/share/classes/java/lang/Package.java b/src/java.base/share/classes/java/lang/Package.java index 5682bb8be75..08f8ba6751e 100644 --- a/src/java.base/share/classes/java/lang/Package.java +++ b/src/java.base/share/classes/java/lang/Package.java @@ -440,7 +440,7 @@ private Class getPackageInfo() { // find package-info.class defined by loader String cn = packageName() + ".package-info"; Module module = module(); - PrivilegedAction pa = module::getClassLoader; + PrivilegedAction<@Nullable ClassLoader> pa = module::getClassLoader; @SuppressWarnings("removal") ClassLoader loader = AccessController.doPrivileged(pa); Class c; @@ -470,7 +470,7 @@ class PackageInfoProxy {} * @since 1.5 */ @Override - public @Nullable A getAnnotation(Class annotationClass) { + public @Nullable A getAnnotation(Class annotationClass) { return getPackageInfo().getAnnotation(annotationClass); } @@ -494,7 +494,7 @@ public boolean isAnnotationPresent(@GuardSatisfied Package this, @GuardSatisfied * @since 1.8 */ @Override - public A[] getAnnotationsByType(Class annotationClass) { + public A[] getAnnotationsByType(Class annotationClass) { return getPackageInfo().getAnnotationsByType(annotationClass); } @@ -518,7 +518,7 @@ public Annotation[] getAnnotations() { * @since 1.8 */ @Override - public @Nullable A getDeclaredAnnotation(Class annotationClass) { + public @Nullable A getDeclaredAnnotation(Class annotationClass) { return getPackageInfo().getDeclaredAnnotation(annotationClass); } @@ -527,7 +527,7 @@ public Annotation[] getAnnotations() { * @since 1.8 */ @Override - public A[] getDeclaredAnnotationsByType(Class annotationClass) { + public A[] getDeclaredAnnotationsByType(Class annotationClass) { return getPackageInfo().getDeclaredAnnotationsByType(annotationClass); } @@ -560,9 +560,9 @@ public Annotation[] getDeclaredAnnotations() { * @param loader defining class loader */ Package(@DotSeparatedIdentifiers String name, - String spectitle, String specversion, String specvendor, - String impltitle, String implversion, String implvendor, - URL sealbase, ClassLoader loader) + @Nullable String spectitle, @Nullable String specversion, @Nullable String specvendor, + @Nullable String impltitle, @Nullable String implversion, @Nullable String implvendor, + @Nullable URL sealbase, ClassLoader loader) { super(Objects.requireNonNull(name), loader != null ? loader.getUnnamedModule() @@ -586,18 +586,18 @@ static class VersionInfo { static final VersionInfo NULL_VERSION_INFO = new VersionInfo(null, null, null, null, null, null, null); - private final String specTitle; - private final String specVersion; - private final String specVendor; - private final String implTitle; - private final String implVersion; - private final String implVendor; - private final URL sealBase; - - static VersionInfo getInstance(String spectitle, String specversion, - String specvendor, String impltitle, - String implversion, String implvendor, - URL sealbase) { + private final @Nullable String specTitle; + private final @Nullable String specVersion; + private final @Nullable String specVendor; + private final @Nullable String implTitle; + private final @Nullable String implVersion; + private final @Nullable String implVendor; + private final @Nullable URL sealBase; + + static VersionInfo getInstance(@Nullable String spectitle, @Nullable String specversion, + @Nullable String specvendor, @Nullable String impltitle, + @Nullable String implversion, @Nullable String implvendor, + @Nullable URL sealbase) { if (spectitle == null && specversion == null && specvendor == null && impltitle == null && implversion == null && implvendor == null && @@ -609,10 +609,10 @@ static VersionInfo getInstance(String spectitle, String specversion, sealbase); } - private VersionInfo(String spectitle, String specversion, - String specvendor, String impltitle, - String implversion, String implvendor, - URL sealbase) + private VersionInfo(@Nullable String spectitle, @Nullable String specversion, + @Nullable String specvendor, @Nullable String impltitle, + @Nullable String implversion, @Nullable String implvendor, + @Nullable URL sealbase) { this.implTitle = impltitle; this.implVersion = implversion; diff --git a/src/java.base/share/classes/java/lang/ProcessBuilder.java b/src/java.base/share/classes/java/lang/ProcessBuilder.java index 85a2fe3b703..9f88ef5139d 100644 --- a/src/java.base/share/classes/java/lang/ProcessBuilder.java +++ b/src/java.base/share/classes/java/lang/ProcessBuilder.java @@ -28,6 +28,7 @@ import org.checkerframework.checker.mustcall.qual.MustCall; import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.tainting.qual.Untainted; +import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.framework.qual.AnnotatedFor; import java.io.File; @@ -198,7 +199,7 @@ public final class ProcessBuilder { private List command; - private File directory; + private @Nullable File directory; private Map environment; private boolean redirectErrorStream; private Redirect[] redirects; @@ -368,7 +369,7 @@ public Map environment() { } // Only for use by Runtime.exec(...envp...) - ProcessBuilder environment(String[] envp) { + ProcessBuilder environment(String @Nullable [] envp) { assert environment == null; if (envp != null) { environment = ProcessEnvironment.emptyEnvironment(envp.length); @@ -581,7 +582,8 @@ public enum Type { * @return the file associated with this redirect, * or {@code null} if there is no such file */ - public File file() { return null; } + @Pure + public @Nullable File file() { return null; } /** * When redirected to a destination file, indicates if the output @@ -679,7 +681,7 @@ public String toString() { * instances of the same type associated with non-null equal * {@code File} instances. */ - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj == this) return true; if (! (obj instanceof Redirect r)) @@ -1089,7 +1091,7 @@ public Process start() throws IOException { * @return the new Process * @throws IOException if an I/O error occurs */ - private Process start(Redirect[] redirects) throws IOException { + private Process start(@Nullable Redirect[] redirects) throws IOException { // Must convert to array first -- a malicious user-supplied // list might try to circumvent the security check. String[] cmdarray = command.toArray(new String[command.size()]); @@ -1284,7 +1286,7 @@ public static List startPipeline(List builders) throws Redirect prevOutput = null; for (int index = 0; index < builders.size(); index++) { ProcessBuilder builder = builders.get(index); - Redirect[] redirects = builder.redirects(); + @Nullable Redirect[] redirects = builder.redirects(); if (index > 0) { // check the current Builder to see if it can take input from the previous if (builder.redirectInput() != Redirect.PIPE) { diff --git a/src/java.base/share/classes/java/lang/ProcessHandle.java b/src/java.base/share/classes/java/lang/ProcessHandle.java index 229f98d0b6f..aff82c93b9f 100644 --- a/src/java.base/share/classes/java/lang/ProcessHandle.java +++ b/src/java.base/share/classes/java/lang/ProcessHandle.java @@ -24,6 +24,8 @@ */ package java.lang; +import org.checkerframework.checker.nullness.qual.Nullable; + import java.time.Duration; import java.time.Instant; import java.util.Optional; @@ -415,7 +417,7 @@ public interface Info { * the same system process; otherwise returns {@code false} */ @Override - boolean equals(Object other); + boolean equals(@Nullable Object other); /** * Compares this ProcessHandle with the specified ProcessHandle for order. diff --git a/src/java.base/share/classes/java/lang/ProcessHandleImpl.java b/src/java.base/share/classes/java/lang/ProcessHandleImpl.java index 593ee48f27d..fb7d71a5c9b 100644 --- a/src/java.base/share/classes/java/lang/ProcessHandleImpl.java +++ b/src/java.base/share/classes/java/lang/ProcessHandleImpl.java @@ -88,7 +88,7 @@ final class ProcessHandleImpl implements ProcessHandle { /** * The thread pool of "process reaper" daemon threads. */ - @SuppressWarnings("removal") + @SuppressWarnings({"removal", "nullness:dereference.of.nullable"}) // AOSEN: Is this a real NPE? private static final Executor processReaperExecutor = AccessController.doPrivileged((PrivilegedAction) () -> { // Initialize ThreadLocalRandom now to avoid using the smaller stack @@ -341,7 +341,7 @@ public Optional parent() { * if greater than the length of the arrays, the arrays are too small */ private static native int getProcessPids0(long pid, long[] pids, - long[] ppids, long[] starttimes); + long @Nullable [] ppids, long[] starttimes); /** * Destroy the process for this ProcessHandle. @@ -427,6 +427,7 @@ public Stream children() { * 0 for all processes * @return a stream of ProcessHandles */ + @SuppressWarnings("nullness:accessing.nullable") // AOSEN: this is a false positive to me static Stream children(long pid) { @SuppressWarnings("removal") SecurityManager sm = System.getSecurityManager(); @@ -448,6 +449,7 @@ static Stream children(long pid) { } @Override + @SuppressWarnings("nullness:accessing.nullable") // AOSEN: this is a false positive to me public Stream descendants() { @SuppressWarnings("removal") SecurityManager sm = System.getSecurityManager(); @@ -563,12 +565,12 @@ static class Info implements ProcessHandle.Info { */ private native void info0(long pid); - String command; - String commandLine; - String[] arguments; + @Nullable String command; + @Nullable String commandLine; + String @Nullable [] arguments; long startTime; long totalTime; - String user; + @Nullable String user; Info() { command = null; diff --git a/src/java.base/share/classes/java/lang/PublicMethods.java b/src/java.base/share/classes/java/lang/PublicMethods.java index b9851e2f049..54f0effe5a7 100644 --- a/src/java.base/share/classes/java/lang/PublicMethods.java +++ b/src/java.base/share/classes/java/lang/PublicMethods.java @@ -24,6 +24,8 @@ */ package java.lang; +import org.checkerframework.checker.nullness.qual.Nullable; + import jdk.internal.reflect.ReflectionFactory; import java.lang.reflect.Method; @@ -58,6 +60,7 @@ final class PublicMethods { * than added method. * See comments in code... */ + @SuppressWarnings("nullness:dereference.of.nullable") // AOSEN: is this a real NPE? void merge(Method method) { Key key = new Key(method); MethodList existing = map.get(key); @@ -112,7 +115,7 @@ static boolean matches(Method method, } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) return true; //noinspection StringEquality (guaranteed interned String(s)) return (o instanceof Key that) @@ -145,7 +148,7 @@ private MethodList(Method method) { * {@code ptypes} and including or excluding static methods as * requested by {@code includeStatic} flag. */ - static MethodList filter(Method[] methods, String name, + static @Nullable MethodList filter(Method[] methods, String name, Class[] ptypes, boolean includeStatic) { MethodList head = null, tail = null; for (Method method : methods) { @@ -170,16 +173,16 @@ static MethodList filter(Method[] methods, String name, * containing only the most specific methods for each signature * (i.e. return type). The returned head of the merged list may or * may not be the same as the {@code head} of the given list. - * The given {@code methodList} is not modified. + * The given {@code methodList} is not modified.1 */ - static MethodList merge(MethodList head, MethodList methodList) { + static @Nullable MethodList merge(@Nullable MethodList head, @Nullable MethodList methodList) { for (MethodList ml = methodList; ml != null; ml = ml.next) { head = merge(head, ml.method); } return head; } - private static MethodList merge(MethodList head, Method method) { + private static @Nullable MethodList merge(@Nullable MethodList head, Method method) { Class dclass = method.getDeclaringClass(); Class rtype = method.getReturnType(); MethodList prev = null; diff --git a/src/java.base/share/classes/java/lang/ReflectiveOperationException.java b/src/java.base/share/classes/java/lang/ReflectiveOperationException.java index 0c79de008be..2296582813c 100644 --- a/src/java.base/share/classes/java/lang/ReflectiveOperationException.java +++ b/src/java.base/share/classes/java/lang/ReflectiveOperationException.java @@ -25,6 +25,8 @@ package java.lang; +import org.checkerframework.checker.nullness.qual.Nullable; + /** * Common superclass of exceptions thrown by reflective operations in * core reflection. @@ -53,7 +55,7 @@ public ReflectiveOperationException() { * @param message the detail message. The detail message is saved for * later retrieval by the {@link #getMessage()} method. */ - public ReflectiveOperationException(String message) { + public ReflectiveOperationException(@Nullable String message) { super(message); } @@ -72,7 +74,7 @@ public ReflectiveOperationException(String message) { * permitted, and indicates that the cause is nonexistent or * unknown.) */ - public ReflectiveOperationException(String message, Throwable cause) { + public ReflectiveOperationException(@Nullable String message, @Nullable Throwable cause) { super(message, cause); } @@ -86,7 +88,7 @@ public ReflectiveOperationException(String message, Throwable cause) { * permitted, and indicates that the cause is nonexistent or * unknown.) */ - public ReflectiveOperationException(Throwable cause) { + public ReflectiveOperationException(@Nullable Throwable cause) { super(cause); } } diff --git a/src/java.base/share/classes/java/lang/Runtime.java b/src/java.base/share/classes/java/lang/Runtime.java index 9e20a7e0a31..bd4444be140 100644 --- a/src/java.base/share/classes/java/lang/Runtime.java +++ b/src/java.base/share/classes/java/lang/Runtime.java @@ -1017,6 +1017,7 @@ private Version(List unmodifiableListOfVersions, * * @return The Version of the given string */ + @SuppressWarnings("nullness:dereference.of.nullable") //AOSEN: possible NPE? I am not sure `m.group(VersionPattern.VNUM_GROUP)` public static Version parse(String s) { if (s == null) throw new NullPointerException(); @@ -1418,6 +1419,7 @@ public String toString() { * */ @Override + @SuppressWarnings("nullness:override.param.invalid") // AOSEN: Don't use @Nullable here as null value will produce NPE. public boolean equals(Object obj) { boolean ret = equalsIgnoreOptional(obj); if (!ret) @@ -1442,7 +1444,7 @@ public boolean equals(Object obj) { * ignoring the optional build information * */ - public boolean equalsIgnoreOptional(Object obj) { + public boolean equalsIgnoreOptional(@Nullable Object obj) { if (this == obj) return true; return (obj instanceof Version that) diff --git a/src/java.base/share/classes/java/lang/RuntimePermission.java b/src/java.base/share/classes/java/lang/RuntimePermission.java index d19b1125fa3..19f0d85f804 100644 --- a/src/java.base/share/classes/java/lang/RuntimePermission.java +++ b/src/java.base/share/classes/java/lang/RuntimePermission.java @@ -419,7 +419,7 @@ public final class RuntimePermission extends BasicPermission { * @throws IllegalArgumentException if {@code name} is empty. */ - public RuntimePermission(String name) + public RuntimePermission(@Nullable String name) { super(name); } @@ -436,7 +436,7 @@ public RuntimePermission(String name) * @throws IllegalArgumentException if {@code name} is empty. */ - public RuntimePermission(String name, @Nullable String actions) + public RuntimePermission(@Nullable String name, @Nullable String actions) { super(name, actions); } diff --git a/src/java.base/share/classes/java/lang/SecurityManager.java b/src/java.base/share/classes/java/lang/SecurityManager.java index a98860f6436..56715710476 100644 --- a/src/java.base/share/classes/java/lang/SecurityManager.java +++ b/src/java.base/share/classes/java/lang/SecurityManager.java @@ -26,6 +26,7 @@ package java.lang; import org.checkerframework.checker.interning.qual.UsesObjectEquals; +import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.framework.qual.AnnotatedFor; import java.lang.module.ModuleDescriptor; @@ -490,6 +491,7 @@ public void checkCreateClassLoader() { private static ThreadGroup rootGroup = getRootGroup(); + @SuppressWarnings("nullness:dereference.of.nullable") // AOSEN: is this a real bug? private static ThreadGroup getRootGroup() { ThreadGroup root = Thread.currentThread().getThreadGroup(); while (root.getParent() != null) { @@ -1244,6 +1246,7 @@ private static String[] getPackages(String p) { /** * Record the non-exported packages of the modules in the given layer */ + @SuppressWarnings("type.arguments.not.inferred") static void addNonExportedPackages(ModuleLayer layer) { Set bootModules = ModuleLoaderMap.bootModules(); Set platformModules = ModuleLoaderMap.platformModules(); @@ -1546,7 +1549,7 @@ public void checkSecurityAccess(String target) { * @since 1.1 * @see java.lang.ThreadGroup */ - public ThreadGroup getThreadGroup() { + public @Nullable ThreadGroup getThreadGroup() { return Thread.currentThread().getThreadGroup(); } diff --git a/src/java.base/share/classes/java/lang/StackFrameInfo.java b/src/java.base/share/classes/java/lang/StackFrameInfo.java index acdd222121f..eaec9d824a2 100644 --- a/src/java.base/share/classes/java/lang/StackFrameInfo.java +++ b/src/java.base/share/classes/java/lang/StackFrameInfo.java @@ -24,6 +24,8 @@ */ package java.lang; +import org.checkerframework.checker.nullness.qual.Nullable; + import jdk.internal.access.JavaLangInvokeAccess; import jdk.internal.access.SharedSecrets; @@ -96,7 +98,7 @@ public int getByteCodeIndex() { } @Override - public String getFileName() { + public @Nullable String getFileName() { return toStackTraceElement().getFileName(); } diff --git a/src/java.base/share/classes/java/lang/StackStreamFactory.java b/src/java.base/share/classes/java/lang/StackStreamFactory.java index 55b276e393f..4c480c6da58 100644 --- a/src/java.base/share/classes/java/lang/StackStreamFactory.java +++ b/src/java.base/share/classes/java/lang/StackStreamFactory.java @@ -24,8 +24,10 @@ */ package java.lang; +import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nonempty.qual.EnsuresNonEmptyIf; import org.checkerframework.dataflow.qual.Pure; + import jdk.internal.reflect.MethodAccessor; import jdk.internal.reflect.ConstructorAccessor; import java.lang.StackWalker.Option; @@ -258,7 +260,7 @@ private boolean skipReflectionFrames() { * or {@code null} if no more frame. If advanceToNextBatch is true, * it will only fetch the next batch. */ - final Class peekFrame() { + final @Nullable Class peekFrame() { while (frameBuffer.isActive() && depth < maxDepth) { if (frameBuffer.isEmpty()) { // fetch another batch of stack frames @@ -290,7 +292,8 @@ final Class peekFrame() { * 2. reuse or expand the allocated buffers * 3. create specialized StackFrame objects */ - private Object doStackWalk(long anchor, int skipFrames, int batchSize, + // AOSEN: let's try nullable first. + private @Nullable Object doStackWalk(long anchor, int skipFrames, int batchSize, int bufStartIndex, int bufEndIndex) { checkState(NEW); @@ -334,7 +337,7 @@ private int getNextBatch() { * * @see #tryNextFrame */ - final Class nextFrame() { + final @Nullable Class nextFrame() { if (!hasNext()) { return null; } @@ -519,7 +522,7 @@ final Class at(int index) { * Returns next StackFrame object in the current batch of stack frames; * or null if no more stack frame. */ - StackFrame nextStackFrame() { + @Nullable StackFrame nextStackFrame() { if (!hasNext()) { return null; } @@ -563,7 +566,7 @@ protected int batchSize(int lastBatchFrameCount) { // ------- Implementation of Spliterator @Override - public Spliterator trySplit() { + public @Nullable Spliterator trySplit() { return null; // ordered stream and do not allow to split } @@ -589,6 +592,7 @@ public void forEachRemaining(Consumer action) { } @Override + @SuppressWarnings("nullness:argument.type.incompatible") // AOSEN: why this error? public boolean tryAdvance(Consumer action) { checkState(OPEN); @@ -675,6 +679,7 @@ Class findCaller() { } @Override + @SuppressWarnings("nullness:assignment.type.incompatible") // AOSEN: caller is only null if nextFrame() returns null protected Integer consumeFrames() { checkState(OPEN); int n = 0; diff --git a/src/java.base/share/classes/java/lang/StackTraceElement.java b/src/java.base/share/classes/java/lang/StackTraceElement.java index 27b5bd237a2..9a11cd450f6 100644 --- a/src/java.base/share/classes/java/lang/StackTraceElement.java +++ b/src/java.base/share/classes/java/lang/StackTraceElement.java @@ -71,15 +71,15 @@ public final class StackTraceElement implements java.io.Serializable { /** * The name of the class loader. */ - private String classLoaderName; + private @Nullable String classLoaderName; /** * The module name. */ - private String moduleName; + private @Nullable String moduleName; /** * The module version. */ - private String moduleVersion; + private @Nullable String moduleVersion; /** * The declaring class. */ @@ -91,7 +91,7 @@ public final class StackTraceElement implements java.io.Serializable { /** * The source file name. */ - private String fileName; + private @Nullable String fileName; /** * The source line number. */ @@ -160,10 +160,10 @@ public StackTraceElement(@FullyQualifiedName String declaringClass, String metho * * @since 9 */ - public StackTraceElement(String classLoaderName, - String moduleName, String moduleVersion, + public StackTraceElement(@Nullable String classLoaderName, + @Nullable String moduleName, @Nullable String moduleVersion, String declaringClass, String methodName, - String fileName, int lineNumber) { + @Nullable String fileName, int lineNumber) { this.classLoaderName = classLoaderName; this.moduleName = moduleName; this.moduleVersion = moduleVersion; @@ -220,7 +220,7 @@ public int getLineNumber(@GuardSatisfied StackTraceElement this) { * @since 9 * @see Module#getName() */ - public String getModuleName() { + public @Nullable String getModuleName() { return moduleName; } @@ -234,7 +234,7 @@ public String getModuleName() { * @since 9 * @see java.lang.module.ModuleDescriptor.Version */ - public String getModuleVersion() { + public @Nullable String getModuleVersion() { return moduleVersion; } @@ -249,7 +249,7 @@ public String getModuleVersion() { * @since 9 * @see java.lang.ClassLoader#getName() */ - public String getClassLoaderName() { + public @Nullable String getClassLoaderName() { return classLoaderName; } @@ -453,6 +453,7 @@ public int hashCode(@GuardSatisfied StackTraceElement this) { * If the loader is one of the built-in loaders (`boot`, `platform`, or `app`) * then set BUILTIN_CLASS_LOADER to omit the first element (`/`). */ + @SuppressWarnings("nullness:assignment.type.incompatible") // AOSEN: declaringClassObject set to null only when clearing it private synchronized void computeFormat() { try { Class cls = (Class) declaringClassObject; @@ -534,6 +535,7 @@ static Set hashedModules() { } @Pure + @SuppressWarnings("nullness:argument.type.incompatible") // False positive because set interface is used. static boolean contains(Module m) { return HASHED_MODULES.contains(m.getName()); } diff --git a/src/java.base/share/classes/java/lang/StackWalker.java b/src/java.base/share/classes/java/lang/StackWalker.java index c703e4caf6f..ac44b6f50be 100644 --- a/src/java.base/share/classes/java/lang/StackWalker.java +++ b/src/java.base/share/classes/java/lang/StackWalker.java @@ -200,7 +200,7 @@ public default String getDescriptor() { * * @jvms 4.7.10 The {@code SourceFile} Attribute */ - public String getFileName(); + public @Nullable String getFileName(); /** * Returns the line number of the source line containing the execution @@ -296,7 +296,7 @@ enum ExtendedOption { new StackWalker(DEFAULT_EMPTY_OPTION); private final Set