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()));
             });

Reply via email to