Skip to content

Commit fb29770

Browse files
author
Paul Sandoz
committed
8287186: JDK modules participating in preview
Reviewed-by: alanb, jlahoda
1 parent 0530f4e commit fb29770

File tree

12 files changed

+83
-75
lines changed

12 files changed

+83
-75
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) 2022, 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 jdk.internal.javac;
26+
27+
import java.lang.annotation.ElementType;
28+
import java.lang.annotation.Retention;
29+
import java.lang.annotation.RetentionPolicy;
30+
import java.lang.annotation.Target;
31+
32+
/**
33+
* Indicates, when declared on a module declaration, that the module participates
34+
* in preview features and therefore does not need to be compiled with "--enable-preview".
35+
*/
36+
@Target(ElementType.MODULE)
37+
@Retention(RetentionPolicy.CLASS)
38+
public @interface ParticipatesInPreview {
39+
}

src/java.base/share/classes/module-info.java

+8
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,17 @@
141141
jdk.compiler;
142142
exports com.sun.security.ntlm to
143143
java.security.sasl;
144+
// Note: all modules in the exported list participate in preview features
145+
// and therefore if they use preview features they do not need to be
146+
// compiled with "--enable-preview".
147+
// It is recommended for any modules that do participate that their
148+
// module declaration be annotated with jdk.internal.javac.ParticipatesInPreview
144149
exports jdk.internal.javac to
145150
java.compiler,
151+
java.management, // participates in preview features
146152
jdk.compiler,
153+
jdk.incubator.concurrent, // participates in preview features
154+
jdk.incubator.vector, // participates in preview features
147155
jdk.jdi,
148156
jdk.jfr,
149157
jdk.jshell,

src/java.management/share/classes/java/lang/management/ThreadInfo.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
import javax.management.openmbean.CompositeData;
3030
import sun.management.ManagementFactoryHelper;
3131
import sun.management.ThreadInfoCompositeData;
32-
import sun.management.Util;
33-
import static java.lang.Thread.State.*;
3432

3533
/**
3634
* Thread information. {@code ThreadInfo} contains the information
@@ -226,7 +224,7 @@ private void initialize(Thread t, int state, Object lockObj, Thread lockOwner,
226224
StackTraceElement[] stackTrace,
227225
MonitorInfo[] lockedMonitors,
228226
LockInfo[] lockedSynchronizers) {
229-
this.virtual = Util.isVirtual(t);
227+
this.virtual = t.isVirtual();
230228
this.threadId = t.threadId();
231229
this.threadName = t.getName();
232230
this.threadState = ManagementFactoryHelper.toThreadState(state);

src/java.management/share/classes/module-info.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2022, 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
@@ -23,6 +23,8 @@
2323
* questions.
2424
*/
2525

26+
import jdk.internal.javac.ParticipatesInPreview;
27+
2628
/**
2729
* Defines the Java Management Extensions (JMX) API.
2830
* <P>
@@ -35,6 +37,7 @@
3537
* @moduleGraph
3638
* @since 9
3739
*/
40+
@ParticipatesInPreview
3841
module java.management {
3942

4043
exports java.lang.management;

src/java.management/share/classes/sun/management/ThreadImpl.java

+6-7
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import java.util.stream.Stream;
3232
import javax.management.ObjectName;
3333
import java.util.Objects;
34-
import sun.management.Util;
3534

3635
/**
3736
* Implementation for java.lang.management.ThreadMXBean as well as providing the
@@ -222,7 +221,7 @@ public void setThreadContentionMonitoringEnabled(boolean enable) {
222221

223222
private boolean verifyCurrentThreadCpuTime() {
224223
// check if Thread CPU time measurement is supported.
225-
if (Util.isVirtual(Thread.currentThread())) {
224+
if (Thread.currentThread().isVirtual()) {
226225
throw new UnsupportedOperationException("Not supported by virtual threads");
227226
}
228227
if (!isCurrentThreadCpuTimeSupported()) {
@@ -284,7 +283,7 @@ protected long[] getThreadCpuTime(long[] ids) {
284283
long id = ids[0];
285284
Thread thread = Thread.currentThread();
286285
if (id == thread.threadId()) {
287-
if (Util.isVirtual(thread)) {
286+
if (thread.isVirtual()) {
288287
times[0] = -1;
289288
} else {
290289
times[0] = getThreadTotalCpuTime0(0);
@@ -327,7 +326,7 @@ protected long[] getThreadUserTime(long[] ids) {
327326
long id = ids[0];
328327
Thread thread = Thread.currentThread();
329328
if (id == thread.threadId()) {
330-
if (Util.isVirtual(thread)) {
329+
if (thread.isVirtual()) {
331330
times[0] = -1;
332331
} else {
333332
times[0] = getThreadUserCpuTime0(0);
@@ -361,7 +360,7 @@ public void setThreadCpuTimeEnabled(boolean enable) {
361360
}
362361

363362
protected long getCurrentThreadAllocatedBytes() {
364-
if (isThreadAllocatedMemoryEnabled() && !Util.isVirtual(Thread.currentThread())) {
363+
if (isThreadAllocatedMemoryEnabled() && !Thread.currentThread().isVirtual()) {
365364
return getThreadAllocatedMemory0(0);
366365
}
367366
return -1;
@@ -377,7 +376,7 @@ protected long getThreadAllocatedBytes(long id) {
377376
if (verified) {
378377
Thread thread = Thread.currentThread();
379378
if (id == thread.threadId()) {
380-
if (Util.isVirtual(thread)) {
379+
if (thread.isVirtual()) {
381380
return -1L;
382381
} else {
383382
return getThreadAllocatedMemory0(0);
@@ -577,7 +576,7 @@ public ObjectName getObjectName() {
577576
*/
578577
private static long[] platformThreadIds(Thread[] threads) {
579578
return Stream.of(threads)
580-
.filter(t -> !Util.isVirtual(t))
579+
.filter(t -> !t.isVirtual())
581580
.mapToLong(Thread::threadId)
582581
.toArray();
583582
}

src/java.management/share/classes/sun/management/Util.java

-26
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
package sun.management;
2727

28-
import java.lang.reflect.Method;
2928
import java.lang.reflect.Field;
3029
import java.lang.management.ManagementPermission;
3130
import java.lang.management.ThreadInfo;
@@ -88,20 +87,6 @@ public static void checkControlAccess() throws SecurityException {
8887
checkAccess(controlPermission);
8988
}
9089

91-
/**
92-
* Returns true if the given Thread is a virtual thread.
93-
*
94-
* @implNote This method uses reflection because Thread::isVirtual is a preview API
95-
* and the java.management module cannot be compiled with --enable-preview.
96-
*/
97-
public static boolean isVirtual(Thread thread) {
98-
try {
99-
return (boolean) THREAD_IS_VIRTUAL.invoke(thread);
100-
} catch (Exception e) {
101-
throw new InternalError(e);
102-
}
103-
}
104-
10590
/**
10691
* Returns true if the given ThreadInfo is for a virtual thread.
10792
*/
@@ -113,16 +98,6 @@ public static boolean isVirtual(ThreadInfo threadInfo) {
11398
}
11499
}
115100

