Skip to content

Commit 6c255dc

Browse files
Implement sealed class support
1 parent 6cae92d commit 6c255dc

File tree

5 files changed

+165
-3
lines changed

5 files changed

+165
-3
lines changed

compiler/src/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/NumUtil.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -105,6 +105,11 @@ public static boolean is32bit(long x) {
105105
return -0x80000000L <= x && x < 0x80000000L;
106106
}
107107

108+
public static byte safeToUByte(int v) {
109+
assert isUByte(v);
110+
return (byte) v;
111+
}
112+
108113
public static byte safeToByte(int v) {
109114
assert isByte(v);
110115
return (byte) v;
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (c) 2021, 2021, 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+
package com.oracle.svm.core.jdk17;
26+
27+
// Checkstyle: allow reflection
28+
29+
import com.oracle.svm.core.annotate.AutomaticFeature;
30+
import com.oracle.svm.core.jdk.SealedClassSupport;
31+
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
32+
import org.graalvm.nativeimage.ImageSingletons;
33+
import org.graalvm.nativeimage.hosted.Feature;
34+
35+
final class SealedClassSupportJDK17OrLater extends SealedClassSupport {
36+
37+
@Override
38+
public Class<?>[] getPermittedSubclasses(Class<?> clazz) {
39+
return clazz.getPermittedSubclasses();
40+
}
41+
}
42+
43+
@AutomaticFeature
44+
final class SealedClassFeatureJDK17OrLater implements Feature {
45+
@Override
46+
public boolean isInConfiguration(IsInConfigurationAccess access) {
47+
return JavaVersionUtil.JAVA_SPEC >= 17;
48+
}
49+
50+
@Override
51+
public void afterRegistration(AfterRegistrationAccess access) {
52+
ImageSingletons.add(SealedClassSupport.class, new SealedClassSupportJDK17OrLater());
53+
}
54+
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -276,6 +276,12 @@ public final class DynamicHub implements JavaKind.FormatWithToString, AnnotatedE
276276
*/
277277
private Object annotationsEncoding;
278278

279+
/**
280+
* Permitted subclasses for this class. This value is created during the image build by caching
281+
* Class.getPermittedSubclasses() value for usage in {@link DynamicHub#getPermittedSubclasses()}
282+
*/
283+
private Class<?>[] permittedSubclasses;
284+
279285
/**
280286
* Metadata for running class initializers at run time. Refers to a singleton marker object for
281287
* classes/interfaces already initialized during image generation, i.e., this field is never
@@ -359,7 +365,7 @@ public DynamicHub(Class<?> hostedJavaClass, String name, HubType hubType, Refere
359365
this.classLoader = PredefinedClassesSupport.isPredefined(hostedJavaClass) ? NO_CLASS_LOADER : classLoader;
360366
this.nestHost = nestHost;
361367

362-
this.flags = NumUtil.safeToByte(makeFlag(IS_PRIMITIVE_FLAG_BIT, hostedJavaClass.isPrimitive()) |
368+
this.flags = NumUtil.safeToUByte(makeFlag(IS_PRIMITIVE_FLAG_BIT, hostedJavaClass.isPrimitive()) |
363369
makeFlag(IS_INTERFACE_FLAG_BIT, hostedJavaClass.isInterface()) |
364370
makeFlag(IS_HIDDED_FLAG_BIT, isHidden) |
365371
makeFlag(IS_RECORD_FLAG_BIT, isRecord) |
@@ -459,6 +465,11 @@ public Object getAnnotationsEncoding() {
459465
return annotationsEncoding;
460466
}
461467

468+
@Platforms(Platform.HOSTED_ONLY.class)
469+
public void setPermittedSubclasses(Class<?>[] permittedSubclasses) {
470+
this.permittedSubclasses = permittedSubclasses;
471+
}
472+
462473
@Platforms(Platform.HOSTED_ONLY.class)
463474
public boolean shouldInitEnumConstants() {
464475
return enumConstantsReference == null;
@@ -804,6 +815,10 @@ public boolean isRecord() {
804815
return isFlagSet(IS_RECORD_FLAG_BIT);
805816
}
806817

818+
@KeepOriginal
819+
@TargetElement(onlyWith = JDK17OrLater.class)
820+
public native boolean isSealed();
821+
807822
@Substitute
808823
private boolean isLocalClass() {
809824
return booleanOrError(isLocalClass);
@@ -1216,6 +1231,14 @@ private Target_java_lang_reflect_RecordComponent[] getRecordComponents0() {
12161231
return (Target_java_lang_reflect_RecordComponent[]) result;
12171232
}
12181233

1234+
@Substitute
1235+
@TargetElement(onlyWith = JDK17OrLater.class)
1236+
private Class<?>[] getPermittedSubclasses() {
1237+
/* Original implementation depends on several private methods that aren't
1238+
* needed here, since we are only returning the cached value. */
1239+
return permittedSubclasses;
1240+
}
1241+
12191242
@Substitute
12201243
@TargetElement(name = "checkMemberAccess", onlyWith = JDK8OrEarlier.class)
12211244
@SuppressWarnings("unused")
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright (c) 2021, 2021, 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+
package com.oracle.svm.core.jdk;
26+
27+
// Checkstyle: allow reflection
28+
29+
import com.oracle.svm.core.annotate.AutomaticFeature;
30+
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
31+
import org.graalvm.nativeimage.ImageSingletons;
32+
import org.graalvm.nativeimage.Platform;
33+
import org.graalvm.nativeimage.Platforms;
34+
import org.graalvm.nativeimage.hosted.Feature;
35+
36+
/**
37+
* Abstracts the information about sealed classes, which are not available in Java 11 and Java 8.
38+
* This class provides all information about sealed classes without exposing any JDK types and
39+
* methods that are not yet present in the old JDKs.
40+
*/
41+
@Platforms(Platform.HOSTED_ONLY.class)
42+
public abstract class SealedClassSupport {
43+
44+
public static SealedClassSupport singleton() {
45+
return ImageSingletons.lookup(SealedClassSupport.class);
46+
}
47+
48+
/** Same as {@code Class.permittedSubclasses()}. */
49+
public abstract Class<?>[] getPermittedSubclasses(Class<?> clazz);
50+
}
51+
52+
/**
53+
* Placeholder implementation for JDK versions that do not have sealed classes.
54+
*/
55+
final class SealedClassSupportJDK11OrEarlier extends SealedClassSupport {
56+
57+
@Override
58+
public Class<?>[] getPermittedSubclasses(Class<?> clazz) {
59+
return null;
60+
}
61+
}
62+
63+
@AutomaticFeature
64+
final class SealedClassFeatureBeforeJDK17 implements Feature {
65+
@Override
66+
public boolean isInConfiguration(IsInConfigurationAccess access) {
67+
return JavaVersionUtil.JAVA_SPEC <= 11;
68+
}
69+
70+
@Override
71+
public void afterRegistration(AfterRegistrationAccess access) {
72+
ImageSingletons.add(SealedClassSupport.class, new SealedClassSupportJDK11OrEarlier());
73+
}
74+
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import com.oracle.svm.core.hub.AnnotatedSuperInfo;
4444
import com.oracle.svm.core.hub.DynamicHub;
4545
import com.oracle.svm.core.hub.GenericInfo;
46+
import com.oracle.svm.core.jdk.SealedClassSupport;
4647
import com.oracle.svm.core.meta.SubstrateObjectConstant;
4748
import com.oracle.svm.hosted.SVMHost;
4849

@@ -103,6 +104,11 @@ public void initializeMetaData(AnalysisType type) {
103104
fillInterfaces(type, hub);
104105
}
105106

107+
/*
108+
* Support for permitted subclasses of a sealed class.
109+
*/
110+
hub.setPermittedSubclasses(SealedClassSupport.singleton().getPermittedSubclasses(type.getJavaClass()));
111+
106112
/*
107113
* Support for Java annotations.
108114
*/

0 commit comments

Comments
 (0)