You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sl...@apache.org on 2026/10/18 21:52:19 UTC

(maven-mvnd) branch mvnd-1.x updated: Compile with --release instead of -source/-target

This is an automated email from the ASF dual-hosted git repository.

slachiewicz pushed a commit to branch mvnd-1.x
in repository https://gitbox.apache.org/repos/asf/maven-mvnd.git


The following commit(s) were added to refs/heads/mvnd-1.x by this push:
     new a3a7e76c Compile with --release instead of -source/-target
a3a7e76c is described below

commit a3a7e76c2111f58a8ee6160a2525016a35cb5fe1
Author: Sylwester Lachiewicz <sl...@apache.org>
AuthorDate: Wed Sep 23 00:41:39 2026 +0200

    Compile with --release instead of -source/-target
    
    sun.misc.Signal (SignalHelper) and com.sun.nio.file.SensitivityWatchEventModifier
    (WatchServiceCacheFactory) were used directly, which requires -source/-target:
    internal APIs are not reachable when compiling with --release. Access both
    reflectively and enable maven.compiler.release so javac checks the code against
    the Java 8 API image instead of the build JDK's bootclasspath. This also removes
    the 'source/target value 8 is obsolete' and 'bootstrap class path not set'
    warnings and makes the Java 9+ API usage in mvnd-common tests visible (and
    fixes it).
    
    This reverts the maven.compiler.release undefining introduced when upgrading
    to maven-parent 47.
---
 build-plugin/pom.xml                               |  1 +
 common/pom.xml                                     |  5 --
 .../org/mvndaemon/mvnd/common/SignalHelper.java    | 16 +++++-
 .../mvndaemon/mvnd/common/DaemonRegistryTest.java  | 62 +++++++++++++---------
 .../org/mvndaemon/mvnd/common/RegistryMutator.java |  6 +--
 daemon/pom.xml                                     |  5 --
 .../mvnd/cache/impl/WatchServiceCacheFactory.java  | 25 ++++++---
 dist/pom.xml                                       |  1 +
 integration-tests/pom.xml                          |  1 +
 pom.xml                                            |  4 +-
 10 files changed, 78 insertions(+), 48 deletions(-)

diff --git a/build-plugin/pom.xml b/build-plugin/pom.xml
index 570cd516..7241de62 100644
--- a/build-plugin/pom.xml
+++ b/build-plugin/pom.xml
@@ -33,6 +33,7 @@
   <properties>
     <maven.compiler.target>11</maven.compiler.target>
     <maven.compiler.source>11</maven.compiler.source>
+    <maven.compiler.release>11</maven.compiler.release>
   </properties>
 
   <dependencies>
diff --git a/common/pom.xml b/common/pom.xml
index a6f0de91..1dd650ae 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -30,11 +30,6 @@
   <packaging>jar</packaging>
   <name>Maven Daemon - Common</name>
 
-  <properties>
-    <!-- If using release, sun.misc is not reachable (see SignalHelper) -->
-    <maven.compiler.release />
-  </properties>
-
   <dependencies>
 
     <dependency>
diff --git a/common/src/main/java/org/mvndaemon/mvnd/common/SignalHelper.java b/common/src/main/java/org/mvndaemon/mvnd/common/SignalHelper.java
index bf9ce527..5c028c3d 100644
--- a/common/src/main/java/org/mvndaemon/mvnd/common/SignalHelper.java
+++ b/common/src/main/java/org/mvndaemon/mvnd/common/SignalHelper.java
@@ -24,9 +24,21 @@ public class SignalHelper {
      * Ignore signals to that stopping the mvnd client won't stop the daemon
      */
     public static void ignoreStopSignals() throws Exception {
-        sun.misc.Signal.handle(new sun.misc.Signal("INT"), sun.misc.SignalHandler.SIG_IGN);
+        handle("INT");
         if (Os.current() != Os.WINDOWS) {
-            sun.misc.Signal.handle(new sun.misc.Signal("TSTP"), sun.misc.SignalHandler.SIG_IGN);
+            handle("TSTP");
         }
     }
+
+    /**
+     * Equivalent of {@code sun.misc.Signal.handle(new sun.misc.Signal(signal), sun.misc.SignalHandler.SIG_IGN)},
+     * done reflectively because {@code sun.misc} is not reachable when compiling with {@code --release}.
+     */
+    private static void handle(String signal) throws Exception {
+        Class<?> signalClass = Class.forName("sun.misc.Signal");
+        Class<?> handlerClass = Class.forName("sun.misc.SignalHandler");
+        Object sigIgn = handlerClass.getField("SIG_IGN").get(null);
+        Object sig = signalClass.getConstructor(String.class).newInstance(signal);
+        signalClass.getMethod("handle", signalClass, handlerClass).invoke(null, sig, sigIgn);
+    }
 }
