mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8202387: javac --release 11 not supported
Adding historical data for JDK 10; adding ability to produce the historical data incrementally. Reviewed-by: erikj, forax, jjg
This commit is contained in:
parent
29b1984560
commit
81bad1fe6b
71 changed files with 3231 additions and 242 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -31,6 +31,7 @@ import build.tools.symbolgenerator.CreateSymbols
|
|||
import build.tools.symbolgenerator.CreateSymbols
|
||||
.ModuleHeaderDescription
|
||||
.RequiresDescription;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
@ -38,8 +39,8 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.FileVisitor;
|
||||
|
@ -49,23 +50,34 @@ import java.nio.file.attribute.BasicFileAttributes;
|
|||
import java.util.stream.Stream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.tools.JavaFileManager;
|
||||
import javax.tools.JavaFileManager.Location;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.JavaFileObject.Kind;
|
||||
import javax.tools.StandardLocation;
|
||||
|
||||
import com.sun.source.util.JavacTask;
|
||||
import com.sun.tools.classfile.AccessFlags;
|
||||
import com.sun.tools.classfile.Annotation;
|
||||
import com.sun.tools.classfile.Annotation.Annotation_element_value;
|
||||
|
@ -115,18 +127,20 @@ import com.sun.tools.classfile.RuntimeParameterAnnotations_attribute;
|
|||
import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute;
|
||||
import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute;
|
||||
import com.sun.tools.classfile.Signature_attribute;
|
||||
import com.sun.tools.javac.api.JavacTool;
|
||||
import com.sun.tools.javac.jvm.Target;
|
||||
import com.sun.tools.javac.util.Assert;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import com.sun.tools.javac.util.Pair;
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* A tool for processing the .sym.txt files. It allows to:
|
||||
* * convert the .sym.txt into class/sig files for ct.sym
|
||||
* * in cooperation with the adjacent history Probe, construct .sym.txt files for previous platforms
|
||||
* * enhance existing .sym.txt files with a a new set .sym.txt for the current platform
|
||||
*
|
||||
* To convert the .sym.txt files to class/sig files from ct.sym, run:
|
||||
* java build.tool.symbolgenerator.CreateSymbols build-ctsym [JOINED_VERSIONS|SEPARATE] <platform-description-file> <target-directory>
|
||||
* java build.tool.symbolgenerator.CreateSymbols build-ctsym <platform-description-file> <target-directory>
|
||||
*
|
||||
* The <platform-description-file> is a file of this format:
|
||||
* generate platforms <platform-ids-to-generate separate with ':'>
|
||||
|
@ -166,11 +180,15 @@ import java.io.StringWriter;
|
|||
* To generate the .sym.txt files for OpenJDK 7 and 8:
|
||||
* <jdk-7>/bin/java build.tools.symbolgenerator.Probe OpenJDK7.classes
|
||||
* <jdk-8>/bin/java build.tools.symbolgenerator.Probe OpenJDK8.classes
|
||||
* java build.tools.symbolgenerator.CreateSymbols build-description langtools/make/data/symbols $TOPDIR langtools/make/data/symbols/include.list
|
||||
* java build.tools.symbolgenerator.CreateSymbols build-description make/data/symbols $TOPDIR make/data/symbols/include.list
|
||||
* 8 OpenJDK8.classes '<none>'
|
||||
* 7 OpenJDK7.classes 8
|
||||
*
|
||||
* Note: the versions are expected to be a single character.
|
||||
*
|
||||
* To enhance existing historical data with data for JDK N, run:
|
||||
* <jdk-N>/bin/java build.tools.symbolgenerator.CreateSymbols build-description-incremental make/data/symbols/symbols make/data/symbols/include.list
|
||||
*
|
||||
*/
|
||||
public class CreateSymbols {
|
||||
|
||||
|
@ -180,11 +198,11 @@ public class CreateSymbols {
|
|||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void createSymbols(String ctDescriptionFile, String ctSymLocation, CtSymKind ctSymKind) throws IOException {
|
||||
Pair<ClassList, List<ModuleDescription>> data = load(Paths.get(ctDescriptionFile));
|
||||
LoadDescriptions data = load(Paths.get(ctDescriptionFile), null);
|
||||
|
||||
splitHeaders(data.fst);
|
||||
splitHeaders(data.classes);
|
||||
|
||||
for (ModuleDescription md : data.snd) {
|
||||
for (ModuleDescription md : data.modules.values()) {
|
||||
for (ModuleHeaderDescription mhd : md.header) {
|
||||
List<String> versionsList =
|
||||
Collections.singletonList(mhd.versions);
|
||||
|
@ -195,7 +213,7 @@ public class CreateSymbols {
|
|||
}
|
||||
}
|
||||
|
||||
for (ClassDescription classDescription : data.fst) {
|
||||
for (ClassDescription classDescription : data.classes) {
|
||||
for (ClassHeaderDescription header : classDescription.header) {
|
||||
switch (ctSymKind) {
|
||||
case JOINED_VERSIONS:
|
||||
|
@ -219,7 +237,7 @@ public class CreateSymbols {
|
|||
|
||||
public static String EXTENSION = ".sig";
|
||||
|
||||
Pair<ClassList, List<ModuleDescription>> load(Path ctDescription) throws IOException {
|
||||
LoadDescriptions load(Path ctDescription, String deletePlatform) throws IOException {
|
||||
List<PlatformInput> platforms = new ArrayList<>();
|
||||
Set<String> generatePlatforms = null;
|
||||
|
||||
|
@ -228,11 +246,14 @@ public class CreateSymbols {
|
|||
switch (reader.lineKey) {
|
||||
case "generate":
|
||||
String[] platformsAttr = reader.attributes.get("platforms").split(":");
|
||||
generatePlatforms = new HashSet<>(Arrays.asList(platformsAttr));
|
||||
generatePlatforms = new HashSet<>(List.of(platformsAttr));
|
||||
generatePlatforms.remove(deletePlatform);
|
||||
reader.moveNext();
|
||||
break;
|
||||
case "platform":
|
||||
platforms.add(PlatformInput.load(reader));
|
||||
PlatformInput platform = PlatformInput.load(reader);
|
||||
if (!platform.version.equals(deletePlatform))
|
||||
platforms.add(platform);
|
||||
reader.moveNext();
|
||||
break;
|
||||
default:
|
||||
|
@ -250,7 +271,9 @@ public class CreateSymbols {
|
|||
addNewVersion(cd.fields, platform.basePlatform, platform.version);
|
||||
addNewVersion(cd.methods, platform.basePlatform, platform.version);
|
||||
}
|
||||
//XXX: enhance module versions
|
||||
for (ModuleDescription md : modules.values()) {
|
||||
addNewVersion(md.header, platform.basePlatform, platform.version);
|
||||
}
|
||||
for (String input : platform.files) {
|
||||
Path inputFile = ctDescription.getParent().resolve(input);
|
||||
try (LineBasedReader reader = new LineBasedReader(inputFile)) {
|
||||
|
@ -270,13 +293,23 @@ public class CreateSymbols {
|
|||
cd.read(reader, platform.basePlatform,
|
||||
platform.version);
|
||||
break;
|
||||
case "module":
|
||||
case "module": {
|
||||
ModuleDescription md =
|
||||
modules.computeIfAbsent(nameAttr,
|
||||
n -> new ModuleDescription());
|
||||
md.read(reader, platform.basePlatform,
|
||||
platform.version);
|
||||
break;
|
||||
}
|
||||
case "-module": {
|
||||
ModuleDescription md =
|
||||
modules.computeIfAbsent(nameAttr,
|
||||
n -> new ModuleDescription());
|
||||
removeVersion(md.header, h -> true,
|
||||
platform.version);
|
||||
reader.moveNext();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -323,7 +356,7 @@ public class CreateSymbols {
|
|||
result.add(desc);
|
||||
}
|
||||
|
||||
List<ModuleDescription> moduleList = new ArrayList<>();
|
||||
Map<String, ModuleDescription> moduleList = new HashMap<>();
|
||||
|
||||
for (ModuleDescription desc : modules.values()) {
|
||||
Iterator<ModuleHeaderDescription> mhdIt = desc.header.iterator();
|
||||
|
@ -340,10 +373,25 @@ public class CreateSymbols {
|
|||
continue;
|
||||
}
|
||||
|
||||
moduleList.add(desc);
|
||||
moduleList.put(desc.name, desc);
|
||||
}
|
||||
|
||||
return new LoadDescriptions(result, moduleList, platforms);
|
||||
}
|
||||
|
||||
static final class LoadDescriptions {
|
||||
public final ClassList classes;
|
||||
public final Map<String, ModuleDescription> modules;
|
||||
public final List<PlatformInput> versions;
|
||||
|
||||
public LoadDescriptions(ClassList classes,
|
||||
Map<String, ModuleDescription> modules,
|
||||
List<PlatformInput> versions) {
|
||||
this.classes = classes;
|
||||
this.modules = modules;
|
||||
this.versions = versions;
|
||||
}
|
||||
|
||||
return Pair.of(result, moduleList);
|
||||
}
|
||||
|
||||
static final class LineBasedReader implements AutoCloseable {
|
||||
|
@ -423,7 +471,7 @@ public class CreateSymbols {
|
|||
public static PlatformInput load(LineBasedReader in) throws IOException {
|
||||
return new PlatformInput(in.attributes.get("version"),
|
||||
in.attributes.get("base"),
|
||||
Arrays.asList(in.attributes.get("files").split(":")));
|
||||
List.of(in.attributes.get("files").split(":")));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -792,7 +840,7 @@ public class CreateSymbols {
|
|||
|
||||
private void addAttributes(MethodDescription desc, List<CPInfo> constantPool, Map<String, Attribute> attributes) {
|
||||
addGenericAttributes(desc, constantPool, attributes);
|
||||
if (desc.thrownTypes != null && !desc.thrownTypes.isEmpty()) {
|
||||
if (desc.thrownTypes != null) {
|
||||
int[] exceptions = new int[desc.thrownTypes.size()];
|
||||
int i = 0;
|
||||
for (String exc : desc.thrownTypes) {
|
||||
|
@ -1081,175 +1129,228 @@ public class CreateSymbols {
|
|||
Map<String, ModuleDescription> modules = new HashMap<>();
|
||||
|
||||
for (VersionDescription desc : versions) {
|
||||
Map<String, ModuleDescription> currentVersionModules =
|
||||
new HashMap<>();
|
||||
List<byte[]> classFileData = new ArrayList<>();
|
||||
|
||||
try (BufferedReader descIn =
|
||||
Files.newBufferedReader(Paths.get(desc.classes))) {
|
||||
String classFileData;
|
||||
|
||||
while ((classFileData = descIn.readLine()) != null) {
|
||||
String line;
|
||||
while ((line = descIn.readLine()) != null) {
|
||||
ByteArrayOutputStream data = new ByteArrayOutputStream();
|
||||
for (int i = 0; i < classFileData.length(); i += 2) {
|
||||
String hex = classFileData.substring(i, i + 2);
|
||||
for (int i = 0; i < line.length(); i += 2) {
|
||||
String hex = line.substring(i, i + 2);
|
||||
data.write(Integer.parseInt(hex, 16));
|
||||
}
|
||||
try (InputStream in =
|
||||
new ByteArrayInputStream(data.toByteArray())) {
|
||||
inspectModuleInfoClassFile(in,
|
||||
currentVersionModules, desc.version);
|
||||
} catch (IOException | ConstantPoolException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
classFileData.add(data.toByteArray());
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
|
||||
ExcludeIncludeList currentEIList = excludesIncludes;
|
||||
loadVersionClasses(classes, modules, classFileData, excludesIncludes, desc.version);
|
||||
}
|
||||
|
||||
if (!currentVersionModules.isEmpty()) {
|
||||
Set<String> includes = new HashSet<>();
|
||||
List<PlatformInput> platforms =
|
||||
versions.stream()
|
||||
.map(desc -> new PlatformInput(desc.version,
|
||||
desc.primaryBaseline,
|
||||
null))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (ModuleDescription md : currentVersionModules.values()) {
|
||||
md.header.get(0).exports.stream().map(e -> e + '/')
|
||||
.forEach(includes::add);
|
||||
}
|
||||
dumpDescriptions(classes, modules, platforms, descDest.resolve("symbols"), args);
|
||||
}
|
||||
//where:
|
||||
private static final String DO_NO_MODIFY =
|
||||
"#\n" +
|
||||
"# Copyright (c) {YEAR}, Oracle and/or its affiliates. All rights reserved.\n" +
|
||||
"# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n" +
|
||||
"#\n" +
|
||||
"# This code is free software; you can redistribute it and/or modify it\n" +
|
||||
"# under the terms of the GNU General Public License version 2 only, as\n" +
|
||||
"# published by the Free Software Foundation. Oracle designates this\n" +
|
||||
"# particular file as subject to the \"Classpath\" exception as provided\n" +
|
||||
"# by Oracle in the LICENSE file that accompanied this code.\n" +
|
||||
"#\n" +
|
||||
"# This code is distributed in the hope that it will be useful, but WITHOUT\n" +
|
||||
"# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n" +
|
||||
"# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n" +
|
||||
"# version 2 for more details (a copy is included in the LICENSE file that\n" +
|
||||
"# accompanied this code).\n" +
|
||||
"#\n" +
|
||||
"# You should have received a copy of the GNU General Public License version\n" +
|
||||
"# 2 along with this work; if not, write to the Free Software Foundation,\n" +
|
||||
"# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n" +
|
||||
"#\n" +
|
||||
"# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n" +
|
||||
"# or visit www.oracle.com if you need additional information or have any\n" +
|
||||
"# questions.\n" +
|
||||
"#\n" +
|
||||
"# ##########################################################\n" +
|
||||
"# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ###\n" +
|
||||
"# ##########################################################\n" +
|
||||
"#\n";
|
||||
|
||||
currentEIList = new ExcludeIncludeList(includes,
|
||||
Collections.emptySet());
|
||||
private void loadVersionClasses(ClassList classes,
|
||||
Map<String, ModuleDescription> modules,
|
||||
Iterable<byte[]> classData,
|
||||
ExcludeIncludeList excludesIncludes,
|
||||
String version) {
|
||||
Map<String, ModuleDescription> currentVersionModules =
|
||||
new HashMap<>();
|
||||
|
||||
for (byte[] classFileData : classData) {
|
||||
try (InputStream in = new ByteArrayInputStream(classFileData)) {
|
||||
inspectModuleInfoClassFile(in,
|
||||
currentVersionModules, version);
|
||||
} catch (IOException | ConstantPoolException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
ExcludeIncludeList currentEIList = excludesIncludes;
|
||||
|
||||
if (!currentVersionModules.isEmpty()) {
|
||||
Set<String> includes = new HashSet<>();
|
||||
|
||||
for (ModuleDescription md : currentVersionModules.values()) {
|
||||
md.header.get(0).exports.stream().map(e -> e + '/')
|
||||
.forEach(includes::add);
|
||||
}
|
||||
|
||||
ClassList currentVersionClasses = new ClassList();
|
||||
try (BufferedReader descIn =
|
||||
Files.newBufferedReader(Paths.get(desc.classes))) {
|
||||
String classFileData;
|
||||
currentEIList = new ExcludeIncludeList(includes,
|
||||
Collections.emptySet());
|
||||
}
|
||||
|
||||
while ((classFileData = descIn.readLine()) != null) {
|
||||
ByteArrayOutputStream data = new ByteArrayOutputStream();
|
||||
for (int i = 0; i < classFileData.length(); i += 2) {
|
||||
String hex = classFileData.substring(i, i + 2);
|
||||
data.write(Integer.parseInt(hex, 16));
|
||||
}
|
||||
try (InputStream in =
|
||||
new ByteArrayInputStream(data.toByteArray())) {
|
||||
inspectClassFile(in, currentVersionClasses,
|
||||
currentEIList, desc.version);
|
||||
} catch (IOException | ConstantPoolException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
ClassList currentVersionClasses = new ClassList();
|
||||
|
||||
for (byte[] classFileData : classData) {
|
||||
try (InputStream in = new ByteArrayInputStream(classFileData)) {
|
||||
inspectClassFile(in, currentVersionClasses,
|
||||
currentEIList, version);
|
||||
} catch (IOException | ConstantPoolException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
ModuleDescription unsupported =
|
||||
currentVersionModules.get("jdk.unsupported");
|
||||
ModuleDescription unsupported =
|
||||
currentVersionModules.get("jdk.unsupported");
|
||||
|
||||
if (unsupported != null) {
|
||||
for (ClassDescription cd : currentVersionClasses.classes) {
|
||||
if (unsupported.header
|
||||
.get(0)
|
||||
.exports
|
||||
.contains(cd.packge().replace('.', '/'))) {
|
||||
ClassHeaderDescription ch = cd.header.get(0);
|
||||
if (ch.classAnnotations == null) {
|
||||
ch.classAnnotations = new ArrayList<>();
|
||||
}
|
||||
AnnotationDescription ad;
|
||||
ad = new AnnotationDescription(PROPERITARY_ANNOTATION,
|
||||
Collections.emptyMap());
|
||||
ch.classAnnotations.add(ad);
|
||||
if (unsupported != null) {
|
||||
for (ClassDescription cd : currentVersionClasses.classes) {
|
||||
if (unsupported.header
|
||||
.get(0)
|
||||
.exports
|
||||
.contains(cd.packge().replace('.', '/'))) {
|
||||
ClassHeaderDescription ch = cd.header.get(0);
|
||||
if (ch.classAnnotations == null) {
|
||||
ch.classAnnotations = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> includedClasses = new HashSet<>();
|
||||
boolean modified;
|
||||
|
||||
do {
|
||||
modified = false;
|
||||
|
||||
for (ClassDescription clazz : currentVersionClasses) {
|
||||
ClassHeaderDescription header = clazz.header.get(0);
|
||||
|
||||
if (includeEffectiveAccess(currentVersionClasses, clazz)) {
|
||||
modified |= include(includedClasses, currentVersionClasses, clazz.name);
|
||||
}
|
||||
|
||||
if (includedClasses.contains(clazz.name)) {
|
||||
modified |= include(includedClasses, currentVersionClasses, header.extendsAttr);
|
||||
for (String i : header.implementsAttr) {
|
||||
modified |= include(includedClasses, currentVersionClasses, i);
|
||||
}
|
||||
|
||||
modified |= includeOutputType(Collections.singleton(header),
|
||||
h -> "",
|
||||
includedClasses,
|
||||
currentVersionClasses);
|
||||
modified |= includeOutputType(clazz.fields,
|
||||
f -> f.descriptor,
|
||||
includedClasses,
|
||||
currentVersionClasses);
|
||||
modified |= includeOutputType(clazz.methods,
|
||||
m -> m.descriptor,
|
||||
includedClasses,
|
||||
currentVersionClasses);
|
||||
}
|
||||
}
|
||||
} while (modified);
|
||||
|
||||
for (ClassDescription clazz : currentVersionClasses) {
|
||||
if (!includedClasses.contains(clazz.name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ClassHeaderDescription header = clazz.header.get(0);
|
||||
|
||||
if (header.innerClasses != null) {
|
||||
Iterator<InnerClassInfo> innerClassIt = header.innerClasses.iterator();
|
||||
|
||||
while(innerClassIt.hasNext()) {
|
||||
InnerClassInfo ici = innerClassIt.next();
|
||||
if (!includedClasses.contains(ici.innerClass))
|
||||
innerClassIt.remove();
|
||||
}
|
||||
}
|
||||
|
||||
ClassDescription existing = classes.find(clazz.name, true);
|
||||
|
||||
if (existing != null) {
|
||||
addClassHeader(existing, header, desc.version);
|
||||
for (MethodDescription currentMethod : clazz.methods) {
|
||||
addMethod(existing, currentMethod, desc.version);
|
||||
}
|
||||
for (FieldDescription currentField : clazz.fields) {
|
||||
addField(existing, currentField, desc.version);
|
||||
}
|
||||
} else {
|
||||
classes.add(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
for (ModuleDescription module : currentVersionModules.values()) {
|
||||
ModuleHeaderDescription header = module.header.get(0);
|
||||
|
||||
if (header.innerClasses != null) {
|
||||
Iterator<InnerClassInfo> innerClassIt =
|
||||
header.innerClasses.iterator();
|
||||
|
||||
while(innerClassIt.hasNext()) {
|
||||
InnerClassInfo ici = innerClassIt.next();
|
||||
if (!includedClasses.contains(ici.innerClass))
|
||||
innerClassIt.remove();
|
||||
}
|
||||
}
|
||||
|
||||
ModuleDescription existing = modules.get(module.name);
|
||||
|
||||
if (existing != null) {
|
||||
addModuleHeader(existing, header, desc.version);
|
||||
} else {
|
||||
modules.put(module.name, module);
|
||||
AnnotationDescription ad;
|
||||
ad = new AnnotationDescription(PROPERITARY_ANNOTATION,
|
||||
Collections.emptyMap());
|
||||
ch.classAnnotations.add(ad);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> includedClasses = new HashSet<>();
|
||||
boolean modified;
|
||||
|
||||
do {
|
||||
modified = false;
|
||||
|
||||
for (ClassDescription clazz : currentVersionClasses) {
|
||||
ClassHeaderDescription header = clazz.header.get(0);
|
||||
|
||||
if (includeEffectiveAccess(currentVersionClasses, clazz)) {
|
||||
modified |= include(includedClasses, currentVersionClasses, clazz.name);
|
||||
}
|
||||
|
||||
if (includedClasses.contains(clazz.name)) {
|
||||
modified |= include(includedClasses, currentVersionClasses, header.extendsAttr);
|
||||
for (String i : header.implementsAttr) {
|
||||
modified |= include(includedClasses, currentVersionClasses, i);
|
||||
}
|
||||
|
||||
modified |= includeOutputType(Collections.singleton(header),
|
||||
h -> "",
|
||||
includedClasses,
|
||||
currentVersionClasses);
|
||||
modified |= includeOutputType(clazz.fields,
|
||||
f -> f.descriptor,
|
||||
includedClasses,
|
||||
currentVersionClasses);
|
||||
modified |= includeOutputType(clazz.methods,
|
||||
m -> m.descriptor,
|
||||
includedClasses,
|
||||
currentVersionClasses);
|
||||
}
|
||||
}
|
||||
} while (modified);
|
||||
|
||||
for (ClassDescription clazz : currentVersionClasses) {
|
||||
if (!includedClasses.contains(clazz.name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ClassHeaderDescription header = clazz.header.get(0);
|
||||
|
||||
if (header.innerClasses != null) {
|
||||
Iterator<InnerClassInfo> innerClassIt = header.innerClasses.iterator();
|
||||
|
||||
while(innerClassIt.hasNext()) {
|
||||
InnerClassInfo ici = innerClassIt.next();
|
||||
if (!includedClasses.contains(ici.innerClass))
|
||||
innerClassIt.remove();
|
||||
}
|
||||
}
|
||||
|
||||
ClassDescription existing = classes.find(clazz.name, true);
|
||||
|
||||
if (existing != null) {
|
||||
addClassHeader(existing, header, version);
|
||||
for (MethodDescription currentMethod : clazz.methods) {
|
||||
addMethod(existing, currentMethod, version);
|
||||
}
|
||||
for (FieldDescription currentField : clazz.fields) {
|
||||
addField(existing, currentField, version);
|
||||
}
|
||||
} else {
|
||||
classes.add(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
for (ModuleDescription module : currentVersionModules.values()) {
|
||||
ModuleHeaderDescription header = module.header.get(0);
|
||||
|
||||
if (header.innerClasses != null) {
|
||||
Iterator<InnerClassInfo> innerClassIt =
|
||||
header.innerClasses.iterator();
|
||||
|
||||
while(innerClassIt.hasNext()) {
|
||||
InnerClassInfo ici = innerClassIt.next();
|
||||
if (!includedClasses.contains(ici.innerClass))
|
||||
innerClassIt.remove();
|
||||
}
|
||||
}
|
||||
|
||||
ModuleDescription existing = modules.get(module.name);
|
||||
|
||||
if (existing != null) {
|
||||
addModuleHeader(existing, header, version);
|
||||
} else {
|
||||
modules.put(module.name, module);
|
||||
}
|
||||
}
|
||||
}
|
||||
//where:
|
||||
private static final String PROPERITARY_ANNOTATION =
|
||||
"Lsun/Proprietary+Annotation;";
|
||||
|
||||
private void dumpDescriptions(ClassList classes,
|
||||
Map<String, ModuleDescription> modules,
|
||||
List<PlatformInput> versions,
|
||||
Path ctDescriptionFile,
|
||||
String[] args) throws IOException {
|
||||
classes.sort();
|
||||
|
||||
Map<String, String> package2Modules = new HashMap<>();
|
||||
|
@ -1298,46 +1399,52 @@ public class CreateSymbols {
|
|||
.filter(m -> !module2Classes.containsKey(m))
|
||||
.forEach(m -> module2Classes.put(m, Collections.emptyList()));
|
||||
|
||||
Path symbolsFile = descDest.resolve("symbols");
|
||||
Files.createDirectories(ctDescriptionFile.getParent());
|
||||
|
||||
Files.createDirectories(symbolsFile.getParent());
|
||||
int year = Calendar.getInstance(TimeZone.getTimeZone("UTF"), Locale.ROOT)
|
||||
.get(Calendar.YEAR);
|
||||
|
||||
try (Writer symbolsOut = Files.newBufferedWriter(symbolsFile)) {
|
||||
Map<VersionDescription, List<Path>> outputFiles = new LinkedHashMap<>();
|
||||
try (Writer symbolsOut = Files.newBufferedWriter(ctDescriptionFile)) {
|
||||
Map<PlatformInput, List<String>> outputFiles = new LinkedHashMap<>();
|
||||
|
||||
for (Entry<String, List<ClassDescription>> e : module2Classes.entrySet()) {
|
||||
for (VersionDescription desc : versions) {
|
||||
StringWriter data = new StringWriter();
|
||||
ModuleDescription module = modules.get(e.getKey());
|
||||
for (PlatformInput desc : versions) {
|
||||
List<String> files = desc.files;
|
||||
|
||||
module.write(data, desc.primaryBaseline, desc.version);
|
||||
if (files == null) {
|
||||
files = new ArrayList<>();
|
||||
for (Entry<String, List<ClassDescription>> e : module2Classes.entrySet()) {
|
||||
StringWriter data = new StringWriter();
|
||||
ModuleDescription module = modules.get(e.getKey());
|
||||
|
||||
for (ClassDescription clazz : e.getValue()) {
|
||||
clazz.write(data, desc.primaryBaseline, desc.version);
|
||||
}
|
||||
module.write(data, desc.basePlatform, desc.version);
|
||||
|
||||
Path f = descDest.resolve(e.getKey() + "-" + desc.version + ".sym.txt");
|
||||
|
||||
String dataString = data.toString();
|
||||
|
||||
if (!dataString.isEmpty()) {
|
||||
try (Writer out = Files.newBufferedWriter(f)) {
|
||||
out.append(DO_NO_MODIFY);
|
||||
out.write(dataString);
|
||||
for (ClassDescription clazz : e.getValue()) {
|
||||
clazz.write(data, desc.basePlatform, desc.version);
|
||||
}
|
||||
|
||||
outputFiles.computeIfAbsent(desc, d -> new ArrayList<>())
|
||||
.add(f);
|
||||
String fileName = e.getKey() + "-" + desc.version + ".sym.txt";
|
||||
Path f = ctDescriptionFile.getParent().resolve(fileName);
|
||||
|
||||
String dataString = data.toString();
|
||||
|
||||
if (!dataString.isEmpty()) {
|
||||
try (Writer out = Files.newBufferedWriter(f)) {
|
||||
out.append(DO_NO_MODIFY.replace("{YEAR}", String.valueOf(year)));
|
||||
out.write(dataString);
|
||||
}
|
||||
files.add(f.getFileName().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outputFiles.put(desc, files);
|
||||
}
|
||||
symbolsOut.append(DO_NO_MODIFY);
|
||||
symbolsOut.append(DO_NO_MODIFY.replace("{YEAR}", "2015, " + year));
|
||||
symbolsOut.append("#command used to generate this file:\n");
|
||||
symbolsOut.append("#")
|
||||
.append(CreateSymbols.class.getName())
|
||||
.append(" ")
|
||||
.append(Arrays.asList(args)
|
||||
.stream()
|
||||
.append(Arrays.stream(args)
|
||||
.collect(Collectors.joining(" ")))
|
||||
.append("\n");
|
||||
symbolsOut.append("#\n");
|
||||
|
@ -1347,31 +1454,102 @@ public class CreateSymbols {
|
|||
.sorted()
|
||||
.collect(Collectors.joining(":")))
|
||||
.append("\n");
|
||||
for (Entry<VersionDescription, List<Path>> versionFileEntry : outputFiles.entrySet()) {
|
||||
for (Entry<PlatformInput, List<String>> versionFileEntry : outputFiles.entrySet()) {
|
||||
symbolsOut.append("platform version ")
|
||||
.append(versionFileEntry.getKey().version);
|
||||
if (versionFileEntry.getKey().primaryBaseline != null) {
|
||||
if (versionFileEntry.getKey().basePlatform != null) {
|
||||
symbolsOut.append(" base ")
|
||||
.append(versionFileEntry.getKey().primaryBaseline);
|
||||
.append(versionFileEntry.getKey().basePlatform);
|
||||
}
|
||||
symbolsOut.append(" files ")
|
||||
.append(versionFileEntry.getValue()
|
||||
.stream()
|
||||
.map(p -> p.getFileName().toString())
|
||||
.map(p -> p)
|
||||
.sorted()
|
||||
.collect(Collectors.joining(":")))
|
||||
.append("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void createIncrementalBaseLine(String ctDescriptionFile,
|
||||
String excludeFile,
|
||||
String[] args) throws IOException {
|
||||
String specVersion = System.getProperty("java.specification.version");
|
||||
String currentVersion =
|
||||
Integer.toString(Integer.parseInt(specVersion), Character.MAX_RADIX);
|
||||
currentVersion = currentVersion.toUpperCase(Locale.ROOT);
|
||||
Path ctDescriptionPath = Paths.get(ctDescriptionFile).toAbsolutePath();
|
||||
LoadDescriptions data = load(ctDescriptionPath, currentVersion);
|
||||
|
||||
ClassList classes = data.classes;
|
||||
Map<String, ModuleDescription> modules = data.modules;
|
||||
List<PlatformInput> versions = data.versions;
|
||||
|
||||
ExcludeIncludeList excludeList =
|
||||
ExcludeIncludeList.create(excludeFile);
|
||||
|
||||
Iterable<byte[]> classBytes = dumpCurrentClasses();
|
||||
loadVersionClasses(classes, modules, classBytes, excludeList, currentVersion);
|
||||
|
||||
String baseline;
|
||||
|
||||
if (versions.isEmpty()) {
|
||||
baseline = null;
|
||||
} else {
|
||||
baseline = versions.stream()
|
||||
.sorted((v1, v2) -> v2.version.compareTo(v1.version))
|
||||
.findFirst()
|
||||
.get()
|
||||
.version;
|
||||
}
|
||||
|
||||
versions.add(new PlatformInput(currentVersion, baseline, null));
|
||||
dumpDescriptions(classes, modules, versions, ctDescriptionPath, args);
|
||||
}
|
||||
|
||||
private List<byte[]> dumpCurrentClasses() throws IOException {
|
||||
JavacTool tool = JavacTool.create();
|
||||
Context ctx = new Context();
|
||||
String version = System.getProperty("java.specification.version");
|
||||
JavacTask task = tool.getTask(null, null, null,
|
||||
List.of("--release", version),
|
||||
null, null, ctx);
|
||||
task.getElements().getTypeElement("java.lang.Object");
|
||||
JavaFileManager fm = ctx.get(JavaFileManager.class);
|
||||
|
||||
List<byte[]> data = new ArrayList<>();
|
||||
for (Location modLoc : LOCATIONS) {
|
||||
for (Set<JavaFileManager.Location> module :
|
||||
fm.listLocationsForModules(modLoc)) {
|
||||
for (JavaFileManager.Location loc : module) {
|
||||
Iterable<JavaFileObject> files =
|
||||
fm.list(loc,
|
||||
"",
|
||||
EnumSet.of(Kind.CLASS),
|
||||
true);
|
||||
|
||||
for (JavaFileObject jfo : files) {
|
||||
try (InputStream is = jfo.openInputStream();
|
||||
InputStream in =
|
||||
new BufferedInputStream(is)) {
|
||||
ByteArrayOutputStream baos =
|
||||
new ByteArrayOutputStream();
|
||||
|
||||
in.transferTo(baos);
|
||||
data.add(baos.toByteArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
//where:
|
||||
private static final String DO_NO_MODIFY =
|
||||
"# ##########################################################\n" +
|
||||
"# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ###\n" +
|
||||
"# ##########################################################\n" +
|
||||
"#\n";
|
||||
private static final String PROPERITARY_ANNOTATION =
|
||||
"Lsun/Proprietary+Annotation;";
|
||||
private static final List<StandardLocation> LOCATIONS =
|
||||
List.of(StandardLocation.SYSTEM_MODULES,
|
||||
StandardLocation.UPGRADE_MODULE_PATH);
|
||||
|
||||
//<editor-fold defaultstate="collapsed" desc="Class Reading">
|
||||
//non-final for tests:
|
||||
|
@ -2006,11 +2184,11 @@ public class CreateSymbols {
|
|||
signature = reader.attributes.get("signature");
|
||||
String inClassAnnotations = reader.attributes.get("classAnnotations");
|
||||
if (inClassAnnotations != null) {
|
||||
classAnnotations = parseAnnotations(unquote(inClassAnnotations), new int[1]);
|
||||
classAnnotations = parseAnnotations(inClassAnnotations, new int[1]);
|
||||
}
|
||||
String inRuntimeAnnotations = reader.attributes.get("runtimeAnnotations");
|
||||
if (inRuntimeAnnotations != null) {
|
||||
runtimeAnnotations = parseAnnotations(unquote(inRuntimeAnnotations), new int[1]);
|
||||
runtimeAnnotations = parseAnnotations(inRuntimeAnnotations, new int[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2115,6 +2293,7 @@ public class CreateSymbols {
|
|||
ModuleHeaderDescription mhd =
|
||||
new ModuleHeaderDescription();
|
||||
mhd.read(reader);
|
||||
mhd.name = name;
|
||||
mhd.versions = version;
|
||||
header.add(mhd);
|
||||
break;
|
||||
|
@ -2695,7 +2874,11 @@ public class CreateSymbols {
|
|||
name = reader.attributes.get("name");
|
||||
descriptor = reader.attributes.get("descriptor");
|
||||
|
||||
thrownTypes = deserializeList(reader.attributes.get("thrownTypes"));
|
||||
String thrownTypesValue = reader.attributes.get("thrownTypes");
|
||||
|
||||
if (thrownTypesValue != null) {
|
||||
thrownTypes = deserializeList(thrownTypesValue);
|
||||
}
|
||||
|
||||
String inAnnotationDefaultValue = reader.attributes.get("annotationDefaultValue");
|
||||
|
||||
|
@ -2803,9 +2986,9 @@ public class CreateSymbols {
|
|||
if (inConstantValue != null) {
|
||||
switch (descriptor) {
|
||||
case "Z": constantValue = "true".equals(inConstantValue); break;
|
||||
case "B": constantValue = Byte.parseByte(inConstantValue); break;
|
||||
case "B": constantValue = Integer.parseInt(inConstantValue); break;
|
||||
case "C": constantValue = inConstantValue.charAt(0); break;
|
||||
case "S": constantValue = Short.parseShort(inConstantValue); break;
|
||||
case "S": constantValue = Integer.parseInt(inConstantValue); break;
|
||||
case "I": constantValue = Integer.parseInt(inConstantValue); break;
|
||||
case "J": constantValue = Long.parseLong(inConstantValue); break;
|
||||
case "F": constantValue = Float.parseFloat(inConstantValue); break;
|
||||
|
@ -3141,7 +3324,7 @@ public class CreateSymbols {
|
|||
serialized = unquote ? unquote(serialized) : serialized;
|
||||
if (serialized == null)
|
||||
return new ArrayList<>();
|
||||
return new ArrayList<>(Arrays.asList(serialized.split(",")));
|
||||
return new ArrayList<>(List.of(serialized.split(",")));
|
||||
}
|
||||
|
||||
private static String quote(String value, boolean quoteQuotes) {
|
||||
|
@ -3291,7 +3474,7 @@ public class CreateSymbols {
|
|||
}
|
||||
|
||||
switch (args[0]) {
|
||||
case "build-description":
|
||||
case "build-description": {
|
||||
if (args.length < 3) {
|
||||
help();
|
||||
return ;
|
||||
|
@ -3332,6 +3515,16 @@ public class CreateSymbols {
|
|||
descDest,
|
||||
args);
|
||||
break;
|
||||
}
|
||||
case "build-description-incremental": {
|
||||
if (args.length != 3) {
|
||||
help();
|
||||
return ;
|
||||
}
|
||||
|
||||
new CreateSymbols().createIncrementalBaseLine(args[1], args[2], args);
|
||||
break;
|
||||
}
|
||||
case "build-ctsym":
|
||||
if (args.length != 3) {
|
||||
help();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue