diff --git a/src/main/java/org/openrewrite/java/migrate/SimplifySecurityManagerThreadGroup.java b/src/main/java/org/openrewrite/java/migrate/SimplifySecurityManagerThreadGroup.java
new file mode 100644
index 0000000000..1bc3bd14ab
--- /dev/null
+++ b/src/main/java/org/openrewrite/java/migrate/SimplifySecurityManagerThreadGroup.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2026 the original author or authors.
+ *
+ * Licensed under the Moderne Source Available License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://docs.moderne.io/licensing/moderne-source-available-license
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.openrewrite.java.migrate;
+
+import lombok.EqualsAndHashCode;
+import lombok.Value;
+import org.openrewrite.ExecutionContext;
+import org.openrewrite.Preconditions;
+import org.openrewrite.Recipe;
+import org.openrewrite.TreeVisitor;
+import org.openrewrite.java.JavaIsoVisitor;
+import org.openrewrite.java.search.UsesJavaVersion;
+import org.openrewrite.java.tree.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+@Value
+@EqualsAndHashCode(callSuper = false)
+public class SimplifySecurityManagerThreadGroup extends Recipe {
+ String displayName = "Simplify the removed security manager's thread group fallback";
+ String description = "Remove a null SecurityManager local used only by the immediately following thread group conditional.";
+
+ @Override
+ public TreeVisitor, ExecutionContext> getVisitor() {
+ return Preconditions.check(new UsesJavaVersion<>(25), new JavaIsoVisitor() {
+ @Override
+ public J.Block visitBlock(J.Block block, ExecutionContext ctx) {
+ J.Block b = super.visitBlock(block, ctx);
+ List statements = new ArrayList<>(b.getStatements());
+ for (int i = 0; i + 1 < statements.size(); i++) {
+ if (!(statements.get(i) instanceof J.VariableDeclarations) ||
+ !(statements.get(i + 1) instanceof J.Assignment)) {
+ continue;
+ }
+ J.VariableDeclarations declaration = (J.VariableDeclarations) statements.get(i);
+ if (declaration.getVariables().size() != 1 || !declaration.getComments().isEmpty() ||
+ !TypeUtils.isOfClassType(declaration.getType(), "java.lang.SecurityManager")) {
+ continue;
+ }
+ J.VariableDeclarations.NamedVariable variable = declaration.getVariables().get(0);
+ if (!J.Literal.isLiteralValue(variable.getInitializer(), null) || variable.getVariableType() == null) {
+ continue;
+ }
+ J.Assignment assignment = (J.Assignment) statements.get(i + 1);
+ if (!(assignment.getAssignment() instanceof J.Ternary)) {
+ continue;
+ }
+ J.Ternary ternary = (J.Ternary) assignment.getAssignment();
+ Expression condition = ternary.getCondition().unwrap();
+ if (!(condition instanceof J.Binary)) {
+ continue;
+ }
+ J.Binary binary = (J.Binary) condition;
+ if (binary.getOperator() != J.Binary.Type.NotEqual ||
+ !sameVariable(binary.getLeft(), variable) || !J.Literal.isLiteralValue(binary.getRight(), null) ||
+ !(ternary.getTruePart() instanceof J.MethodInvocation)) {
+ continue;
+ }
+ J.MethodInvocation method = (J.MethodInvocation) ternary.getTruePart();
+ if (!"getThreadGroup".equals(method.getSimpleName()) || !sameVariable(method.getSelect(), variable)) {
+ continue;
+ }
+ AtomicInteger references = new AtomicInteger();
+ new JavaIsoVisitor() {
+ @Override
+ public J.Identifier visitIdentifier(J.Identifier identifier, AtomicInteger count) {
+ if (sameVariable(identifier, variable) && !identifier.getId().equals(variable.getName().getId())) {
+ count.incrementAndGet();
+ }
+ return identifier;
+ }
+ }.visit(b, references);
+ if (references.get() != 2 || hasComments(declaration) || hasComments(ternary)) {
+ continue;
+ }
+ statements.set(i + 1, assignment.withAssignment(ternary.getFalsePart().withPrefix(ternary.getPrefix())));
+ statements.remove(i--);
+ }
+ return b.withStatements(statements);
+ }
+
+ private boolean hasComments(J tree) {
+ AtomicBoolean found = new AtomicBoolean();
+ new JavaIsoVisitor() {
+ @Override
+ public Space visitSpace(Space space, Space.Location location, AtomicBoolean comments) {
+ if (!space.getComments().isEmpty()) {
+ comments.set(true);
+ }
+ return space;
+ }
+ }.visit(tree, found);
+ return found.get();
+ }
+
+ private boolean sameVariable(Expression expression, J.VariableDeclarations.NamedVariable variable) {
+ return expression instanceof J.Identifier && variable.getVariableType().equals(((J.Identifier) expression).getFieldType());
+ }
+ });
+ }
+}
diff --git a/src/main/resources/META-INF/rewrite/java-version-25.yml b/src/main/resources/META-INF/rewrite/java-version-25.yml
index 2868f3316a..f0bfd44948 100644
--- a/src/main/resources/META-INF/rewrite/java-version-25.yml
+++ b/src/main/resources/META-INF/rewrite/java-version-25.yml
@@ -150,6 +150,7 @@ recipeList:
- org.openrewrite.java.ReplaceMethodInvocationWithConstant:
methodPattern: java.lang.System#getSecurityManager()
replacement: "null"
+ - org.openrewrite.java.migrate.SimplifySecurityManagerThreadGroup
- org.openrewrite.staticanalysis.SimplifyConstantIfBranchExecution
---
diff --git a/src/main/resources/META-INF/rewrite/recipes.csv b/src/main/resources/META-INF/rewrite/recipes.csv
index 367d785df4..1d21048a3b 100644
--- a/src/main/resources/META-INF/rewrite/recipes.csv
+++ b/src/main/resources/META-INF/rewrite/recipes.csv
@@ -53,7 +53,7 @@ maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.J
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.JREThrowableFinalMethods,Rename final method declarations `getSuppressed()` and `addSuppressed(Throwable exception)` in classes that extend `Throwable`,The recipe renames `getSuppressed()` and `addSuppressed(Throwable exception)` methods in classes that extend `java.lang.Throwable` to `myGetSuppressed` and `myAddSuppressed(Throwable)`. These methods were added to Throwable in Java 7 and are marked final which cannot be overridden.,1,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.JREWrapperInterface,Add missing `isWrapperFor` and `unwrap` methods,Add method implementations stubs to classes that implement `java.sql.Wrapper`.,3,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.Java8toJava11,Migrate to Java 11,"This recipe will apply changes commonly needed when upgrading to Java 11. Specifically, for those applications that are built on Java 8, this recipe will update and add dependencies on J2EE libraries that are no longer directly bundled with the JDK. This recipe will also replace deprecated API with equivalents when there is a clear migration strategy. Build files will also be updated to use Java 11 as the target/source and plugins will be also be upgraded to versions that are compatible with Java 11.",310,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,"[{""name"":""org.openrewrite.maven.table.MavenMetadataFailures"",""displayName"":""Maven metadata failures"",""instanceName"":""Maven metadata failures"",""description"":""Attempts to resolve maven metadata that failed."",""columns"":[{""name"":""group"",""type"":""String"",""displayName"":""Group id"",""description"":""The groupId of the artifact for which the metadata download failed.""},{""name"":""artifactId"",""type"":""String"",""displayName"":""Artifact id"",""description"":""The artifactId of the artifact for which the metadata download failed.""},{""name"":""version"",""type"":""String"",""displayName"":""Version"",""description"":""The version of the artifact for which the metadata download failed.""},{""name"":""mavenRepositoryUri"",""type"":""String"",""displayName"":""Maven repository"",""description"":""The URL of the Maven repository that the metadata download failed on.""},{""name"":""snapshots"",""type"":""String"",""displayName"":""Snapshots"",""description"":""Does the repository support snapshots.""},{""name"":""releases"",""type"":""String"",""displayName"":""Releases"",""description"":""Does the repository support releases.""},{""name"":""failure"",""type"":""String"",""displayName"":""Failure"",""description"":""The reason the metadata download failed.""}]}]"
-maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.JavaBestPractices,Java best practices,"Applies opinionated best practices for Java projects targeting Java 25. This recipe includes the full Java 25 upgrade chain plus additional improvements to code style, API usage, and third-party dependency reduction that go beyond what the version migration recipes apply.",895,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,"[{""name"":""org.openrewrite.maven.table.MavenMetadataFailures"",""displayName"":""Maven metadata failures"",""instanceName"":""Maven metadata failures"",""description"":""Attempts to resolve maven metadata that failed."",""columns"":[{""name"":""group"",""type"":""String"",""displayName"":""Group id"",""description"":""The groupId of the artifact for which the metadata download failed.""},{""name"":""artifactId"",""type"":""String"",""displayName"":""Artifact id"",""description"":""The artifactId of the artifact for which the metadata download failed.""},{""name"":""version"",""type"":""String"",""displayName"":""Version"",""description"":""The version of the artifact for which the metadata download failed.""},{""name"":""mavenRepositoryUri"",""type"":""String"",""displayName"":""Maven repository"",""description"":""The URL of the Maven repository that the metadata download failed on.""},{""name"":""snapshots"",""type"":""String"",""displayName"":""Snapshots"",""description"":""Does the repository support snapshots.""},{""name"":""releases"",""type"":""String"",""displayName"":""Releases"",""description"":""Does the repository support releases.""},{""name"":""failure"",""type"":""String"",""displayName"":""Failure"",""description"":""The reason the metadata download failed.""}]}]"
+maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.JavaBestPractices,Java best practices,"Applies opinionated best practices for Java projects targeting Java 25. This recipe includes the full Java 25 upgrade chain plus additional improvements to code style, API usage, and third-party dependency reduction that go beyond what the version migration recipes apply.",896,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,"[{""name"":""org.openrewrite.maven.table.MavenMetadataFailures"",""displayName"":""Maven metadata failures"",""instanceName"":""Maven metadata failures"",""description"":""Attempts to resolve maven metadata that failed."",""columns"":[{""name"":""group"",""type"":""String"",""displayName"":""Group id"",""description"":""The groupId of the artifact for which the metadata download failed.""},{""name"":""artifactId"",""type"":""String"",""displayName"":""Artifact id"",""description"":""The artifactId of the artifact for which the metadata download failed.""},{""name"":""version"",""type"":""String"",""displayName"":""Version"",""description"":""The version of the artifact for which the metadata download failed.""},{""name"":""mavenRepositoryUri"",""type"":""String"",""displayName"":""Maven repository"",""description"":""The URL of the Maven repository that the metadata download failed on.""},{""name"":""snapshots"",""type"":""String"",""displayName"":""Snapshots"",""description"":""Does the repository support snapshots.""},{""name"":""releases"",""type"":""String"",""displayName"":""Releases"",""description"":""Does the repository support releases.""},{""name"":""failure"",""type"":""String"",""displayName"":""Failure"",""description"":""The reason the metadata download failed.""}]}]"
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.JpaCacheProperties,Disable the persistence unit second-level cache,Sets an explicit value for the shared cache mode.,1,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.Jre17AgentMainPreMainPublic,Set visibility of `premain` and `agentmain` methods to `public`,Check for a behavior change in Java agents.,5,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.Krb5LoginModuleClass,Use `com.sun.security.auth.module.Krb5LoginModule` instead of `com.ibm.security.auth.module.Krb5LoginModule`,Do not use the `com.ibm.security.auth.module.Krb5LoginModule` class.,2,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
@@ -82,9 +82,10 @@ maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.R
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.ReplaceComSunAWTUtilitiesMethods,Replace `com.sun.awt.AWTUtilities` static method invocations,"This recipe replaces several static calls in `com.sun.awt.AWTUtilities` with the JavaSE 11 equivalent. The methods replaced are `AWTUtilities.isTranslucencySupported()`, `AWTUtilities.setWindowOpacity()`, `AWTUtilities.getWindowOpacity()`, `AWTUtilities.getWindowShape()`, `AWTUtilities.isWindowOpaque()`, `AWTUtilities.isTranslucencyCapable()` and `AWTUtilities.setComponentMixingCutoutShape()`.",1,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,"[{""name"":""getAWTIsWindowsTranslucencyPattern"",""type"":""String"",""displayName"":""Method pattern to replace"",""description"":""The method pattern to match and replace."",""example"":""com.sun.awt.AWTUtilities isTranslucencySupported(com.sun.awt.AWTUtilities.Translucency)"",""value"":""com.sun.awt.AWTUtilities isTranslucencySupported(com.sun.awt.AWTUtilities.Translucency)""},{""name"":""isWindowOpaquePattern"",""type"":""String"",""displayName"":""Method pattern to replace"",""description"":""The method pattern to match and replace."",""example"":""com.test.AWTUtilities isWindowOpaque(java.awt.Window)"",""value"":""com.sun.awt.AWTUtilities isWindowOpaque(java.awt.Window)""},{""name"":""isTranslucencyCapablePattern"",""type"":""String"",""displayName"":""Method pattern to replace"",""description"":""The method pattern to match and replace."",""example"":""com.test.AWTUtilities isTranslucencyCapable(java.awt.GraphicsConfiguration)"",""value"":""com.sun.awt.AWTUtilities isTranslucencyCapable(java.awt.GraphicsConfiguration)""},{""name"":""setWindowOpacityPattern"",""type"":""String"",""displayName"":""Method pattern to replace"",""description"":""The method pattern to match and replace."",""example"":""com.test.AWTUtilities setWindowOpacity(java.awt.Window, float)"",""value"":""com.sun.awt.AWTUtilities setWindowOpacity(java.awt.Window, float)""},{""name"":""getWindowOpacityPattern"",""type"":""String"",""displayName"":""Method pattern to replace"",""description"":""The method pattern to match and replace."",""example"":""com.test.AWTUtilities getWindowOpacity(java.awt.Window)"",""value"":""com.sun.awt.AWTUtilities getWindowOpacity(java.awt.Window)""},{""name"":""getWindowShapePattern"",""type"":""String"",""displayName"":""Method pattern to replace"",""description"":""The method pattern to match and replace."",""example"":""com.test.AWTUtilitiesTest getWindowShape(java.awt.Window)"",""value"":""com.sun.awt.AWTUtilities getWindowShape(java.awt.Window)""},{""name"":""setComponentMixingCutoutShapePattern"",""type"":""String"",""displayName"":""Method pattern to replace"",""description"":""The method pattern to match and replace."",""example"":""com.test.AWTUtilities setComponentMixingCutoutShape(java.awt.Component,java.awt.Shape)"",""value"":""com.sun.awt.AWTUtilities setComponentMixingCutoutShape(java.awt.Component,java.awt.Shape)""}]",
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.ReplaceLocalizedStreamMethods,Replace `getLocalizedInputStream` and `getLocalizedOutputStream` with direct assignment,Replaces `Runtime.getLocalizedInputStream(InputStream)` and `Runtime.getLocalizedOutputStream(OutputStream)` with their direct arguments. This modification is made because the previous implementation of `getLocalizedInputStream` and `getLocalizedOutputStream` merely returned the arguments provided.,1,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,"[{""name"":""localizedInputStreamMethodMatcher"",""type"":""String"",""displayName"":""Method pattern to replace"",""description"":""The method pattern to match and replace."",""example"":""java.lang.Runtime getLocalizedInputStream(java.io.InputStream)"",""value"":""java.lang.Runtime getLocalizedInputStream(java.io.InputStream)""},{""name"":""localizedOutputStreamMethodMatcher"",""type"":""String"",""displayName"":""Method pattern to replace"",""description"":""The method pattern to match and replace."",""example"":""java.lang.Runtime getLocalizedOutputStream(java.io.OutputStream)"",""value"":""java.lang.Runtime getLocalizedOutputStream(java.io.OutputStream)""}]",
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.ReplaceStringLiteralValue,Replace `String` literal,Replace the value of a complete `String` literal.,2,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,"[{""name"":""oldLiteralValue"",""type"":""String"",""displayName"":""Old literal `String` value"",""description"":""The `String` value to replace."",""example"":""apple"",""required"":true},{""name"":""newLiteralValue"",""type"":""String"",""displayName"":""New literal `String` value"",""description"":""The `String` value to replace with."",""example"":""orange"",""required"":true}]",
+maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.SimplifySecurityManagerThreadGroup,Simplify the removed security manager's thread group fallback,Remove a null SecurityManager local used only by the immediately following thread group conditional.,1,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.SunNetSslPackageUnavailable,Replace `com.sun.net.ssl` package,The internal API `com.sun.net.ssl` is removed. The package was intended for internal use only and replacement APIs can be found in the `javax.net.ssl` package.,2,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.SwitchPatternMatching,Adopt switch pattern matching (JEP 441),[JEP 441](https://openjdk.org/jeps/441) describes how some switch statements can be improved with pattern matching. This recipe applies some of those improvements where applicable.,3,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
-maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.SystemGetSecurityManagerToNull,Replace `System.getSecurityManager()` with `null`,The Security Manager API is unsupported in Java 24. This recipe will replace `System.getSecurityManager()` with `null` to make its behavior more obvious and try to simplify execution paths afterwards.,3,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
+maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.SystemGetSecurityManagerToNull,Replace `System.getSecurityManager()` with `null`,The Security Manager API is unsupported in Java 24. This recipe will replace `System.getSecurityManager()` with `null` to make its behavior more obvious and try to simplify execution paths afterwards.,4,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.ThreadStopDestroy,Remove `Thread.destroy()` and `Thread.stop(Throwable)`,"The `java.lang.Thread.destroy()` method was never implemented, and the `java.lang.Thread.stop(java.lang.Throwable)` method has been unusable since Java SE 8. This recipe removes any usage of these methods from your application.",3,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.UpdateSdkMan,Update SDKMan Java version,"Update the SDKMAN JDK version in the `.sdkmanrc` file. Given a major release (e.g., 17), the recipe will update the current distribution to the current default SDKMAN version of the specified major release. The distribution option can be used to specify a specific JVM distribution. Note that these must correspond to valid SDKMAN distributions.",1,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,"[{""name"":""newVersion"",""type"":""String"",""displayName"":""Java version"",""description"":""The Java version to update to. Use `latest.patch` to upgrade to the latest version within the current major version."",""example"":""17""},{""name"":""newDistribution"",""type"":""String"",""displayName"":""Distribution"",""description"":""The JVM distribution to use."",""example"":""tem""}]",
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.UpgradeBuildToJava11,Upgrade build to Java 11,Updates build files to use Java 11 as the target/source.,10,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
@@ -104,7 +105,7 @@ maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.U
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.UpgradeSpringBootParentForJava25,Upgrade Spring Boot 3 Maven parents for Java 25,"Upgrade Spring Boot 3 Maven parents to the latest 3.5 release so that Spring's bundled ASM can read Java 25 class files. Stay within Boot 3: crossing from Boot 2 requires a separate Jakarta migration, and newer Boot major versions must not be downgraded.",2,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.UpgradeToJava17,Migrate to Java 17,"This recipe will apply changes commonly needed when migrating to Java 17. Specifically, for those applications that are built on Java 8, this recipe will update and add dependencies on J2EE libraries that are no longer directly bundled with the JDK. This recipe will also replace deprecated API with equivalents when there is a clear migration strategy. Build files will also be updated to use Java 17 as the target/source and plugins will be also be upgraded to versions that are compatible with Java 17.",384,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,"[{""name"":""org.openrewrite.maven.table.MavenMetadataFailures"",""displayName"":""Maven metadata failures"",""instanceName"":""Maven metadata failures"",""description"":""Attempts to resolve maven metadata that failed."",""columns"":[{""name"":""group"",""type"":""String"",""displayName"":""Group id"",""description"":""The groupId of the artifact for which the metadata download failed.""},{""name"":""artifactId"",""type"":""String"",""displayName"":""Artifact id"",""description"":""The artifactId of the artifact for which the metadata download failed.""},{""name"":""version"",""type"":""String"",""displayName"":""Version"",""description"":""The version of the artifact for which the metadata download failed.""},{""name"":""mavenRepositoryUri"",""type"":""String"",""displayName"":""Maven repository"",""description"":""The URL of the Maven repository that the metadata download failed on.""},{""name"":""snapshots"",""type"":""String"",""displayName"":""Snapshots"",""description"":""Does the repository support snapshots.""},{""name"":""releases"",""type"":""String"",""displayName"":""Releases"",""description"":""Does the repository support releases.""},{""name"":""failure"",""type"":""String"",""displayName"":""Failure"",""description"":""The reason the metadata download failed.""}]}]"
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.UpgradeToJava21,Migrate to Java 21,This recipe will apply changes commonly needed when migrating to Java 21. This recipe will also replace deprecated API with equivalents when there is a clear migration strategy. Build files will also be updated to use Java 21 as the target/source and plugins will be also be upgraded to versions that are compatible with Java 21.,431,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,"[{""name"":""org.openrewrite.maven.table.MavenMetadataFailures"",""displayName"":""Maven metadata failures"",""instanceName"":""Maven metadata failures"",""description"":""Attempts to resolve maven metadata that failed."",""columns"":[{""name"":""group"",""type"":""String"",""displayName"":""Group id"",""description"":""The groupId of the artifact for which the metadata download failed.""},{""name"":""artifactId"",""type"":""String"",""displayName"":""Artifact id"",""description"":""The artifactId of the artifact for which the metadata download failed.""},{""name"":""version"",""type"":""String"",""displayName"":""Version"",""description"":""The version of the artifact for which the metadata download failed.""},{""name"":""mavenRepositoryUri"",""type"":""String"",""displayName"":""Maven repository"",""description"":""The URL of the Maven repository that the metadata download failed on.""},{""name"":""snapshots"",""type"":""String"",""displayName"":""Snapshots"",""description"":""Does the repository support snapshots.""},{""name"":""releases"",""type"":""String"",""displayName"":""Releases"",""description"":""Does the repository support releases.""},{""name"":""failure"",""type"":""String"",""displayName"":""Failure"",""description"":""The reason the metadata download failed.""}]}]"
-maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.UpgradeToJava25,Migrate to Java 25,This recipe will apply changes commonly needed when migrating to Java 25. This recipe will also replace deprecated API with equivalents when there is a clear migration strategy. Build files will also be updated to use Java 25 as the target/source and plugins will be also be upgraded to versions that are compatible with Java 25.,521,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,"[{""name"":""org.openrewrite.maven.table.MavenMetadataFailures"",""displayName"":""Maven metadata failures"",""instanceName"":""Maven metadata failures"",""description"":""Attempts to resolve maven metadata that failed."",""columns"":[{""name"":""group"",""type"":""String"",""displayName"":""Group id"",""description"":""The groupId of the artifact for which the metadata download failed.""},{""name"":""artifactId"",""type"":""String"",""displayName"":""Artifact id"",""description"":""The artifactId of the artifact for which the metadata download failed.""},{""name"":""version"",""type"":""String"",""displayName"":""Version"",""description"":""The version of the artifact for which the metadata download failed.""},{""name"":""mavenRepositoryUri"",""type"":""String"",""displayName"":""Maven repository"",""description"":""The URL of the Maven repository that the metadata download failed on.""},{""name"":""snapshots"",""type"":""String"",""displayName"":""Snapshots"",""description"":""Does the repository support snapshots.""},{""name"":""releases"",""type"":""String"",""displayName"":""Releases"",""description"":""Does the repository support releases.""},{""name"":""failure"",""type"":""String"",""displayName"":""Failure"",""description"":""The reason the metadata download failed.""}]}]"
+maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.UpgradeToJava25,Migrate to Java 25,This recipe will apply changes commonly needed when migrating to Java 25. This recipe will also replace deprecated API with equivalents when there is a clear migration strategy. Build files will also be updated to use Java 25 as the target/source and plugins will be also be upgraded to versions that are compatible with Java 25.,522,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,"[{""name"":""org.openrewrite.maven.table.MavenMetadataFailures"",""displayName"":""Maven metadata failures"",""instanceName"":""Maven metadata failures"",""description"":""Attempts to resolve maven metadata that failed."",""columns"":[{""name"":""group"",""type"":""String"",""displayName"":""Group id"",""description"":""The groupId of the artifact for which the metadata download failed.""},{""name"":""artifactId"",""type"":""String"",""displayName"":""Artifact id"",""description"":""The artifactId of the artifact for which the metadata download failed.""},{""name"":""version"",""type"":""String"",""displayName"":""Version"",""description"":""The version of the artifact for which the metadata download failed.""},{""name"":""mavenRepositoryUri"",""type"":""String"",""displayName"":""Maven repository"",""description"":""The URL of the Maven repository that the metadata download failed on.""},{""name"":""snapshots"",""type"":""String"",""displayName"":""Snapshots"",""description"":""Does the repository support snapshots.""},{""name"":""releases"",""type"":""String"",""displayName"":""Releases"",""description"":""Does the repository support releases.""},{""name"":""failure"",""type"":""String"",""displayName"":""Failure"",""description"":""The reason the metadata download failed.""}]}]"
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.UpgradeToJava6,Migrate to Java 6,This recipe will apply changes commonly needed when upgrading to Java 6. This recipe will also replace deprecated API with equivalents when there is a clear migration strategy.,7,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,"[{""name"":""org.openrewrite.maven.table.MavenMetadataFailures"",""displayName"":""Maven metadata failures"",""instanceName"":""Maven metadata failures"",""description"":""Attempts to resolve maven metadata that failed."",""columns"":[{""name"":""group"",""type"":""String"",""displayName"":""Group id"",""description"":""The groupId of the artifact for which the metadata download failed.""},{""name"":""artifactId"",""type"":""String"",""displayName"":""Artifact id"",""description"":""The artifactId of the artifact for which the metadata download failed.""},{""name"":""version"",""type"":""String"",""displayName"":""Version"",""description"":""The version of the artifact for which the metadata download failed.""},{""name"":""mavenRepositoryUri"",""type"":""String"",""displayName"":""Maven repository"",""description"":""The URL of the Maven repository that the metadata download failed on.""},{""name"":""snapshots"",""type"":""String"",""displayName"":""Snapshots"",""description"":""Does the repository support snapshots.""},{""name"":""releases"",""type"":""String"",""displayName"":""Releases"",""description"":""Does the repository support releases.""},{""name"":""failure"",""type"":""String"",""displayName"":""Failure"",""description"":""The reason the metadata download failed.""}]}]"
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.UpgradeToJava7,Migrate to Java 7,This recipe will apply changes commonly needed when upgrading to Java 7. This recipe will also replace deprecated API with equivalents when there is a clear migration strategy.,54,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,"[{""name"":""org.openrewrite.maven.table.MavenMetadataFailures"",""displayName"":""Maven metadata failures"",""instanceName"":""Maven metadata failures"",""description"":""Attempts to resolve maven metadata that failed."",""columns"":[{""name"":""group"",""type"":""String"",""displayName"":""Group id"",""description"":""The groupId of the artifact for which the metadata download failed.""},{""name"":""artifactId"",""type"":""String"",""displayName"":""Artifact id"",""description"":""The artifactId of the artifact for which the metadata download failed.""},{""name"":""version"",""type"":""String"",""displayName"":""Version"",""description"":""The version of the artifact for which the metadata download failed.""},{""name"":""mavenRepositoryUri"",""type"":""String"",""displayName"":""Maven repository"",""description"":""The URL of the Maven repository that the metadata download failed on.""},{""name"":""snapshots"",""type"":""String"",""displayName"":""Snapshots"",""description"":""Does the repository support snapshots.""},{""name"":""releases"",""type"":""String"",""displayName"":""Releases"",""description"":""Does the repository support releases.""},{""name"":""failure"",""type"":""String"",""displayName"":""Failure"",""description"":""The reason the metadata download failed.""}]}]"
maven,org.openrewrite.recipe:rewrite-migrate-java,org.openrewrite.java.migrate.UpgradeToJava8,Migrate to Java 8,This recipe will apply changes commonly needed when upgrading to Java 8. This recipe will also replace deprecated API with equivalents when there is a clear migration strategy.,123,,,Modernize,Java,,,Modernize your code to best use the project's current JDK version. Take advantage of newly available APIs and reduce the dependency of your code on third party dependencies where there is equivalent functionality in the Java standard library.,Basic building blocks for transforming Java code.,,"[{""name"":""org.openrewrite.maven.table.MavenMetadataFailures"",""displayName"":""Maven metadata failures"",""instanceName"":""Maven metadata failures"",""description"":""Attempts to resolve maven metadata that failed."",""columns"":[{""name"":""group"",""type"":""String"",""displayName"":""Group id"",""description"":""The groupId of the artifact for which the metadata download failed.""},{""name"":""artifactId"",""type"":""String"",""displayName"":""Artifact id"",""description"":""The artifactId of the artifact for which the metadata download failed.""},{""name"":""version"",""type"":""String"",""displayName"":""Version"",""description"":""The version of the artifact for which the metadata download failed.""},{""name"":""mavenRepositoryUri"",""type"":""String"",""displayName"":""Maven repository"",""description"":""The URL of the Maven repository that the metadata download failed on.""},{""name"":""snapshots"",""type"":""String"",""displayName"":""Snapshots"",""description"":""Does the repository support snapshots.""},{""name"":""releases"",""type"":""String"",""displayName"":""Releases"",""description"":""Does the repository support releases.""},{""name"":""failure"",""type"":""String"",""displayName"":""Failure"",""description"":""The reason the metadata download failed.""}]}]"
diff --git a/src/test/java/org/openrewrite/java/migrate/SimplifySecurityManagerThreadGroupTest.java b/src/test/java/org/openrewrite/java/migrate/SimplifySecurityManagerThreadGroupTest.java
new file mode 100644
index 0000000000..7d05152bac
--- /dev/null
+++ b/src/test/java/org/openrewrite/java/migrate/SimplifySecurityManagerThreadGroupTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2026 the original author or authors.
+ *
+ * Licensed under the Moderne Source Available License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://docs.moderne.io/licensing/moderne-source-available-license
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.openrewrite.java.migrate;
+
+import org.junit.jupiter.api.Test;
+import org.openrewrite.test.RewriteTest;
+
+import static org.openrewrite.java.Assertions.java;
+import static org.openrewrite.java.Assertions.version;
+
+class SimplifySecurityManagerThreadGroupTest implements RewriteTest {
+ @Test
+ void removeNullLocalAndDeadBranch() {
+ rewriteRun(
+ spec -> spec.recipeFromResources("org.openrewrite.java.migrate.SystemGetSecurityManagerToNull")
+ .allSources(source -> version(source, 25)),
+ java(
+ """
+ class Test {
+ ThreadGroup group;
+ Test() {
+ SecurityManager s = System.getSecurityManager();
+ group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
+ }
+ }
+ """,
+ """
+ class Test {
+ ThreadGroup group;
+ Test() {
+ group = Thread.currentThread().getThreadGroup();
+ }
+ }
+ """
+ )
+ );
+ }
+ @Test
+ void retainLocalWithAnotherUse() {
+ rewriteRun(
+ spec -> spec.recipe(new SimplifySecurityManagerThreadGroup())
+ .allSources(source -> version(source, 25)),
+ java(
+ """
+ class Test {
+ ThreadGroup group;
+ Test() {
+ SecurityManager s = null;
+ group = s != null ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
+ System.out.println(s);
+ }
+ }
+ """
+ )
+ );
+ }
+ @Test
+ void retainNestedComments() {
+ rewriteRun(
+ spec -> spec.recipe(new SimplifySecurityManagerThreadGroup())
+ .allSources(source -> version(source, 25)),
+ java(
+ """
+ class InitializerComment {
+ ThreadGroup group;
+ InitializerComment() {
+ SecurityManager s = /* keep rationale */ null;
+ group = s != null ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
+ }
+ }
+ """
+ ),
+ java(
+ """
+ class BranchComment {
+ ThreadGroup group;
+ BranchComment() {
+ SecurityManager s = null;
+ group = s != null ? /* keep rationale */ s.getThreadGroup() : Thread.currentThread().getThreadGroup();
+ }
+ }
+ """
+ )
+ );
+ }
+}