1 /* 2 * Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import jdk.internal.misc.PreviewFeatures; 25 26 import java.lang.classfile.ClassFile; 27 import java.lang.reflect.Modifier; 28 import java.lang.annotation.*; 29 30 /* 31 * @test 32 * @bug 8296743 33 * @modules java.base/jdk.internal.misc 34 * @summary Verify array classes and primitives have expected modifiers 35 * @run main/othervm TestPrimitiveAndArrayModifiers 36 * @run main/othervm --enable-preview TestPrimitiveAndArrayModifiers 37 */ 38 @ExpectedModifiers(Modifier.PUBLIC | Modifier.FINAL | Modifier.ABSTRACT) 39 public class TestPrimitiveAndArrayModifiers { 40 41 /* 42 * Relevant excerpt of the Class.getModifiers() specification: 43 * <p> If the underlying class is an array class: 44 * <ul> 45 * <li> its {@code public}, {@code private} and {@code protected} 46 * modifiers are the same as those of its component type 47 * <li> its {@code final} and {@code abstract} modifiers are always 48 * {@code true} 49 * <li> its interface modifier is always {@code false}, even when 50 * the component type is an interface 51 * </ul> 52 */ 53 54 public static void main(String... args) throws Exception { 55 testPrimitives(); 56 testArrays(); 57 } 58 59 private static void testArrays() { 60 Class<?>[] testCases = { 61 TestPrimitiveAndArrayModifiers.class, 62 63 PackagePrivateClass.class, 64 ProtectedClass.class, 65 PrivateClass.class, 66 67 PublicInterface.class, 68 PackagePrivateInterface.class, 69 ProtectedInterface.class, 70 PrivateInterface.class, 71 }; 72 73 for(var testCase : testCases) { 74 int expectedModifiers = 75 testCase.getAnnotation(ExpectedModifiers.class).value(); 76 if (PreviewFeatures.isEnabled()) { 77 // All arrays under preview also have IDENTITY 78 expectedModifiers |= ClassFile.ACC_IDENTITY; 79 } 80 Class<?> arrayClass = testCase.arrayType(); 81 int actualModifiers = arrayClass.getModifiers(); 82 if (expectedModifiers != actualModifiers) { 83 throw new RuntimeException("Expected " + Modifier.toString(expectedModifiers) + 84 " on " + testCase.getCanonicalName() + 85 ", but got " + Modifier.toString(actualModifiers)); 86 } 87 } 88 } 89 90 @ExpectedModifiers(Modifier.FINAL | Modifier.ABSTRACT) 91 class PackagePrivateClass {} 92 93 @ExpectedModifiers(Modifier.FINAL | Modifier.ABSTRACT | Modifier.PROTECTED) 94 protected class ProtectedClass {} 95 96 @ExpectedModifiers(Modifier.FINAL | Modifier.ABSTRACT | Modifier.PRIVATE) 97 private class PrivateClass {} 98 99 @ExpectedModifiers(Modifier.FINAL | Modifier.ABSTRACT | Modifier.PUBLIC) 100 public interface PublicInterface {} 101 102 @ExpectedModifiers(Modifier.FINAL | Modifier.ABSTRACT) 103 interface PackagePrivateInterface {} 104 105 @ExpectedModifiers(Modifier.FINAL | Modifier.ABSTRACT | Modifier.PROTECTED) 106 protected interface ProtectedInterface {} 107 108 @ExpectedModifiers(Modifier.FINAL | Modifier.ABSTRACT | Modifier.PRIVATE) 109 private interface PrivateInterface {} 110 111 /* 112 * Relevant excerpt of the Class.getModifiers() specification: 113 * 114 * If this {@code Class} object represents a primitive type or 115 * void, its {@code public}, {@code abstract}, and {@code final} 116 * modifiers are always {@code true}. 117 */ 118 private static void testPrimitives() { 119 Class<?>[] testCases = { 120 void.class, 121 boolean.class, 122 byte.class, 123 short.class, 124 char.class, 125 int.class, 126 float.class, 127 long.class, 128 double.class, 129 }; 130 131 for(var testCase : testCases) { 132 int actualModifiers = testCase.getModifiers(); 133 if ((Modifier.PUBLIC | Modifier.ABSTRACT | Modifier.FINAL) != 134 actualModifiers) { 135 throw new RuntimeException("Bad modifiers " + 136 Modifier.toString(actualModifiers) + 137 " on primitive type " + testCase); 138 } 139 } 140 } 141 } 142 143 @Retention(RetentionPolicy.RUNTIME) 144 @interface ExpectedModifiers { 145 int value() default 0; 146 } --- EOF ---