diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index f96ad9ff972..eab1993a2b4 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -160,6 +160,10 @@ import sun.reflect.annotation.*; * other members are the classes and interfaces whose declarations are * enclosed within the top-level class declaration. * + *

Unless otherwise specified, methods in this class throw a + * {@link NullPointerException} when they are called with {@code null} + * or an array that contains {@code null} as an argument. + * *

Hidden Classes

* A class or interface created by the invocation of * {@link java.lang.invoke.MethodHandles.Lookup#defineHiddenClass(byte[], boolean, MethodHandles.Lookup.ClassOption...) @@ -530,7 +534,8 @@ public final class Class implements java.io.Serializable, * (which implies linking). See Section {@jls * 12.4} of The Java Language * Specification. - * @param loader class loader from which the class must be loaded + * @param loader class loader from which the class must be loaded, + * may be {@code null} * @return class object representing the desired class * * @throws LinkageError if the linkage fails @@ -589,8 +594,6 @@ public final class Class implements java.io.Serializable, * @return {@code Class} object of the given name defined in the given module; * {@code null} if not found. * - * @throws NullPointerException if the given module or name is {@code null} - * * @throws LinkageError if the linkage fails * * @jls 12.2 Loading of Classes and Interfaces @@ -620,8 +623,6 @@ public final class Class implements java.io.Serializable, * * @param primitiveName the name of the primitive type to find * - * @throws NullPointerException if the argument is {@code null} - * * @jls 4.2 Primitive Types and Values * @jls 15.8.2 Class Literals * @since 22 @@ -757,7 +758,7 @@ public final class Class implements java.io.Serializable, * this {@code Class} object represents a primitive type, this method * returns {@code false}. * - * @param obj the object to check + * @param obj the object to check, may be {@code null} * @return true if {@code obj} is an instance of this class * * @since 1.1 @@ -787,8 +788,6 @@ public final class Class implements java.io.Serializable, * @param cls the {@code Class} object to be checked * @return the {@code boolean} value indicating whether objects of the * type {@code cls} can be assigned to objects of this class - * @throws NullPointerException if the specified Class parameter is - * null. * @since 1.1 */ @IntrinsicCandidate @@ -2057,7 +2056,6 @@ public final class Class implements java.io.Serializable, * {@code name} * @throws NoSuchFieldException if a field with the specified name is * not found. - * @throws NullPointerException if {@code name} is {@code null} * * @since 1.1 * @jls 8.2 Class Members @@ -2148,13 +2146,13 @@ public final class Class implements java.io.Serializable, * overriding method as it would have a more specific return type. * * @param name the name of the method - * @param parameterTypes the list of parameters + * @param parameterTypes the list of parameters, may be {@code null} * @return the {@code Method} object that matches the specified * {@code name} and {@code parameterTypes} - * @throws NoSuchMethodException if a matching method is not found + * @throws NoSuchMethodException if a matching method is not found, + * if {@code parameterTypes} contains {@code null}, * or if the name is {@value ConstantDescs#INIT_NAME} or - * {@value ConstantDescs#CLASS_INIT_NAME}. - * @throws NullPointerException if {@code name} is {@code null} + * {@value ConstantDescs#CLASS_INIT_NAME} * * @jls 8.2 Class Members * @jls 8.4 Method Declarations @@ -2185,12 +2183,13 @@ public final class Class implements java.io.Serializable, * represented by this {@code Class} object whose formal parameter * types match those specified by {@code parameterTypes}. * - * @param parameterTypes the parameter array + * @param parameterTypes the parameter array, may be {@code null} * @return the {@code Constructor} object of the public constructor that * matches the specified {@code parameterTypes} * @throws NoSuchMethodException if a matching constructor is not found, - * including when this {@code Class} object represents - * an interface, a primitive type, an array class, or void. + * if this {@code Class} object represents an interface, a primitive + * type, an array class, or void, or if {@code parameterTypes} + * contains {@code null} * * @see #getDeclaredConstructor(Class[]) * @since 1.1 @@ -2371,7 +2370,6 @@ public final class Class implements java.io.Serializable, * class * @throws NoSuchFieldException if a field with the specified name is * not found. - * @throws NullPointerException if {@code name} is {@code null} * * @since 1.1 * @jls 8.2 Class Members @@ -2406,11 +2404,13 @@ public final class Class implements java.io.Serializable, * method does not find the {@code clone()} method. * * @param name the name of the method - * @param parameterTypes the parameter array - * @return the {@code Method} object for the method of this class - * matching the specified name and parameters - * @throws NoSuchMethodException if a matching method is not found. - * @throws NullPointerException if {@code name} is {@code null} + * @param parameterTypes the parameter array, may be {@code null} + * @return the {@code Method} object for the method of this class + * matching the specified name and parameters + * @throws NoSuchMethodException if a matching method is not found, + * if {@code parameterTypes} contains {@code null}, + * or if the name is {@value ConstantDescs#INIT_NAME} or + * {@value ConstantDescs#CLASS_INIT_NAME} * * @jls 8.2 Class Members * @jls 8.4 Method Declarations @@ -2477,12 +2477,13 @@ public final class Class implements java.io.Serializable, * declared in a non-static context, the formal parameter types * include the explicit enclosing instance as the first parameter. * - * @param parameterTypes the parameter array + * @param parameterTypes the parameter array, may be {@code null} * @return The {@code Constructor} object for the constructor with the * specified parameter list * @throws NoSuchMethodException if a matching constructor is not found, - * including when this {@code Class} object represents - * an interface, a primitive type, an array class, or void. + * if this {@code Class} object represents an interface, a + * primitive type, an array class, or void, or if + * {@code parameterTypes} contains {@code null} * * @see #getConstructor(Class[]) * @since 1.1 @@ -2541,7 +2542,6 @@ public final class Class implements java.io.Serializable, * resource with this name is found, or the resource is in a package * that is not {@linkplain Module#isOpen(String, Module) open} to at * least the caller module. - * @throws NullPointerException If {@code name} is {@code null} * * @see Module#getResourceAsStream(String) * @since 1.1 @@ -2637,7 +2637,6 @@ public final class Class implements java.io.Serializable, * resource is in a package that is not * {@linkplain Module#isOpen(String, Module) open} to at least the caller * module. - * @throws NullPointerException If {@code name} is {@code null} * @since 1.1 */ @CallerSensitive @@ -3479,7 +3478,7 @@ public final class Class implements java.io.Serializable, * Casts an object to the class or interface represented * by this {@code Class} object. * - * @param obj the object to be cast + * @param obj the object to be cast, may be {@code null} * @return the object after casting, or null if obj is null * * @throws ClassCastException if the object is not @@ -3534,7 +3533,6 @@ public final class Class implements java.io.Serializable, *

Note that any annotation returned by this method is a * declaration annotation. * - * @throws NullPointerException {@inheritDoc} * @since 1.5 */ @Override @@ -3547,7 +3545,6 @@ public final class Class implements java.io.Serializable, /** * {@inheritDoc} - * @throws NullPointerException {@inheritDoc} * @since 1.5 */ @Override @@ -3560,7 +3557,6 @@ public final class Class implements java.io.Serializable, *

Note that any annotations returned by this method are * declaration annotations. * - * @throws NullPointerException {@inheritDoc} * @since 1.8 */ @Override @@ -3590,7 +3586,6 @@ public final class Class implements java.io.Serializable, *

Note that any annotation returned by this method is a * declaration annotation. * - * @throws NullPointerException {@inheritDoc} * @since 1.8 */ @Override @@ -3606,7 +3601,6 @@ public final class Class implements java.io.Serializable, *

Note that any annotations returned by this method are * declaration annotations. * - * @throws NullPointerException {@inheritDoc} * @since 1.8 */ @Override @@ -3837,6 +3831,7 @@ public final class Class implements java.io.Serializable, * @since 11 */ public boolean isNestmateOf(Class c) { + Objects.requireNonNull(c); if (this == c) { return true; } diff --git a/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java b/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java index 1637d26b571..54000b916e2 100644 --- a/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java +++ b/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java @@ -97,6 +97,8 @@ public class AccessibleObject implements AnnotatedElement { * objects in the array * @throws SecurityException if an element in the array is a constructor for {@code * java.lang.Class} + * @throws NullPointerException if {@code array} or any of its elements is + * {@code null} */ @CallerSensitive public static void setAccessible(AccessibleObject[] array, boolean flag) { diff --git a/src/java.base/share/classes/java/lang/reflect/Array.java b/src/java.base/share/classes/java/lang/reflect/Array.java index 2fbad52c374..4e676c050d7 100644 --- a/src/java.base/share/classes/java/lang/reflect/Array.java +++ b/src/java.base/share/classes/java/lang/reflect/Array.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -98,8 +98,8 @@ class Array { * @param dimensions an array of {@code int} representing the dimensions of * the new array * @return the new array - * @throws NullPointerException if the specified - * {@code componentType} argument is null + * @throws NullPointerException if any of the specified + * {@code componentType} or {@code dimensions} arguments is null * @throws IllegalArgumentException if the specified {@code dimensions} * argument is a zero-dimensional array, if componentType is {@link * Void#TYPE}, or if the number of dimensions of the requested array @@ -117,8 +117,8 @@ class Array { * * @param array the array * @return the length of the array - * @throws IllegalArgumentException if the object argument is not - * an array + * @throws NullPointerException if {@code array} is {@code null} + * @throws IllegalArgumentException if {@code array} is not an array */ @IntrinsicCandidate public static native int getLength(Object array) diff --git a/src/java.base/share/classes/java/lang/reflect/ClassFileFormatVersion.java b/src/java.base/share/classes/java/lang/reflect/ClassFileFormatVersion.java index 4a63dd157f8..16fe000091c 100644 --- a/src/java.base/share/classes/java/lang/reflect/ClassFileFormatVersion.java +++ b/src/java.base/share/classes/java/lang/reflect/ClassFileFormatVersion.java @@ -433,6 +433,7 @@ public enum ClassFileFormatVersion { * ClassFileFormatVersion.valueOf(Runtime.Version.parse("17"))} * * @param rv runtime version to map to a class file format version + * @throws NullPointerException if {@code rv} is {@code null} * @throws IllegalArgumentException if the feature of version * argument is greater than the feature of the platform version. */ diff --git a/src/java.base/share/classes/java/lang/reflect/InaccessibleObjectException.java b/src/java.base/share/classes/java/lang/reflect/InaccessibleObjectException.java index 7bc9ea33b2b..29d6eb13602 100644 --- a/src/java.base/share/classes/java/lang/reflect/InaccessibleObjectException.java +++ b/src/java.base/share/classes/java/lang/reflect/InaccessibleObjectException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ public class InaccessibleObjectException extends RuntimeException { * message. * * @param msg - * The detail message + * The detail message, may be {@code null} */ public InaccessibleObjectException(String msg) { super(msg); diff --git a/src/java.base/share/classes/java/lang/reflect/InvocationTargetException.java b/src/java.base/share/classes/java/lang/reflect/InvocationTargetException.java index a6ef4fa289c..efdca9bcbd1 100644 --- a/src/java.base/share/classes/java/lang/reflect/InvocationTargetException.java +++ b/src/java.base/share/classes/java/lang/reflect/InvocationTargetException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ public class InvocationTargetException extends ReflectiveOperationException { /** * Constructs a InvocationTargetException with a target exception. * - * @param target the target exception + * @param target the target exception, may be {@code null} */ public InvocationTargetException(Throwable target) { super((Throwable)null); // Disallow initCause @@ -73,8 +73,8 @@ public class InvocationTargetException extends ReflectiveOperationException { * Constructs a InvocationTargetException with a target exception * and a detail message. * - * @param target the target exception - * @param s the detail message + * @param target the target exception, may be {@code null} + * @param s the detail message, may be {@code null} */ public InvocationTargetException(Throwable target, String s) { super(s, null); // Disallow initCause diff --git a/src/java.base/share/classes/java/lang/reflect/MalformedParametersException.java b/src/java.base/share/classes/java/lang/reflect/MalformedParametersException.java index ae2da8c9279..fa754be5474 100644 --- a/src/java.base/share/classes/java/lang/reflect/MalformedParametersException.java +++ b/src/java.base/share/classes/java/lang/reflect/MalformedParametersException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,7 @@ public class MalformedParametersException extends RuntimeException { /** * Create a {@code MalformedParametersException}. * - * @param reason The reason for the exception. + * @param reason The reason for the exception, may be {@code null} */ public MalformedParametersException(String reason) { super(reason); diff --git a/src/java.base/share/classes/java/lang/reflect/Proxy.java b/src/java.base/share/classes/java/lang/reflect/Proxy.java index dc512e86590..b811deb863d 100644 --- a/src/java.base/share/classes/java/lang/reflect/Proxy.java +++ b/src/java.base/share/classes/java/lang/reflect/Proxy.java @@ -897,7 +897,8 @@ public class Proxy implements java.io.Serializable { * of interfaces but in a different order will result in two distinct * proxy classes. * - * @param loader the class loader to define the proxy class + * @param loader the class loader to define the proxy class, may be + * {@code null} to represent the bootstrap class loader * @param interfaces the list of interfaces for the proxy class * to implement * @param h the invocation handler to dispatch method invocations to diff --git a/src/java.base/share/classes/java/lang/reflect/UndeclaredThrowableException.java b/src/java.base/share/classes/java/lang/reflect/UndeclaredThrowableException.java index 0b086330de2..25d8affa474 100644 --- a/src/java.base/share/classes/java/lang/reflect/UndeclaredThrowableException.java +++ b/src/java.base/share/classes/java/lang/reflect/UndeclaredThrowableException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,7 @@ public class UndeclaredThrowableException extends RuntimeException { * specified {@code Throwable}. * * @param undeclaredThrowable the undeclared checked exception - * that was thrown + * that was thrown, may be {@code null} */ public UndeclaredThrowableException(Throwable undeclaredThrowable) { super(null, undeclaredThrowable); // Disallow initCause @@ -72,8 +72,8 @@ public class UndeclaredThrowableException extends RuntimeException { * specified {@code Throwable} and a detail message. * * @param undeclaredThrowable the undeclared checked exception - * that was thrown - * @param s the detail message + * that was thrown, may be {@code null} + * @param s the detail message, may be {@code null} */ public UndeclaredThrowableException(Throwable undeclaredThrowable, String s) diff --git a/test/jdk/java/lang/Class/NullBehaviorTest.java b/test/jdk/java/lang/Class/NullBehaviorTest.java new file mode 100644 index 00000000000..a38972a8aaf --- /dev/null +++ b/test/jdk/java/lang/Class/NullBehaviorTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8371953 + * @summary Check null argument behaviors for java.lang.Class APIs. + * @run junit NullBehaviorTest + */ + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class NullBehaviorTest { + @Test + void nullChecks() { + assertThrows(NullPointerException.class, () -> Class.forName(null)); + assertDoesNotThrow(() -> Class.forName("java.lang.Object", false, null)); + assertThrows(NullPointerException.class, () -> Class.forName(null, false, null)); + assertThrows(NullPointerException.class, () -> Class.forName(null, "java.lang.Object")); + assertThrows(NullPointerException.class, () -> Class.forName(Object.class.getModule(), null)); + assertThrows(NullPointerException.class, () -> Class.forPrimitiveName(null)); + assertFalse(Object.class.isInstance(null)); + assertThrows(NullPointerException.class, () -> Object.class.isAssignableFrom(null)); + assertThrows(NullPointerException.class, () -> Object.class.getField(null)); + assertThrows(NullPointerException.class, () -> Object.class.getDeclaredField(null)); + assertThrows(NullPointerException.class, () -> Object.class.getMethod(null)); + assertThrows(NullPointerException.class, () -> Object.class.getDeclaredMethod(null)); + assertDoesNotThrow(() -> Object.class.getMethod("hashCode", (Class[]) null)); + assertDoesNotThrow(() -> Object.class.getDeclaredMethod("hashCode", (Class[]) null)); + assertThrows(NoSuchMethodException.class, () -> Object.class.getMethod("hashCode", new Class[]{null})); + assertThrows(NoSuchMethodException.class, () -> Object.class.getDeclaredMethod("hashCode", new Class[]{null})); + assertDoesNotThrow(() -> Object.class.getConstructor((Class[]) null)); + assertDoesNotThrow(() -> Object.class.getDeclaredConstructor((Class[]) null)); + assertThrows(NoSuchMethodException.class, () -> Object.class.getConstructor(new Class[]{null})); + assertThrows(NoSuchMethodException.class, () -> Object.class.getDeclaredConstructor(new Class[]{null})); + assertThrows(NullPointerException.class, () -> Object.class.getResourceAsStream(null)); + assertThrows(NullPointerException.class, () -> Object.class.getResource(null)); + assertDoesNotThrow(() -> Object.class.cast(null)); + assertThrows(NullPointerException.class, () -> Object.class.asSubclass(null)); + assertThrows(NullPointerException.class, () -> Object.class.isNestmateOf(null)); + assertThrows(NullPointerException.class, () -> int.class.isNestmateOf(null)); + } +} diff --git a/test/jdk/java/lang/reflect/AccessFlag/AccessFlagNullCheckTest.java b/test/jdk/java/lang/reflect/AccessFlag/AccessFlagNullCheckTest.java new file mode 100644 index 00000000000..b847a27df2b --- /dev/null +++ b/test/jdk/java/lang/reflect/AccessFlag/AccessFlagNullCheckTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8371953 + * @summary Null checks for AccessFlag and Location. + * @run junit AccessFlagNullCheckTest + */ + +import java.lang.reflect.AccessFlag; +import java.lang.reflect.ClassFileFormatVersion; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +class AccessFlagNullCheckTest { + @Test + void accessFlagNullChecks() { + assertThrows(NullPointerException.class, () -> AccessFlag.valueOf(null)); + assertThrows(NullPointerException.class, () -> AccessFlag.PUBLIC.locations(null)); + assertThrows(NullPointerException.class, () -> AccessFlag.maskToAccessFlags(0, null)); + assertThrows(NullPointerException.class, () -> AccessFlag.maskToAccessFlags(0, AccessFlag.Location.CLASS, null)); + assertThrows(NullPointerException.class, () -> AccessFlag.maskToAccessFlags(0, null, ClassFileFormatVersion.RELEASE_1)); + } + + @Test + void locationNullChecks() { + assertThrows(NullPointerException.class, () -> AccessFlag.Location.valueOf(null)); + assertThrows(NullPointerException.class, () -> AccessFlag.Location.CLASS.flags(null)); + assertThrows(NullPointerException.class, () -> AccessFlag.Location.CLASS.flagsMask(null)); + } +} diff --git a/test/jdk/java/lang/reflect/AccessibleObject/AccessibleObjectNullCheckTest.java b/test/jdk/java/lang/reflect/AccessibleObject/AccessibleObjectNullCheckTest.java new file mode 100644 index 00000000000..562903b370e --- /dev/null +++ b/test/jdk/java/lang/reflect/AccessibleObject/AccessibleObjectNullCheckTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8371953 + * @summary API null checks for AccessibleObject. + * @run junit AccessibleObjectNullCheckTest + */ + +import java.lang.reflect.AccessibleObject; +import java.util.Objects; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +class AccessibleObjectNullCheckTest { + @Test + void nullChecks() throws ReflectiveOperationException { + assertThrows(NullPointerException.class, () -> AccessibleObject.setAccessible(null, false)); + assertThrows(NullPointerException.class, () -> AccessibleObject.setAccessible(new AccessibleObject[]{ null }, false)); + var accessible = Objects.requireNonNull(Object.class.getMethod("toString")); + assertThrows(IllegalArgumentException.class, () -> accessible.canAccess(null)); + } +} diff --git a/test/jdk/java/lang/reflect/Array/ArrayArgumentCheckTest.java b/test/jdk/java/lang/reflect/Array/ArrayArgumentCheckTest.java new file mode 100644 index 00000000000..a08913716e1 --- /dev/null +++ b/test/jdk/java/lang/reflect/Array/ArrayArgumentCheckTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8371953 + * @summary General argument checks for Array APIs. + * @run junit ArrayArgumentCheckTest + */ + +import java.lang.constant.ConstantDescs; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Array; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class ArrayArgumentCheckTest { + @Test + void newArrayChecks() throws ReflectiveOperationException { + // Single newInstance + assertDoesNotThrow(() -> Array.newInstance(Object.class, 0)); + assertThrows(NullPointerException.class, () -> Array.newInstance(null, 0)); + assertThrows(NegativeArraySizeException.class, () -> Array.newInstance(Object.class, -1)); + assertThrows(IllegalArgumentException.class, () -> Array.newInstance(void.class, 0)); + var object255ArrayType = ConstantDescs.CD_Object.arrayType(255).resolveConstantDesc(MethodHandles.publicLookup()); + assertThrows(IllegalArgumentException.class, () -> Array.newInstance(object255ArrayType, 0)); + // Multi-level newInstance + assertDoesNotThrow(() -> Array.newInstance(Object.class, 0)); + assertThrows(NullPointerException.class, () -> Array.newInstance(null, new int[1])); + assertThrows(NullPointerException.class, () -> Array.newInstance(Object.class, (int[]) null)); + assertThrows(NegativeArraySizeException.class, () -> Array.newInstance(Object.class, new int[]{3, -1, 5})); + assertThrows(IllegalArgumentException.class, () -> Array.newInstance(Object.class)); + var object254ArrayType = ConstantDescs.CD_Object.arrayType(254).resolveConstantDesc(MethodHandles.publicLookup()); + assertThrows(IllegalArgumentException.class, () -> Array.newInstance(object254ArrayType, new int[] {2, 3})); + } + + @Test + void getLengthChecks() { + assertThrows(NullPointerException.class, () -> Array.getLength(null)); + assertThrows(IllegalArgumentException.class, () -> Array.getLength(5)); + } +} diff --git a/test/jdk/java/lang/reflect/ClassFileFormatVersionTest.java b/test/jdk/java/lang/reflect/ClassFileFormatVersionTest.java new file mode 100644 index 00000000000..ffd2ed5ffd3 --- /dev/null +++ b/test/jdk/java/lang/reflect/ClassFileFormatVersionTest.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8371953 + * @summary General tests for ClassFileFormatVersion. + * @run junit ClassFileFormatVersionTest + */ + +import java.lang.reflect.ClassFileFormatVersion; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +class ClassFileFormatVersionTest { + @Test + void argumentChecks() { + assertThrows(NullPointerException.class, () -> ClassFileFormatVersion.valueOf((String) null)); + assertThrows(NullPointerException.class, () -> ClassFileFormatVersion.valueOf((Runtime.Version) null)); + assertThrows(IllegalArgumentException.class, () -> ClassFileFormatVersion.valueOf("Absent")); + var runtimeVersion = Runtime.Version.parse("99999999"); + assertThrows(IllegalArgumentException.class, () -> ClassFileFormatVersion.valueOf(runtimeVersion)); + } +} diff --git a/test/jdk/java/lang/reflect/ExceptionClassesNullCheckTest.java b/test/jdk/java/lang/reflect/ExceptionClassesNullCheckTest.java new file mode 100644 index 00000000000..4b777bacc09 --- /dev/null +++ b/test/jdk/java/lang/reflect/ExceptionClassesNullCheckTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8371953 + * @summary Null arguments for exception classes in java.lang.reflect package. + * @run junit ExceptionClassesNullCheckTest + */ + +import java.lang.reflect.GenericSignatureFormatError; +import java.lang.reflect.InaccessibleObjectException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.MalformedParameterizedTypeException; +import java.lang.reflect.MalformedParametersException; +import java.lang.reflect.UndeclaredThrowableException; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +class ExceptionClassesNullCheckTest { + @Test + void argumentChecks() { + // Add casts to preserve compilation if they add new constructor overloads + assertDoesNotThrow(() -> new GenericSignatureFormatError((String) null)); + assertDoesNotThrow(() -> new InaccessibleObjectException((String) null)); + assertDoesNotThrow(() -> new InvocationTargetException((Throwable) null)); + assertDoesNotThrow(() -> new InvocationTargetException(null, null)); + assertDoesNotThrow(() -> new MalformedParameterizedTypeException((String) null)); + assertDoesNotThrow(() -> new MalformedParametersException((String) null)); + assertDoesNotThrow(() -> new UndeclaredThrowableException((Throwable) null)); + assertDoesNotThrow(() -> new UndeclaredThrowableException(null, null)); + } +} diff --git a/test/jdk/java/lang/reflect/Proxy/ProxyNullCheckTest.java b/test/jdk/java/lang/reflect/Proxy/ProxyNullCheckTest.java new file mode 100644 index 00000000000..f60baba3b3b --- /dev/null +++ b/test/jdk/java/lang/reflect/Proxy/ProxyNullCheckTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8371953 + * @summary Basic API null checks for Proxy. + * @run junit ProxyNullCheckTest + */ + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class ProxyNullCheckTest { + @SuppressWarnings("deprecation") + @Test + void nullChecks() throws ReflectiveOperationException { + InvocationHandler h = (_, _, _) -> null; + // newProxyInstance + assertDoesNotThrow(() -> Proxy.newProxyInstance(null, new Class[0], h)); + assertThrows(NullPointerException.class, () -> Proxy.newProxyInstance(null, null, h)); + assertThrows(NullPointerException.class, () -> Proxy.newProxyInstance(null, new Class[] { null }, h)); + assertThrows(NullPointerException.class, () -> Proxy.newProxyInstance(null, new Class[0], null)); + // getProxyClass + assertDoesNotThrow(() -> Proxy.getProxyClass(null, new Class[0])); + assertThrows(NullPointerException.class, () -> Proxy.getProxyClass(null, (Class[]) null)); + assertThrows(NullPointerException.class, () -> Proxy.getProxyClass(null, new Class[] { null })); + // isProxyClass + assertFalse(Proxy.isProxyClass(Object.class)); + assertThrows(NullPointerException.class, () -> Proxy.isProxyClass(null)); + // getInvocationHandler + assertThrows(NullPointerException.class, () -> Proxy.getInvocationHandler(null)); + assertThrows(IllegalArgumentException.class, () -> Proxy.getInvocationHandler(42)); + } +}