diff --git a/CHANGELOG.md b/CHANGELOG.md index fc2c393a130..23eab9423b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Currently the versioning policy of this project follows [Semantic Versioning v2. - Bump up logback to `1.4.0` - Bump up log4j2 binding to `2.18.0` - Fixed InvalidInputException in Eclipse while bug reporting ([#2134](https://github.com/spotbugs/spotbugs/issues/2134)) +- Avoid warning on use of security manager on Java 17 and newer. ([#1579](https://github.com/spotbugs/spotbugs/issues/1579)) - Fixed false positives `EI_EXPOSE_REP` thrown in case of fields initialized by the `of` or `copyOf` method of a `List`, `Map` or `Set` ([#1771](https://github.com/spotbugs/spotbugs/issues/1771)) - Fixed CFGBuilderException thrown when `dup_x2` is used to swap the reference and wide-value (double, long) in the stack ([#2146](https://github.com/spotbugs/spotbugs/pull/2146)) diff --git a/spotbugs/src/main/java/edu/umd/cs/findbugs/PluginLoader.java b/spotbugs/src/main/java/edu/umd/cs/findbugs/PluginLoader.java index c7ccafbe2d5..b539263c387 100644 --- a/spotbugs/src/main/java/edu/umd/cs/findbugs/PluginLoader.java +++ b/spotbugs/src/main/java/edu/umd/cs/findbugs/PluginLoader.java @@ -58,6 +58,7 @@ import javax.annotation.Nullable; import javax.annotation.WillClose; +import edu.umd.cs.findbugs.util.SecurityManagerHandler; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; @@ -1472,7 +1473,7 @@ static synchronized void loadInitialPlugins() { // Thread.currentThread().getContextClassLoader().getResource("my.java.policy"); // Policy.getPolicy().refresh(); try { - System.setSecurityManager(null); + SecurityManagerHandler.disableSecurityManager(); } catch (Throwable e) { assert true; // keep going } diff --git a/spotbugs/src/main/java/edu/umd/cs/findbugs/util/SecurityManagerHandler.java b/spotbugs/src/main/java/edu/umd/cs/findbugs/util/SecurityManagerHandler.java new file mode 100644 index 00000000000..0418ba11f3a --- /dev/null +++ b/spotbugs/src/main/java/edu/umd/cs/findbugs/util/SecurityManagerHandler.java @@ -0,0 +1,65 @@ +package edu.umd.cs.findbugs.util; + +import org.apache.commons.lang3.JavaVersion; +import org.apache.commons.lang3.SystemUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Since Java 17, the security manager is deprecated for removal and invoking related methods + * causes a warning to be printed to the console. This intermediate disables the use of + * security manager-related APIs on Java 17 or later, unless using the security manager is + * explicitly configured by setting the edu.umd.cs.findbugs.securityManagerDisabled + * property. + */ +public class SecurityManagerHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(SecurityManagerHandler.class); + + /** + * Determines if the security manager is used by SpotBugs. + */ + private static final boolean SECURITY_MANAGER_DISABLED; + + static { + boolean securityManagerDisabled; + try { + String property = System.getProperty("edu.umd.cs.findbugs.securityManagerDisabled"); + if (property != null) { + securityManagerDisabled = Boolean.parseBoolean(property); + } else { + securityManagerDisabled = SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_17); + } + } catch (Throwable t) { + securityManagerDisabled = false; + LOGGER.debug("failed to detect the ability of security manager feature, so treat it as available", t); + } + SECURITY_MANAGER_DISABLED = securityManagerDisabled; + } + + /** + * Disables the security manager by setting {@link System#setSecurityManager(SecurityManager)} + * to {@code null}. + */ + public static void disableSecurityManager() { + if (SECURITY_MANAGER_DISABLED) { + return; + } + doDisableSecurityManager(); + } + + /** + * This method is a safeguard for running this library on a JVM that might no longer include + * the security manager API after removal. As the JVM verifies methods lazily, and since this + * method will never be invoked, validation of this method with a missing type can never fail. + * + * As some environments do not support setting the security manager but always return null + * when getting it, we check if a security manager is set before disabling it. + */ + private static void doDisableSecurityManager() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + System.setSecurityManager(null); + } + } +}