116-
@SuppressWarnings("removal")
117-
private static Method threadIsVirtual() {
118-
PrivilegedExceptionAction<Method> pa = () -> Thread.class.getMethod("isVirtual");
119-
try {
120-
return AccessController.doPrivileged(pa);
121-
} catch (PrivilegedActionException e) {
122-
throw new InternalError(e);
123-
}
124-
}
125-
126101
@SuppressWarnings("removal")
127102
private static Field threadInfoVirtual() {
128103
PrivilegedExceptionAction<Field> pa = () -> {
@@ -137,6 +112,5 @@ private static Field threadInfoVirtual() {
137112
}
138113
}
139114

140-
private static final Method THREAD_IS_VIRTUAL = threadIsVirtual();
141115
private static final Field THREADINFO_VIRTUAL = threadInfoVirtual();
142116
}

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java

+12-5
Original file line numberDiff line numberDiff line change
@@ -124,15 +124,22 @@ private Map<Integer, Source> initMajorVersionToSourceMap() {
124124
* Returns true if {@code s} is deemed to participate in the preview of {@code previewSymbol}, and
125125
* therefore no warnings or errors will be produced.
126126
*
127+
* @parem syms the symbol table
127128
* @param s the symbol depending on the preview symbol
128129
* @param previewSymbol the preview symbol marked with @Preview
129130
* @return true if {@code s} is participating in the preview of {@code previewSymbol}
130131
*/
131-
public boolean participatesInPreview(Symbol s, Symbol previewSymbol) {
132-
// Hardcode the incubating vector API module for now
133-
// Will generalize with an annotation, @PreviewParticipating say, later
134-
return previewSymbol.packge().modle == s.packge().modle ||
135-
s.packge().modle.name == names.jdk_incubator_vector;
132+
public boolean participatesInPreview(Symtab syms, Symbol s, Symbol previewSymbol) {
133+
// All symbols in the same module as the preview symbol participate in the preview API
134+
if (previewSymbol.packge().modle == s.packge().modle) {
135+
return true;
136+
}
137+
138+
// If java.base's jdk.internal.javac package is exported to s's module then
139+
// s participates in the preview API
140+
return syms.java_base.exports.stream()
141+
.filter(ed -> ed.packge.fullname == names.jdk_internal_javac)
142+
.anyMatch(ed -> ed.modules.contains(s.packge().modle));
136143
}
137144

138145
/**

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -3600,7 +3600,7 @@ void checkProfile(final DiagnosticPosition pos, final Symbol s) {
36003600
}
36013601

36023602
void checkPreview(DiagnosticPosition pos, Symbol other, Symbol s) {
3603-
if ((s.flags() & PREVIEW_API) != 0 && !preview.participatesInPreview(other, s)) {
3603+
if ((s.flags() & PREVIEW_API) != 0 && !preview.participatesInPreview(syms, other, s)) {
36043604
if ((s.flags() & PREVIEW_REFLECTIVE) == 0) {
36053605
if (!preview.isEnabled()) {
36063606
log.error(pos, Errors.IsPreview(s));

src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,11 @@ public static Names instance(Context context) {
120120
// package names
121121
public final Name java;
122122
public final Name java_lang;
123+
public final Name jdk_internal_javac;
123124

124125
// module names
125126
public final Name java_base;
126127
public final Name jdk_unsupported;
127-
public final Name jdk_incubator_vector;
128128

129129
// attribute names
130130
public final Name Annotation;
@@ -302,11 +302,11 @@ public Names(Context context) {
302302
// package names
303303
java = fromString("java");
304304
java_lang = fromString("java.lang");
305+
jdk_internal_javac = fromString("jdk.internal.javac");
305306

306307
// module names
307308
java_base = fromString("java.base");
308309
jdk_unsupported = fromString("jdk.unsupported");
309-
jdk_incubator_vector = fromString("jdk.incubator.vector");
310310

311311
// attribute names
312312
Annotation = fromString("Annotation");

src/jdk.incubator.concurrent/share/classes/jdk/incubator/concurrent/StructuredTaskScope.java

+3-29
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
import java.lang.invoke.MethodHandles;
2828
import java.lang.invoke.VarHandle;
29-
import java.lang.reflect.Method;
3029
import java.security.AccessController;
3130
import java.security.PrivilegedAction;
3231
import java.time.Duration;
@@ -300,7 +299,7 @@ public StructuredTaskScope(String name, ThreadFactory factory) {
300299
*/
301300
public StructuredTaskScope() {
302301
PreviewFeatures.ensureEnabled();
303-
this.factory = FactoryHolder.VIRTUAL_THREAD_FACTORY;
302+
this.factory = Thread.ofVirtual().factory();
304303
this.flock = ThreadFlock.open(null);
305304
}
306305

@@ -839,7 +838,7 @@ public ShutdownOnSuccess(String name, ThreadFactory factory) {
839838
* name of {@code null} and a thread factory that creates virtual threads.
840839
*/
841840
public ShutdownOnSuccess() {
842-
super(null, FactoryHolder.VIRTUAL_THREAD_FACTORY);
841+
super(null, Thread.ofVirtual().factory());
843842
}
844843

845844
/**
@@ -1015,7 +1014,7 @@ public ShutdownOnFailure(String name, ThreadFactory factory) {
10151014
* name of {@code null} and a thread factory that creates virtual threads.
10161015
*/
10171016
public ShutdownOnFailure() {
1018-
super(null, FactoryHolder.VIRTUAL_THREAD_FACTORY);
1017+
super(null, Thread.ofVirtual().factory());
10191018
}
10201019

10211020
/**
@@ -1161,29 +1160,4 @@ void throwIfFailed(Function<Throwable, ? extends X> esf) throws X {
11611160
}
11621161
}
11631162
}
1164-
1165-
/**
1166-
* Holder class for the virtual thread factory. It uses reflection to allow
1167-
* this class be compiled in an incubator module without also enabling preview
1168-
* features.
1169-
*/
1170-
private static class FactoryHolder {
1171-
static final ThreadFactory VIRTUAL_THREAD_FACTORY = virtualThreadFactory();
1172-
1173-
@SuppressWarnings("removal")
1174-
private static ThreadFactory virtualThreadFactory() {
1175-
PrivilegedAction<ThreadFactory> pa = () -> {
1176-
try {
1177-
Method ofVirtualMethod = Thread.class.getDeclaredMethod("ofVirtual");
1178-
Object virtualThreadBuilder = ofVirtualMethod.invoke(null);
1179-
Class<?> ofVirtualClass = Class.forName("java.lang.Thread$Builder$OfVirtual");
1180-
Method factoryMethod = ofVirtualClass.getMethod("factory");
1181-
return (ThreadFactory) factoryMethod.invoke(virtualThreadBuilder);
1182-
} catch (Exception e) {
1183-
throw new InternalError(e);
1184-
}
1185-
};
1186-
return AccessController.doPrivileged(pa);
1187-
}
1188-
}
11891163
}

src/jdk.incubator.concurrent/share/classes/module-info.java

+3
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,15 @@
2323
* questions.
2424
*/
2525

26+
import jdk.internal.javac.ParticipatesInPreview;
27+
2628
/**
2729
* Defines non-final APIs for concurrent programming.
2830
* {@Incubating}
2931
*
3032
* @moduleGraph
3133
*/
34+
@ParticipatesInPreview
3235
module jdk.incubator.concurrent {
3336
exports jdk.incubator.concurrent;
3437
}

src/jdk.incubator.vector/share/classes/module-info.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2022, 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
@@ -23,6 +23,8 @@
2323
* questions.
2424
*/
2525

26+
import jdk.internal.javac.ParticipatesInPreview;
27+
2628
/**
2729
* Defines an API for expressing computations that can be reliably compiled
2830
* at runtime into SIMD instructions, such as AVX instructions on x64, and
@@ -31,6 +33,7 @@
3133
*
3234
* @moduleGraph
3335
*/
36+
@ParticipatesInPreview
3437
module jdk.incubator.vector {
3538
exports jdk.incubator.vector;
3639
}

0 commit comments

Comments
 (0)