diff --git a/common/src/test/java/org/mvndaemon/mvnd/common/DaemonRegistryTest.java b/common/src/test/java/org/mvndaemon/mvnd/common/DaemonRegistryTest.java
index 2d2ffd4d..197f6a7d 100644
--- a/common/src/test/java/org/mvndaemon/mvnd/common/DaemonRegistryTest.java
+++ b/common/src/test/java/org/mvndaemon/mvnd/common/DaemonRegistryTest.java
@@ -22,6 +22,7 @@ import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.PrintStream;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.attribute.PosixFilePermissions;
@@ -34,6 +35,7 @@ import java.util.Random;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
 import org.junit.jupiter.api.AfterEach;
@@ -164,7 +166,7 @@ public class DaemonRegistryTest {
             reg1.storeStopEvent(new DaemonStopEvent(
                     "11111", System.currentTimeMillis(), DaemonExpirationStatus.QUIET_EXPIRE, "because"));
             assertEquals(1, reg1.doGetDaemonStopEvents().size());
-            Files.writeString(temp, "Foobar");
+            Files.write(temp, "Foobar".getBytes(StandardCharsets.UTF_8));
             // check if registry is reset
             assertEquals(0, reg1.getAll().size());
             assertEquals(0, reg1.doGetDaemonStopEvents().size());
@@ -197,7 +199,7 @@ public class DaemonRegistryTest {
                                         System.currentTimeMillis()));
                             }
                         }))
-                        .toList()
+                        .collect(Collectors.toList())
                         .toArray(new CompletableFuture[0]))
                 .get();
 
@@ -218,7 +220,7 @@ public class DaemonRegistryTest {
                                 reg.remove(info.getId());
                             }
                         }))
-                        .toList()
+                        .collect(Collectors.toList())
                         .toArray(new CompletableFuture[0]))
                 .get();
 
