Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package java-11-openj9 for openSUSE:Factory checked in at 2026-08-09 21:34:25 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/java-11-openj9 (Old) and /work/SRC/openSUSE:Factory/.java-11-openj9.new.16738 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "java-11-openj9" Sun Aug 9 21:34:25 2026 rev:39 rq:1370209 version:11.0.32.0 Changes: -------- --- /work/SRC/openSUSE:Factory/java-11-openj9/java-11-openj9.changes 2026-06-05 14:59:00.573103896 +0200 +++ /work/SRC/openSUSE:Factory/.java-11-openj9.new.16738/java-11-openj9.changes 2026-08-09 21:36:41.961020569 +0200 @@ -1,0 +2,43 @@ +Thu Aug 6 16:05:51 UTC 2026 - Bernhard Wiedemann <[email protected]> + +- Add patches for reproducible builds: + * java-40y.patch + * reproducible-nls.patch + * reproducible-tracemerge-order.patch + * reproducible-generatecharacter.patch + * reproducible-generated-source-dates.patch + * reproducible-jmod-mtime.patch + * reproducible-search-index-files.patch + * reproducible-tznames-order.patch + * reproducible-nested-jars.patch + +------------------------------------------------------------------- +Thu Aug 6 05:54:44 UTC 2026 - Fridrich Strba <[email protected]> + +- Update to OpenJDK 11.0.32 with OpenJ9 0.60.0 virtual + machine +- Including Oracle July 2026 CPU changes + * CVE-2026-46968 (bsc#1272224), CVE-2026-46917 (bsc#1272223), + CVE-2026-47010 (bsc#1272225), CVE-2026-47021 (bsc#1272227), + CVE-2026-47027 (bsc#1272228), CVE-2026-60147 (bsc#1272237), + CVE-2026-47059 (bsc#1272235), CVE-2026-47063 (bsc#1272236), + CVE-2026-47057 (bsc#1272233), CVE-2026-47058 (bsc#1272234), + CVE-2026-41254 (bsc#1264994) +- OpenJ9 specific security fixes + * CVE-2026-16439 (bsc#1272250) + * CVE-2026-16441 (bsc#1272248) + * OpenJ9 changes, see + https://www.eclipse.org/openj9/docs/version0.60/ +- Modified patch: + * openj9-openssl.patch + + rebase +- Added patches: + * omr-gcc16.patch + + remove inlining annotation that compiler cannot honour + and that is fatal with gcc16 + * openj9-gcc16.patch + + add memory barrier between zeroing a memory by memset and + constructing an object into it, since gcc16 was optimizing + out the zeroing and OpenJ9 VM heavily relies on it + +------------------------------------------------------------------- Old: ---- 6426f03fa087b257a7e58f363ef61526c896fea3.zip a8e14054ef30e8468055458c15503d5857e8c837.zip c53b6b93f422b77b3395a3464d5578b706e9a618.zip New: ---- 2e3166f7afc61f577ccaa63b85444b63b82491f7.zip 396c827fb365c53b26586f55ec09d4727b37d9be.zip cb00718c9bc24aa94fa99dc4214f641b66cd492c.zip java-40y.patch omr-gcc16.patch openj9-gcc16.patch reproducible-generatecharacter.patch reproducible-generated-source-dates.patch reproducible-jmod-mtime.patch reproducible-nested-jars.patch reproducible-nls.patch reproducible-search-index-files.patch reproducible-tracemerge-order.patch reproducible-tznames-order.patch ----------(New B)---------- New:- Add patches for reproducible builds: * java-40y.patch * reproducible-nls.patch New:- Added patches: * omr-gcc16.patch + remove inlining annotation that compiler cannot honour New: and that is fatal with gcc16 * openj9-gcc16.patch + add memory barrier between zeroing a memory by memset and New: * reproducible-tracemerge-order.patch * reproducible-generatecharacter.patch * reproducible-generated-source-dates.patch New: * reproducible-generatecharacter.patch * reproducible-generated-source-dates.patch * reproducible-jmod-mtime.patch New: * reproducible-generated-source-dates.patch * reproducible-jmod-mtime.patch * reproducible-search-index-files.patch New: * reproducible-tznames-order.patch * reproducible-nested-jars.patch New: * java-40y.patch * reproducible-nls.patch * reproducible-tracemerge-order.patch New: * reproducible-jmod-mtime.patch * reproducible-search-index-files.patch * reproducible-tznames-order.patch New: * reproducible-nls.patch * reproducible-tracemerge-order.patch * reproducible-generatecharacter.patch New: * reproducible-search-index-files.patch * reproducible-tznames-order.patch * reproducible-nested-jars.patch ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ java-11-openj9.spec ++++++ --- /var/tmp/diff_new_pack.wds4W2/_old 2026-08-09 21:36:45.585143972 +0200 +++ /var/tmp/diff_new_pack.wds4W2/_new 2026-08-09 21:36:45.589144109 +0200 @@ -34,19 +34,19 @@ # Standard JPackage naming and versioning defines. %global featurever 11 %global interimver 0 -%global updatever 31 +%global updatever 32 %global patchver 0 -%global buildver 11 +%global buildver 9 %global root_repository https://github.com/ibmruntimes/openj9-openjdk-jdk%{featurever}/archive -%global root_revision a8e14054ef30e8468055458c15503d5857e8c837 -%global root_branch v0.59.0-release -%global omr_repository https://github.com/eclipse/openj9-omr/archive -%global omr_revision 6426f03fa087b257a7e58f363ef61526c896fea3 -%global omr_branch v0.59.0-release -%global openj9_repository https://github.com/eclipse/openj9/archive -%global openj9_revision c53b6b93f422b77b3395a3464d5578b706e9a618 -%global openj9_branch v0.59.0-release -%global openj9_tag openj9-0.59.0 +%global root_revision cb00718c9bc24aa94fa99dc4214f641b66cd492c +%global root_branch v0.60.0-release +%global omr_repository https://github.com/eclipse-openj9/openj9-omr/archive +%global omr_revision 2e3166f7afc61f577ccaa63b85444b63b82491f7 +%global omr_branch v0.60.0-release +%global openj9_repository https://github.com/eclipse-openj9/openj9/archive +%global openj9_revision 396c827fb365c53b26586f55ec09d4727b37d9be +%global openj9_branch v0.60.0-release +%global openj9_tag openj9-0.60.0 %if 0%{?suse_version} > 1500 %bcond_without libalternatives %else @@ -116,6 +116,9 @@ Patch4: openj9-openssl.patch # Fix: implicit-pointer-decl Patch5: implicit-pointer-decl.patch +# Fixes for build with gcc 16 +Patch6: omr-gcc16.patch +Patch7: openj9-gcc16.patch # Patch10: system-pcsclite.patch # @@ -124,6 +127,16 @@ Patch30: JDK-8208602.patch Patch31: aarch64.patch Patch32: reproducible-version.patch +Patch33: reproducible-nls.patch +Patch34: reproducible-tracemerge-order.patch +Patch35: reproducible-generatecharacter.patch +Patch36: reproducible-generated-source-dates.patch +Patch37: reproducible-jmod-mtime.patch +Patch38: reproducible-search-index-files.patch +Patch39: java-40y.patch +Patch40: reproducible-tznames-order.patch +Patch41: reproducible-nested-jars.patch + # # OpenJDK specific patches # @@ -163,6 +176,9 @@ BuildRequires: nasm BuildRequires: openssl-devel BuildRequires: pkgconfig +%if 0%{?suse_version} >= 1500 +BuildRequires: strip-nondeterminism +%endif BuildRequires: unzip BuildRequires: xprop BuildRequires: zip @@ -360,6 +376,8 @@ %patch -P 3 -p1 %patch -P 4 -p1 %patch -P 5 -p1 +%patch -P 6 -p1 +%patch -P 7 -p1 %if %{with_system_pcsc} %patch -P 10 -p1 @@ -370,6 +388,15 @@ %patch -P 30 -p1 %patch -P 31 -p1 %patch -P 32 -p1 +%patch -P 33 -p1 +%patch -P 34 -p1 +%patch -P 35 -p1 +%patch -P 36 -p1 +%patch -P 37 -p1 +%patch -P 38 -p1 +%patch -P 39 -p1 +%patch -P 40 -p1 +%patch -P 41 -p1 %patch -P 300 -p1 @@ -411,34 +438,35 @@ CC=gcc-%{with_gcc} \ NM=gcc-nm-%{with_gcc} \ %endif +%if %{with_system_pcsc} + --with-pcsclite=system \ +%endif +%if %{with_system_harfbuzz} + --with-harfbuzz=system \ +%endif --with-extra-cflags="$EXTRA_CFLAGS" \ --with-extra-cxxflags="$EXTRA_CPP_FLAGS" \ --with-version-pre="" \ --with-version-opt="suse-0%{?suse_version}-%{_arch}" \ + --with-debug-level=%{debugbuild} \ + --with-conf-name=%{debugbuild} \ --disable-warnings-as-errors \ --disable-warnings-as-errors-omr \ --disable-warnings-as-errors-openj9 \ --disable-keep-packaged-modules \ --enable-jfr \ - --with-debug-level=%{debugbuild} \ - --with-conf-name=%{debugbuild} \ --with-zlib=system \ --with-libjpeg=system \ --with-giflib=system \ --with-libpng=system \ --with-lcms=system \ --with-openssl=system \ -%if %{with_system_pcsc} - --with-pcsclite=system \ -%endif -%if %{with_system_harfbuzz} - --with-harfbuzz=system \ -%endif --with-stdc++lib=dynamic \ - --with-extra-cxxflags="$EXTRA_CPP_FLAGS" \ - --with-extra-cflags="$EXTRA_CFLAGS" \ --disable-javac-server \ - --enable-demos + --enable-demos \ + --enable-reproducible-build \ + --with-source-date="${SOURCE_DATE_EPOCH:-$(date +%%s)}" \ + --with-copyright-year="$(date -u -d "@${SOURCE_DATE_EPOCH:-$(date +%%s)}" +%%Y)" %{make} \ LOG=trace \ @@ -564,6 +592,16 @@ | sed 's|^|%doc |' \ >> %{name}-demo.files +%if 0%?have_strip_nondeterminism > 0 +# normalizes the zip timestamps in the demo jars, jrt-fs.jar and src.zip; +# ct.sym is a jar too, but only matched by name. The jmod archives are +# already normalized at build time (reproducible-jmod-mtime.patch) and +# must not be touched, or the ModuleHashes recorded in java.base go stale. +strip-all-nondeterminism %{buildroot}/%{_jvmdir} +strip-nondeterminism --type zip --timestamp=${SOURCE_DATE_EPOCH:-1494270000} \ + --clamp-timestamp %{buildroot}%{_jvmdir}/%{sdkdir}/lib/ct.sym +%endif + # fdupes links the files from JDK to JRE, so it breaks a JRE # use it carefully :)) %fdupes -s %{buildroot}/%{_jvmdir}/%{sdkdir}/ ++++++ 6426f03fa087b257a7e58f363ef61526c896fea3.zip -> 2e3166f7afc61f577ccaa63b85444b63b82491f7.zip ++++++ /work/SRC/openSUSE:Factory/java-11-openj9/6426f03fa087b257a7e58f363ef61526c896fea3.zip /work/SRC/openSUSE:Factory/.java-11-openj9.new.16738/2e3166f7afc61f577ccaa63b85444b63b82491f7.zip differ: char 11, line 2 ++++++ 6426f03fa087b257a7e58f363ef61526c896fea3.zip -> 396c827fb365c53b26586f55ec09d4727b37d9be.zip ++++++ /work/SRC/openSUSE:Factory/java-11-openj9/6426f03fa087b257a7e58f363ef61526c896fea3.zip /work/SRC/openSUSE:Factory/.java-11-openj9.new.16738/396c827fb365c53b26586f55ec09d4727b37d9be.zip differ: char 11, line 2 ++++++ 6426f03fa087b257a7e58f363ef61526c896fea3.zip -> cb00718c9bc24aa94fa99dc4214f641b66cd492c.zip ++++++ /work/SRC/openSUSE:Factory/java-11-openj9/6426f03fa087b257a7e58f363ef61526c896fea3.zip /work/SRC/openSUSE:Factory/.java-11-openj9.new.16738/cb00718c9bc24aa94fa99dc4214f641b66cd492c.zip differ: char 11, line 2 ++++++ java-40y.patch ++++++ diff --git a/make/jdk/src/classes/build/tools/generatecurrencydata/GenerateCurrencyData.java b/make/jdk/src/classes/build/tools/generatecurrencydata/GenerateCurrencyData.java index 9a82021d2..559b9024e 100644 --- a/make/jdk/src/classes/build/tools/generatecurrencydata/GenerateCurrencyData.java +++ b/make/jdk/src/classes/build/tools/generatecurrencydata/GenerateCurrencyData.java @@ -285,8 +285,8 @@ public class GenerateCurrencyData { checkCurrencyCode(newCurrency); String timeString = currencyInfo.substring(4, length - 4); long time = format.parse(timeString).getTime(); - if (Math.abs(time - System.currentTimeMillis()) > ((long) 10) * 365 * 24 * 60 * 60 * 1000) { - throw new RuntimeException("time is more than 10 years from present: " + time); + if (Math.abs(time - System.currentTimeMillis()) > ((long) 40) * 365 * 24 * 60 * 60 * 1000) { + throw new RuntimeException("time is more than 40 years from present: " + time); } specialCaseCutOverTimes[specialCaseCount] = time; specialCaseOldCurrencies[specialCaseCount] = oldCurrency; ++++++ omr-gcc16.patch ++++++ --- a/omr/gc/base/MemorySubSpaceGenerational.hpp +++ b/omr/gc/base/MemorySubSpaceGenerational.hpp @@ -107,7 +107,7 @@ class MM_MemorySubSpaceGenerational : public MM_MemorySubSpace virtual uintptr_t releaseFreeMemoryPages(MM_EnvironmentBase* env, uintptr_t memoryType); - virtual MMINLINE uintptr_t getContractionSize() const { return _memorySubSpaceOld->getContractionSize(); } + virtual uintptr_t getContractionSize() const { return _memorySubSpaceOld->getContractionSize(); } /** * Create a MemorySubSpaceGenerational object. ++++++ openj9-gcc16.patch ++++++ --- a/openj9/runtime/compiler/control/CompilationThread.cpp +++ b/openj9/runtime/compiler/control/CompilationThread.cpp @@ -778,6 +778,7 @@ bool TR::CompilationInfo::createCompilationInfo(J9JITConfig *jitConfig) /* Note: there are embedded objects in TR::CompilationInfo that rely on the fact that we do memset this object to 0 */ memset(alloc, 0, sizeof(TR::CompilationInfo)); + __asm__("" : : : "memory"); _compilationRuntime = new (alloc) TR::CompilationInfo(jitConfig); jitConfig->compilationRuntime = (void *)_compilationRuntime; #ifdef DEBUG ++++++ openj9-openssl.patch ++++++ --- /var/tmp/diff_new_pack.wds4W2/_old 2026-08-09 21:36:45.941156094 +0200 +++ /var/tmp/diff_new_pack.wds4W2/_new 2026-08-09 21:36:45.949156367 +0200 @@ -8,7 +8,7 @@ +#define SSL_R_UNEXPECTED_EOF_WHILE_READING 294 +#endif + - static bool - handleOpenSSLConnectionError(int connfd, SSL *&ssl, BIO *&bio, const char *errMsg, int ret, TR::CompilationInfo *compInfo) - { + static bool handleOpenSSLConnectionError(int connfd, SSL *&ssl, BIO *&bio, const char *errMsg, int ret, + TR::CompilationInfo *compInfo) + { ++++++ reproducible-generatecharacter.patch ++++++ From: Magnus Ihse Bursie <[email protected]> Subject: 8243985: Make source generation by generatecharacter reproducible Backported from upstream OpenJDK commit 09e8b7ca4d614ed05a22e0544b17c68b5c7b00db, which postdates this jdk11 branch point. GenerateCharacter embedded the current wall-clock time in every generated source file's header comment, so java.base/java/lang/CharacterData*.java and the CLDR resource files differed between otherwise identical builds. --- a/make/jdk/src/classes/build/tools/generatecharacter/GenerateCharacter.java +++ b/make/jdk/src/classes/build/tools/generatecharacter/GenerateCharacter.java @@ -700,7 +700,7 @@ PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(theOutputFileName))); out.println(commentStart + " This file was generated AUTOMATICALLY from a template file " + - new java.util.Date() + commentEnd); + commentEnd); int marklen = commandMarker.length(); LOOP: while(true) { try { ++++++ reproducible-generated-source-dates.patch ++++++ From: Bernhard M. Wiedemann <[email protected]> Subject: Use SOURCE_DATE_EPOCH for dates written into generated sources Two build tools stamp the current year into the copyright header of the sources they generate, all of which end up in the shipped src.zip: CopyrightHeaders in the CLDR converter (sun/util/resources/cldr/**) and EquivMapsGenerator (sun/util/locale/LocaleEquivalentMaps.java). Take the date from SOURCE_DATE_EPOCH when it is set and keep the current time otherwise. The year is still computed in America/Los_Angeles, as before, so only the instant changes. Same fix as in the java-1_8_0-openj9 package, adapted to the jdk11 code layout and to EquivMapsGenerator's use of java.time. Signed-off-by: Bernhard M. Wiedemann <[email protected]> --- a/make/jdk/src/classes/build/tools/cldrconverter/CopyrightHeaders.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/CopyrightHeaders.java @@ -150,8 +150,17 @@ } private static int getYear() { - return new GregorianCalendar(TimeZone.getTimeZone("America/Los_Angeles"), - Locale.US).get(Calendar.YEAR); + GregorianCalendar cal = + new GregorianCalendar(TimeZone.getTimeZone("America/Los_Angeles"), + Locale.US); + String sourceDateEpoch = System.getenv("SOURCE_DATE_EPOCH"); + if (sourceDateEpoch != null && !sourceDateEpoch.isEmpty()) { + try { + cal.setTimeInMillis(Long.parseLong(sourceDateEpoch.trim()) * 1000L); + } catch (NumberFormatException e) { + } + } + return cal.get(Calendar.YEAR); } // no instantiation --- a/make/jdk/src/classes/build/tools/generatelsrequivmaps/EquivMapsGenerator.java +++ b/make/jdk/src/classes/build/tools/generatelsrequivmaps/EquivMapsGenerator.java @@ -30,6 +30,7 @@ import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; +import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.ArrayList; @@ -266,9 +267,18 @@ + "}"; private static String getOpenJDKCopyright() { - int year = ZonedDateTime.now(ZoneId - .of("America/Los_Angeles")).getYear(); - return String.format(Locale.US, COPYRIGHT, year); + ZonedDateTime zdt = ZonedDateTime.now(ZoneId + .of("America/Los_Angeles")); + String sourceDateEpoch = System.getenv("SOURCE_DATE_EPOCH"); + if (sourceDateEpoch != null && !sourceDateEpoch.isEmpty()) { + try { + zdt = ZonedDateTime.ofInstant( + Instant.ofEpochSecond(Long.parseLong(sourceDateEpoch.trim())), + ZoneId.of("America/Los_Angeles")); + } catch (NumberFormatException e) { + } + } + return String.format(Locale.US, COPYRIGHT, zdt.getYear()); } /** ++++++ reproducible-jmod-mtime.patch ++++++ From: Bernhard M. Wiedemann <[email protected]> Subject: Make jmod content deterministic jmod stores each entry with the current time and packages the files of a section in the order the filesystem returns directory entries, so every .jmod archive can differ between two builds - seen both in the legal notices ("legal/ADDITIONAL_LICENSE_INFO" vs "legal/ASSEMBLY_EXCEPTION" first) and in the classes section. Clamp the entry time to SOURCE_DATE_EPOCH when it is set and sort each section's file list. jmod gained a --date option and sorted content for the same purpose in JDK 19 (JDK-8276766). Signed-off-by: Bernhard M. Wiedemann <[email protected]> --- a/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodOutputStream.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodOutputStream.java @@ -101,7 +101,15 @@ String prefix = section.jmodDir(); String name = Paths.get(prefix, path).toString() .replace(File.separatorChar, '/'); - return new ZipEntry(name); + ZipEntry entry = new ZipEntry(name); + String sourceDateEpoch = System.getenv("SOURCE_DATE_EPOCH"); + if (sourceDateEpoch != null && !sourceDateEpoch.isEmpty()) { + try { + entry.setTime(Long.parseLong(sourceDateEpoch.trim()) * 1000L); + } catch (NumberFormatException e) { + } + } + return entry; } @Override --- a/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java @@ -773,33 +773,41 @@ void processSection(JmodOutputStream out, Section section, Path path) throws IOException { + // Collect and sort the files so that the archive does not depend + // on the order the filesystem returns directory entries in. + List<Path> files = new ArrayList<>(); Files.walkFileTree(path, Set.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Path relPath = path.relativize(file); - if (relPath.toString().equals(MODULE_INFO) - && !Section.CLASSES.equals(section)) - warning("warn.ignore.entry", MODULE_INFO, section); - - if (!relPath.toString().equals(MODULE_INFO) - && !matches(relPath, excludes)) { - try (InputStream in = Files.newInputStream(file)) { - out.writeEntry(in, section, relPath.toString()); - } catch (IOException x) { - if (x.getMessage().contains("duplicate entry")) { - warning("warn.ignore.duplicate.entry", - relPath.toString(), section); - return FileVisitResult.CONTINUE; - } - throw x; - } - } + files.add(file); return FileVisitResult.CONTINUE; } }); + Collections.sort(files); + + for (Path file : files) { + Path relPath = path.relativize(file); + if (relPath.toString().equals(MODULE_INFO) + && !Section.CLASSES.equals(section)) + warning("warn.ignore.entry", MODULE_INFO, section); + + if (!relPath.toString().equals(MODULE_INFO) + && !matches(relPath, excludes)) { + try (InputStream in = Files.newInputStream(file)) { + out.writeEntry(in, section, relPath.toString()); + } catch (IOException x) { + if (x.getMessage().contains("duplicate entry")) { + warning("warn.ignore.duplicate.entry", + relPath.toString(), section); + continue; + } + throw x; + } + } + } } boolean matches(Path path, List<PathMatcher> matchers) { ++++++ reproducible-nested-jars.patch ++++++ From: Bernhard M. Wiedemann <[email protected]> Subject: Normalize jars before they are archived into jmods jrt-fs.jar and ct.sym are created with the boot JDK's jar tool, which hardcodes the current time into the META-INF entries, so the copies archived into java.base.jmod and jdk.compiler.jmod differ between builds even though the standalone copies get normalized during packaging. Run strip-nondeterminism on them right before jmod picks them up; normalizing them later is not possible because java.base records hashes over the other .jmod files. Not upstreamable in this form (it relies on strip-nondeterminism being installed and is a no-op without it); upstream fixed this in JDK 19 by teaching jar and jmod a --date option (JDK-8276766). Signed-off-by: Bernhard M. Wiedemann <[email protected]> --- a/make/CreateJmods.gmk +++ b/make/CreateJmods.gmk @@ -222,6 +222,16 @@ $(call LogWarn, Creating $(patsubst $(OUTPUTDIR)/%, %, $@)) $(call MakeDir, $(JMODS_DIR) $(JMODS_TEMPDIR)) $(RM) $@ $(JMODS_TEMPDIR)/$(notdir $@) + # The boot JDK's jar tool stamps the current time into the META-INF + # entries of jrt-fs.jar and ct.sym, and jmod archives those bytes, so + # they have to be normalized before packaging - afterwards is too late + # because of the module hashes recorded in java.base. + $(if $(filter-out updated, $(SOURCE_DATE)), \ + if [ -d "$(LIBS_DIR)" ] && command -v strip-nondeterminism > /dev/null 2>&1; then \ + $(FIND) $(LIBS_DIR) -type f \( -name '*.jar' -o -name 'ct.sym' \) \ + -exec strip-nondeterminism --type zip --timestamp=$(SOURCE_DATE) \ + --clamp-timestamp {} + ; \ + fi) $(call ExecuteWithLog, $(SUPPORT_OUTPUTDIR)/jmods/$(MODULE).jmod, \ $(JMOD) create \ --module-version $(VERSION_SHORT) \ ++++++ reproducible-nls.patch ++++++ diff --git a/openj9/sourcetools/j9nls/com/ibm/oti/NLSTool/J9NLS.java b/openj9/sourcetools/j9nls/com/ibm/oti/NLSTool/J9NLS.java index 25aa5c221..2fea566e0 100644 --- a/openj9/sourcetools/j9nls/com/ibm/oti/NLSTool/J9NLS.java +++ b/openj9/sourcetools/j9nls/com/ibm/oti/NLSTool/J9NLS.java @@ -22,6 +22,7 @@ package com.ibm.oti.NLSTool; import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -291,8 +292,8 @@ public class J9NLS implements NLSConstants { } else { String fileName = getNameWithLocale(outFileName, locale); if (propertiesDifferentFromCopyOnDisk(fileName)) { - out = new FileOutputStream(fileName); - outputProperties.store(out, null); + out = new FileOutputStream(fileName); + storeOutputProperties(out); out.flush(); dp("** Generated " + fileName + "\n"); totalPropertiesFilesCreated++; @@ -308,6 +309,22 @@ public class J9NLS implements NLSConstants { } } + /** + * Writes the generated properties, dropping the leading comment line in + * which Properties.store() records the current time: it would make the + * generated files differ between otherwise identical builds. + * + * @param out + * @throws IOException + */ + private void storeOutputProperties(OutputStream out) throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + outputProperties.store(buffer, null); + /* Properties.store(OutputStream, String) writes ISO 8859-1. */ + String stored = buffer.toString("ISO-8859-1"); + out.write(stored.substring(stored.indexOf('\n') + 1).getBytes("ISO-8859-1")); + } + private MsgInfo createMsgInfo(String macro, String key, String msg, Properties nlsProperties) { MsgInfo msgInfo = new MsgInfo(); msgInfo.setMacro(macro); ++++++ reproducible-search-index-files.patch ++++++ --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractIndexWriter.java @@ -497,6 +497,10 @@ public class AbstractIndexWriter extends HtmlDocletWriter { ZipOutputStream zos = new ZipOutputStream(fos)) { try { ZipEntry ze = new ZipEntry(searchIndexFile.getPath()); + String sde = System.getenv("SOURCE_DATE_EPOCH"); + if (sde != null) { + ze.setTime(1000 * Long.parseLong(sde)); + } zos.putNextEntry(ze); zos.write(searchVar.toString().getBytes()); } finally { ++++++ reproducible-tracemerge-order.patch ++++++ diff --git a/omr/tools/tracegen/FileUtils.cpp b/omr/tools/tracegen/FileUtils.cpp index 7db9723f8..b015970fb 100644 --- a/omr/tools/tracegen/FileUtils.cpp +++ b/omr/tools/tracegen/FileUtils.cpp @@ -120,44 +120,106 @@ FileUtils::getMtime(const char *filePath) return statbuf.st_mtime; } +/* + * Compare two directory entry names. strcmp() is used rather than strcoll() + * so that the ordering is a plain byte comparison, and hence does not depend + * on the locale the build happens to run in. + */ +static int +compareEntryNames(const void *left, const void *right) +{ + return strcmp(*(const char *const *)left, *(const char *const *)right); +} + +static void +freeEntryNames(char ***entries, size_t entryCount) +{ + if (NULL != *entries) { + size_t index = 0; + for (index = 0; index < entryCount; index += 1) { + Port::omrmem_free((void **)&(*entries)[index]); + } + Port::omrmem_free((void **)entries); + } +} + RCType FileUtils::visitDirectory(J9TDFOptions *options, const char *dirName, const char *fileExtFilter, void *targetObject, VisitFileCallBack callback) { char *resultBuffer = NULL; RCType rc = RC_OK; intptr_t handle = PORT_INVALID_FIND_FILE_HANDLE; + char **entries = NULL; + size_t entryCount = 0; + size_t entryCapacity = 0; + size_t index = 0; rc = Port::omrfile_findfirst(dirName, &resultBuffer, &handle); if (RC_OK != rc) { printError("Failed to open directory %s\n", dirName); - goto failed; + /* findfirst leaves no handle open when it fails, so there is nothing to close. */ + return RC_FAILED; } + /* + * Collect the entries before visiting any of them. The order in which the + * filesystem reports directory entries is not stable, and that order used + * to reach the merged trace data, so otherwise identical builds produced + * different output. + */ while (RC_FAILED != rc) { - char *nextEntry = NULL; - size_t nextEntrySize = 0; /* skip current and parent dir */ if ((0 == strcmp(resultBuffer, ".")) || (0 == strcmp(resultBuffer, ".."))) { - goto next; + Port::omrmem_free((void **)&resultBuffer); + } else { + if (entryCount == entryCapacity) { + size_t newCapacity = (0 == entryCapacity) ? 16 : (entryCapacity * 2); + char **newEntries = (char **)Port::omrmem_calloc(newCapacity, sizeof(char *)); + if (NULL == newEntries) { + goto failed; + } + if (NULL != entries) { + memcpy(newEntries, entries, entryCount * sizeof(char *)); + Port::omrmem_free((void **)&entries); + } + entries = newEntries; + entryCapacity = newCapacity; + } + /* the array takes ownership of the name allocated by findfirst/findnext */ + entries[entryCount] = resultBuffer; + entryCount += 1; + resultBuffer = NULL; } + rc = Port::omrfile_findnext(handle, &resultBuffer); + } + Port::omrfile_findclose(handle); + handle = PORT_INVALID_FIND_FILE_HANDLE; + + if (0 != entryCount) { + qsort(entries, entryCount, sizeof(char *), compareEntryNames); + } + + for (index = 0; index < entryCount; index += 1) { + const char *entryName = entries[index]; + size_t nextEntrySize = strlen(dirName) + strlen(PATH_SEP) + strlen(entryName) + 1; + char *nextEntry = (char *)Port::omrmem_calloc(1, nextEntrySize); + struct J9FileStat buf; - nextEntrySize = strlen(dirName) + 1 /* PATH_SEP */ + strlen(resultBuffer) + 1; - nextEntry = (char *)Port::omrmem_calloc(1, nextEntrySize); if (NULL == nextEntry) { goto failed; } - snprintf(nextEntry, nextEntrySize, "%s" PATH_SEP "%s", dirName, resultBuffer); + snprintf(nextEntry, nextEntrySize, "%s" PATH_SEP "%s", dirName, entryName); - struct J9FileStat buf; if (RC_OK != Port::omrfile_stat(nextEntry, 0, &buf)) { if (options->statErrorsAreFatal) { printError("stat failed %s\n", nextEntry); + Port::omrmem_free((void **)&nextEntry); goto failed; } } else if (buf.isDir) { visitDirectory(options, nextEntry, fileExtFilter, targetObject, callback); } else { - const char *ext = FileUtils::getFileExt(resultBuffer); + const char *ext = FileUtils::getFileExt(entryName); if (NULL != ext) { if (0 == strcmp(ext, fileExtFilter)) { callback(targetObject, options, nextEntry); @@ -165,17 +227,17 @@ FileUtils::visitDirectory(J9TDFOptions *options, const char *dirName, const char } } Port::omrmem_free((void **)&nextEntry); -next: - Port::omrmem_free((void **)&resultBuffer); - rc = Port::omrfile_findnext(handle, &resultBuffer); } - Port::omrfile_findclose(handle); + freeEntryNames(&entries, entryCount); return RC_OK; failed: - Port::omrfile_findclose(handle); + if (PORT_INVALID_FIND_FILE_HANDLE != handle) { + Port::omrfile_findclose(handle); + } Port::omrmem_free((void **)&resultBuffer); + freeEntryNames(&entries, entryCount); return RC_FAILED; } ++++++ reproducible-tznames-order.patch ++++++ From: Bernhard M. Wiedemann <[email protected]> Subject: Emit CLDR short timezone aliases in deterministic order ZoneId.SHORT_IDS is an immutable Map.of() map, and iteration order of those is randomized per JVM run. extractZoneNames inserts the alias entries into the bundle map in that iteration order, and aliases whose keys land in the same hash bucket ("PST" and "AET") keep their insertion order in the bucket chain, so the entry order in a generated TimeZoneNames_*.java flips between builds. Sort the aliases before inserting them. Signed-off-by: Bernhard M. Wiedemann <[email protected]> --- a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java @@ -719,8 +719,12 @@ } // Finally some compatibility stuff + // ZoneId.SHORT_IDS is an immutable map whose iteration order changes + // from run to run; sort so that same-bucket keys always end up in the + // same chain order in the generated TimeZoneNames maps. ZoneId.SHORT_IDS.entrySet().stream() .filter(e -> !names.containsKey(e.getKey()) && names.containsKey(e.getValue())) + .sorted(Map.Entry.comparingByKey()) .forEach(e -> { names.put(e.getKey(), names.get(e.getValue())); });
