Skip to content

Commit a741e29

Browse files
committed
8379284: Avoid the need to keep obsolete preview feature constants until bootstrap JDK is upgraded
Reviewed-by: liach, erikj, jpai, vromero
1 parent 5e8bba3 commit a741e29

3 files changed

Lines changed: 109 additions & 32 deletions

File tree

make/CompileInterimLangtools.gmk

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
2+
# Copyright (c) 2014, 2026, 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
@@ -68,17 +68,19 @@ java.compiler.interim_EXTRA_FILES := \
6868
TARGETS += $(BUILDTOOLS_OUTPUTDIR)/gensrc/java.compiler.interim/javax/tools/ToolProvider.java
6969

7070
################################################################################
71-
# Use the up-to-date PreviewFeature.java and NoPreview.java from the current
72-
# sources, instead of the versions from the boot JDK, as javac may be referring
73-
# to constants from the up-to-date versions.
74-
75-
$(eval $(call SetupCopyFiles, COPY_PREVIEW_FEATURES, \
76-
FILES := $(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java \
77-
$(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/NoPreview.java, \
78-
DEST := $(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/javac/, \
79-
))
71+
# Create a hybrid PreviewFeature.java that combines constants
72+
# from the current sources, as those can be used in javac APIs, and from the
73+
# bootstrap JDK, as those can be used from bootstrap JDK classfiles.
74+
75+
$(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/javac/PreviewFeature.java: \
76+
$(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java
77+
$(call LogInfo, Generating $@)
78+
$(JAVA) $(TOPDIR)/make/langtools/tools/previewfeature/SetupPreviewFeature.java \
79+
$(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java \
80+
$@
81+
8082

81-
TARGETS += $(COPY_PREVIEW_FEATURES)
83+
TARGETS += $(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/javac/PreviewFeature.java
8284

8385
################################################################################
8486
# Setup the rules to build interim langtools, which is compiled by the boot
@@ -123,7 +125,8 @@ define SetupInterimModule
123125
$1_DEPS_INTERIM := $$(addsuffix .interim, $$(filter \
124126
$$(INTERIM_LANGTOOLS_BASE_MODULES), $$(call FindTransitiveDepsForModule, $1)))
125127

126-
$$(BUILD_$1.interim): $$(foreach d, $$($1_DEPS_INTERIM), $$(BUILD_$$d)) $(COPY_PREVIEW_FEATURES)
128+
$$(BUILD_$1.interim): $$(foreach d, $$($1_DEPS_INTERIM), $$(BUILD_$$d)) \
129+
$(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/javac/PreviewFeature.java
127130

128131
TARGETS += $$(BUILD_$1.interim)
129132
endef
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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+
package previewfeature;
26+
27+
import com.sun.source.util.JavacTask;
28+
import com.sun.source.util.Trees;
29+
import java.io.StringWriter;
30+
import java.lang.reflect.Field;
31+
import java.nio.file.Files;
32+
import java.nio.file.Path;
33+
import java.util.HashSet;
34+
import java.util.Set;
35+
import java.util.stream.Collectors;
36+
import javax.lang.model.element.ElementKind;
37+
import javax.tools.ToolProvider;
38+
39+
/* Construct a hybrid PreviewFeature.Feature enum that includes constants both
40+
* from the current JDK sources (so that they can be used in the javac API sources),
41+
* and from the bootstrap JDK (so that they can be used in the bootstrap classfiles).
42+
*
43+
* This hybrid enum is only used for the interim javac.
44+
*/
45+
public class SetupPreviewFeature {
46+
public static void main(String... args) throws Exception {
47+
Class<?> runtimeFeature = Class.forName("jdk.internal.javac.PreviewFeature$Feature");
48+
Set<String> constantsToAdd = new HashSet<>();
49+
for (Field runtimeField : runtimeFeature.getDeclaredFields()) {
50+
if (runtimeField.isEnumConstant()) {
51+
constantsToAdd.add(runtimeField.getName());
52+
}
53+
}
54+
var dummy = new StringWriter();
55+
var compiler = ToolProvider.getSystemJavaCompiler();
56+
var source = Path.of(args[0]);
57+
try (var fm = compiler.getStandardFileManager(null, null, null)) {
58+
JavacTask task =
59+
(JavacTask) compiler.getTask(dummy, null, null, null, null, fm.getJavaFileObjects(source));
60+
task.analyze();
61+
var sourceFeature = task.getElements()
62+
.getTypeElement("jdk.internal.javac.PreviewFeature.Feature");
63+
int insertPosition = -1;
64+
for (var el : sourceFeature.getEnclosedElements()) {
65+
if (el.getKind() == ElementKind.ENUM_CONSTANT) {
66+
constantsToAdd.remove(el.getSimpleName().toString());
67+
if (insertPosition == (-1)) {
68+
var trees = Trees.instance(task);
69+
var elPath = trees.getPath(el);
70+
insertPosition = (int) trees.getSourcePositions()
71+
.getStartPosition(elPath.getCompilationUnit(),
72+
elPath.getLeaf());
73+
}
74+
}
75+
}
76+
var target = Path.of(args[1]);
77+
Files.createDirectories(target.getParent());
78+
if (constantsToAdd.isEmpty()) {
79+
Files.copy(source, target);
80+
} else {
81+
String sourceCode = Files.readString(source);
82+
try (var out = Files.newBufferedWriter(target)) {
83+
out.write(sourceCode, 0, insertPosition);
84+
out.write(constantsToAdd.stream()
85+
.collect(Collectors.joining(", ",
86+
"/*compatibility constants:*/ ",
87+
",\n")));
88+
out.write(sourceCode, insertPosition, sourceCode.length() - insertPosition);
89+
}
90+
}
91+
}
92+
}
93+
}

src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2026, 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
@@ -64,25 +64,6 @@
6464
* Values should be annotated with the feature's {@code JEP}.
6565
*/
6666
public enum Feature {
67-
// The JDK build process involves creating an interim javac which is then
68-
// used to compile the rest of the JDK. The jdk.internal.javac.PreviewFeature
69-
// annotation from the current sources is used when compiling interim javac.
70-
// That's because the javac APIs of the current sources may be annotated with
71-
// this annotation and they may be using the enum constants of the current sources.
72-
// Furthermore, when compiling interim javac, the class files from the bootstrap JDK get
73-
// used and those may also contain the PreviewFeature annotation. However, they may be
74-
// using the enum constants of the bootstrap JDK's PreviewFeature annotation.
75-
// If javac sees an annotation with an unknown enum constant, it produces a warning,
76-
// and that in turn fails the build.
77-
// So, in the current sources, we need to preserve the PreviewFeature enum constants
78-
// for as long as the interim javac build needs it. As a result, we retain PreviewFeature
79-
// enum constants for preview features that are present in the bootstrap JDK.
80-
// Older constants can be removed.
81-
//
82-
// For example, Class-File API became final in JDK 24. As soon as JDK 23 was dropped as
83-
// the bootstrap JDK, the CLASSFILE_API enum constant became eligible for removal.
84-
85-
//---
8667
@JEP(number=525, title="Structured Concurrency", status="Sixth Preview")
8768
STRUCTURED_CONCURRENCY,
8869
@JEP(number = 526, title = "Lazy Constants", status = "Second Preview")

0 commit comments

Comments
 (0)