@@ -237,20 +239,26 @@ public class DaemonRegistryTest {
         CompletableFuture.allOf(IntStream.range(0, nbDaemons)
                         .mapToObj(i -> {
                             try {
-                                return new ProcessBuilder(
-                                                "java",
-                                                "-cp",
-                                                System.getProperty("java.class.path"),
-                                                "org.mvndaemon.mvnd.common.RegistryMutator",
-                                                "add",
-                                                temp.toString())
-                                        .start()
-                                        .onExit();
+                                return CompletableFuture.runAsync(() -> {
+                                    try {
+                                        new ProcessBuilder(
+                                                        "java",
+                                                        "-cp",
+                                                        System.getProperty("java.class.path"),
+                                                        "org.mvndaemon.mvnd.common.RegistryMutator",
+                                                        "add",
+                                                        temp.toString())
+                                                .start()
+                                                .waitFor();
+                                    } catch (Exception e) {
+                                        throw new RuntimeException(e);
+                                    }
+                                });
                             } catch (Exception e) {
                                 throw new RuntimeException(e);
                             }
                         })
-                        .toList()
+                        .collect(Collectors.toList())
                         .toArray(new CompletableFuture[0]))
                 .get();
 
@@ -268,21 +276,27 @@ public class DaemonRegistryTest {
         CompletableFuture.allOf(toRemove.stream()
                         .map(info -> {
                             try {
-                                return new ProcessBuilder(
-                                                "java",
-                                                "-cp",
-                                                System.getProperty("java.class.path"),
-                                                "org.mvndaemon.mvnd.common.RegistryMutator",
-                                                "remove",
-                                                temp.toString(),
-                                                info.getId())
-                                        .start()
-                                        .onExit();
+                                return CompletableFuture.runAsync(() -> {
+                                    try {
+                                        new ProcessBuilder(
+                                                        "java",
+                                                        "-cp",
+                                                        System.getProperty("java.class.path"),
+                                                        "org.mvndaemon.mvnd.common.RegistryMutator",
+                                                        "remove",
+                                                        temp.toString(),
+                                                        info.getId())
+                                                .start()
+                                                .waitFor();
+                                    } catch (Exception e) {
+                                        throw new RuntimeException(e);
+                                    }
+                                });
                             } catch (Exception e) {
                                 throw new RuntimeException(e);
                             }
                         })
-                        .toList()
+                        .collect(Collectors.toList())
                         .toArray(new CompletableFuture[0]))
                 .get();
 
diff --git a/common/src/test/java/org/mvndaemon/mvnd/common/RegistryMutator.java b/common/src/test/java/org/mvndaemon/mvnd/common/RegistryMutator.java
index 92cc4cc2..02f65aea 100644
--- a/common/src/test/java/org/mvndaemon/mvnd/common/RegistryMutator.java
+++ b/common/src/test/java/org/mvndaemon/mvnd/common/RegistryMutator.java
@@ -18,7 +18,7 @@
  */
 package org.mvndaemon.mvnd.common;
 
-import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Collections;
 import java.util.Locale;
 import java.util.Random;
@@ -31,7 +31,7 @@ public class RegistryMutator {
     public static void main(String[] args) {
         Random random = new Random();
         if (args[0].equals("add")) {
-            try (DaemonRegistry reg = new DaemonRegistry(Path.of(args[1]))) {
+            try (DaemonRegistry reg = new DaemonRegistry(Paths.get(args[1]))) {
                 byte[] token = new byte[16];
                 random.nextBytes(token);
                 reg.store(new DaemonInfo(
@@ -48,7 +48,7 @@ public class RegistryMutator {
                         System.currentTimeMillis()));
             }
         } else {
-            try (DaemonRegistry reg = new DaemonRegistry(Path.of(args[1]))) {
+            try (DaemonRegistry reg = new DaemonRegistry(Paths.get(args[1]))) {
                 reg.remove(args[2]);
             }
         }
diff --git a/daemon/pom.xml b/daemon/pom.xml
index 94f04685..52d48f7a 100644
--- a/daemon/pom.xml
+++ b/daemon/pom.xml
@@ -30,11 +30,6 @@
   <packaging>jar</packaging>
   <name>Maven Daemon - Daemon</name>
 
-  <properties>
-    <!-- If using release, sun.misc is not reachable (see SignalHelper) -->
-    <maven.compiler.release />
-  </properties>
-
   <dependencies>
     <dependency>
       <groupId>org.apache.maven.daemon</groupId>
diff --git a/daemon/src/main/java/org/mvndaemon/mvnd/cache/impl/WatchServiceCacheFactory.java b/daemon/src/main/java/org/mvndaemon/mvnd/cache/impl/WatchServiceCacheFactory.java
index e8ab45ca..678a824a 100644
--- a/daemon/src/main/java/org/mvndaemon/mvnd/cache/impl/WatchServiceCacheFactory.java
+++ b/daemon/src/main/java/org/mvndaemon/mvnd/cache/impl/WatchServiceCacheFactory.java
@@ -49,6 +49,23 @@ public class WatchServiceCacheFactory implements CacheFactory {
 
     private static final Logger LOG = LoggerFactory.getLogger(WatchServiceCacheFactory.class);
 
+    /**
+     * {@link com.sun.nio.file.SensitivityWatchEventModifier#HIGH}, loaded reflectively because the type is internal
+     * proprietary API and thus not reachable when compiling with {@code --release}.
+     */
+    private static final WatchEvent.Modifier[] SENSITIVITY_MODIFIERS = sensitivityModifiers();
+
+    private static WatchEvent.Modifier[] sensitivityModifiers() {
+        try {
+            Object high = Class.forName("com.sun.nio.file.SensitivityWatchEventModifier")
+                    .getField("HIGH")
+                    .get(null);
+            return new WatchEvent.Modifier[] {(WatchEvent.Modifier) high};
+        } catch (Throwable t) {
+            return null;
+        }
+    }
+
     private final WatchService watchService;
 
     /**
@@ -95,18 +112,12 @@ public class WatchServiceCacheFactory implements CacheFactory {
         if (value == null) {
             LOG.debug("Starting to watch path {}", key);
             try {
-                WatchEvent.Modifier[] mods;
-                try {
-                    mods = new WatchEvent.Modifier[] {com.sun.nio.file.SensitivityWatchEventModifier.HIGH};
-                } catch (Throwable t) {
-                    mods = null;
-                }
                 final WatchKey watchKey = key.register(
                         watchService,
                         new WatchEvent.Kind[] {
                             StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY
                         },
-                        mods);
+                        SENSITIVITY_MODIFIERS);
                 return new Registration(watchKey);
             } catch (NoSuchFileException e) {
                 // we allow this exception in case of a missing reactor artifact
diff --git a/dist/pom.xml b/dist/pom.xml
index 1ccdcc85..d745eeca 100644
--- a/dist/pom.xml
+++ b/dist/pom.xml
@@ -33,6 +33,7 @@
   <properties>
     <maven.compiler.target>11</maven.compiler.target>
     <maven.compiler.source>11</maven.compiler.source>
+    <maven.compiler.release>11</maven.compiler.release>
   </properties>
 
   <dependencies>
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 23e48484..0e77d851 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -32,6 +32,7 @@
   <properties>
     <maven.compiler.target>11</maven.compiler.target>
     <maven.compiler.source>11</maven.compiler.source>
+    <maven.compiler.release>11</maven.compiler.release>
     <mvnd.home>${project.basedir}/../dist/target/maven-mvnd-${project.version}-${os.detected.name}-${os.detected.arch}</mvnd.home>
     <preinstall.artifacts>org/apache/maven/surefire/surefire-providers/${surefire.version}
             org/apache/maven/surefire/surefire-junit-platform/${surefire.version}
diff --git a/pom.xml b/pom.xml
index 525ec148..07273b39 100644
--- a/pom.xml
+++ b/pom.xml
@@ -68,8 +68,8 @@
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <maven.compiler.target>8</maven.compiler.target>
     <maven.compiler.source>8</maven.compiler.source>
-    <!-- parent profile defines this; undefine -->
-    <maven.compiler.release />
+    <!-- source/target kept for bytecode checks; compilation is driven via the release flag -->
+    <maven.compiler.release>8</maven.compiler.release>
     <maven-dist.required.jdk>8</maven-dist.required.jdk>
     <project.build.outputTimestamp>2026-05-27T20:12:56Z</project.build.outputTimestamp>
     <trimStackTrace>false</trimStackTrace>