From 1996f649a3a30b7ac4b547a762417f807f5fa414 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Tue, 31 Aug 2021 16:33:02 +0000 Subject: [PATCH] 8273092: Sort classlist in JDK image Reviewed-by: redestad, ihse, dfuchs --- make/GenerateLinkOptData.gmk | 7 +- .../build/tools/classlist/SortClasslist.java | 99 +++++++++++++++++++ make/scripts/compare.sh | 14 +-- 3 files changed, 108 insertions(+), 12 deletions(-) create mode 100644 make/jdk/src/classes/build/tools/classlist/SortClasslist.java diff --git a/make/GenerateLinkOptData.gmk b/make/GenerateLinkOptData.gmk index 0de28d643fc..5dd766c8c07 100644 --- a/make/GenerateLinkOptData.gmk +++ b/make/GenerateLinkOptData.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2016, 2021, 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 @@ -88,7 +88,10 @@ $(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXECUTABLE_SUFFIX) $(CLASSLIST $(CAT) $(LINK_OPT_DIR)/stderr $(JLI_TRACE_FILE) ; \ exit $$exitcode \ ) - $(GREP) -v HelloClasslist $@.raw.2 > $@ + $(GREP) -v HelloClasslist $@.raw.2 > $@.raw.3 + $(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java \ + -cp $(SUPPORT_OUTPUTDIR)/classlist.jar \ + build.tools.classlist.SortClasslist $@.raw.3 > $@ # The jli trace is created by the same recipe as classlist. By declaring these # dependencies, make will correctly rebuild both jli trace and classlist diff --git a/make/jdk/src/classes/build/tools/classlist/SortClasslist.java b/make/jdk/src/classes/build/tools/classlist/SortClasslist.java new file mode 100644 index 00000000000..a85025ee85b --- /dev/null +++ b/make/jdk/src/classes/build/tools/classlist/SortClasslist.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2021, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * This application is meant to be run to create a classlist file representing + * common use. + * + * The classlist is produced by adding -XX:DumpLoadedClassList=classlist + */ +package build.tools.classlist; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.regex.Pattern; +import java.util.regex.Matcher; +import java.util.Scanner; + +/** + * The classlist generated by build.tools.classlist.HelloClasslist + * may have non-deterministic contents, affected by Java thread execution order. + * SortClasslist sorts the file to make the JDK image's contents more deterministic. + */ +public class SortClasslist { + public static void main(String args[]) throws FileNotFoundException { + ArrayList classes = new ArrayList<>(); + ArrayList lambdas = new ArrayList<>(); + + FileInputStream fis = new FileInputStream(args[0]); + Scanner scanner = new Scanner(fis); + Pattern p = Pattern.compile("^(.*)[ ]+id:[ ]+([0-9]+)$"); + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + Matcher m = p.matcher(line); + if (line.startsWith("#")) { + // Comments -- print them first without sorting. These appear only at the top + // of the file. + System.out.println(line); + } else if (line.startsWith("@")) { + // @lambda-form-invoker, @lambda-proxy, etc. + lambdas.add(line); + } else if (m.find()) { + // We found a pattern like this: + // + // java/lang/Object id: 0 + // + // This is a class used by one of the three builtin class loaders + // (boot/platform/app). Since the default classlist does not support unregistered + // classes, the ID is unused. Let's omit the ID, as it may be non-deterministic. + String className = m.group(1); // matches the (.*) part of the pattern. + classes.add(className); + } else { + // HelloClasslist should not load classes in custom class loaders, or else + // we might end up with output like this: + // + // SomeClass id: 123 super: 0 source: foo.jar + // + // Such classes won't be usable for common applications, so they should + // not be included in the JDK's default classlist. + System.err.println("Unexpected line: " + line); + System.err.println("The default classlist should not contain unregistered classes"); + System.exit(1); + } + } + + Collections.sort(classes); + Collections.sort(lambdas); + + for (String s : classes) { + System.out.println(s); + } + for (String s : lambdas) { + System.out.println(s); + } + } +} diff --git a/make/scripts/compare.sh b/make/scripts/compare.sh index c7215058b50..cc05476c997 100644 --- a/make/scripts/compare.sh +++ b/make/scripts/compare.sh @@ -356,20 +356,14 @@ compare_general_files() { " $CAT $OTHER_DIR/$f | eval "$SVG_FILTER" > $OTHER_FILE $CAT $THIS_DIR/$f | eval "$SVG_FILTER" > $THIS_FILE - elif [[ "$f" = *"/lib/classlist" ]] || [ "$SUFFIX" = "jar_contents" ]; then - # The classlist files may have some lines in random order + elif [ "$SUFFIX" = "jar_contents" ]; then + # The jar_contents files may have some lines in random order OTHER_FILE=$WORK_DIR/$f.other THIS_FILE=$WORK_DIR/$f.this $MKDIR -p $(dirname $OTHER_FILE) $(dirname $THIS_FILE) $RM $OTHER_FILE $THIS_FILE - # Also filter out the "id: NNNN" in the classlists - if [[ "$f" = *"/lib/classlist" ]]; then - $CAT $OTHER_DIR/$f | $SORT | $SED "s| id: .*||g" > $OTHER_FILE - $CAT $THIS_DIR/$f | $SORT | $SED "s| id: .*||g" > $THIS_FILE - else - $CAT $OTHER_DIR/$f | $SORT > $OTHER_FILE - $CAT $THIS_DIR/$f | $SORT > $THIS_FILE - fi + $CAT $OTHER_DIR/$f | $SORT > $OTHER_FILE + $CAT $THIS_DIR/$f | $SORT > $THIS_FILE else OTHER_FILE=$OTHER_DIR/$f THIS_FILE=$THIS_DIR/$f