1 /*
2 * Copyright (c) 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.internal.reflect;
27
28 import java.lang.reflect.AccessFlag;
29 import java.lang.reflect.ClassFileFormatVersion;
30 import java.util.Collections;
31 import java.util.EnumSet;
32 import java.util.Objects;
33 import java.util.Set;
34
35 import jdk.internal.vm.annotation.Stable;
36
37 import static java.lang.classfile.ClassFile.*;
38 import static java.lang.reflect.AccessFlag.*;
39
40 /// Support for [AccessFlag] reflection for the preview VM features supported by
41 /// the current Java SE release.
42 ///
43 /// These preview features appear when VM is running with --enable-preview, or
44 /// in x.65535 class files. Tools must handle x.65535 class files when their
45 /// own VM is not running in preview, so this class may be used by tools when
46 /// preview features are not enabled,
47 public final class PreviewAccessFlags {
48
49 public static final @Stable AccessFlag[]
50 CLASS_PREVIEW_FLAGS = AccessFlagSet.createDefinition(PUBLIC, FINAL, IDENTITY, INTERFACE, ABSTRACT, SYNTHETIC, ANNOTATION, ENUM, MODULE),
51 FIELD_PREVIEW_FLAGS = AccessFlagSet.createDefinition(PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, VOLATILE, TRANSIENT, SYNTHETIC, ENUM, STRICT_INIT),
52 INNER_CLASS_PREVIEW_FLAGS = AccessFlagSet.createDefinition(PUBLIC, PRIVATE, PROTECTED, IDENTITY, STATIC, FINAL, INTERFACE, ABSTRACT, SYNTHETIC, ANNOTATION, ENUM);
53
54 /// Preview variant of [Location#flagsMask()].
55 public static int flagsMask(Location location) {
56 return switch (location) {
57 case FIELD -> ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED |
58 ACC_STATIC | ACC_FINAL | ACC_VOLATILE |
59 ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM | ACC_STRICT_INIT; // strict init
60 case INNER_CLASS -> ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_IDENTITY |
61 ACC_STATIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT |
62 ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM; // identity
63 default -> location.flagsMask();
64 };
65 }
66
67 /// Preview variant of [AccessFlag#locations()].
68 public static Set<Location> locations(AccessFlag flag) {
69 return switch (flag) {
70 case SUPER -> Set.of();
71 case IDENTITY -> Set.of(Location.CLASS, Location.INNER_CLASS);
72 case STRICT_INIT -> Set.of(Location.FIELD);
73 default -> flag.locations();
74 };
75 }
76
77 /// Preview variant of [AccessFlagSet#findDefinition].
78 public static AccessFlag[] findDefinition(Location location) {
79 return switch (location) {
80 case CLASS -> CLASS_PREVIEW_FLAGS;
81 case FIELD -> FIELD_PREVIEW_FLAGS;
82 case INNER_CLASS -> INNER_CLASS_PREVIEW_FLAGS;
83 default -> AccessFlagSet.findDefinition(location);
84 };
85 }
86
87 /// Preview variant of [AccessFlag#maskToAccessFlags].
88 /// The method body should be in parity.
89 /// @throws IllegalArgumentException if there is unrecognized flag bit
90 public static Set<AccessFlag> maskToAccessFlags(int mask, Location location) {
91 var definition = findDefinition(location); // null checks location
92 int unmatchedMask = mask & (~flagsMask(location));
93 if (unmatchedMask != 0) {
94 throw new IllegalArgumentException("Unmatched bit position 0x" +
95 Integer.toHexString(unmatchedMask) +
96 " for location " + location +
97 " for preview class files");
98 }
99 return AccessFlagSet.ofValidated(definition, mask);
100 }
101
102 private PreviewAccessFlags() {
103 }
104 }