JDK-8357185 : Redundant local variables with unconditionally matching primitive patterns
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 23,25
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2025-05-16
  • Updated: 2025-07-22
  • Resolved: 2025-07-09
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 26
26 b06Fixed
Related Reports
Causes :  
Description
A DESCRIPTION OF THE PROBLEM :
When using "spotbugs" for static code analysis, it gives a warning for the code if compiled with JDK23, but not if compiled with JDK22:
M D DLS: Dead store to $L7 in DeadStoreBug.getDouble()  At DeadStoreBug.java:[line 21]

Of course, this may be a bug in spotbugs, but looking at the byte code I don't think so.

In the byte code there is the instruction "dstore 7" that is not followed up by any load.

Byte code:
  public java.util.OptionalDouble getDouble();
    descriptor: ()Ljava/util/OptionalDouble;
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=4, locals=9, args_size=1
         0: aload_0
         1: getfield      #15                 // Field value:LDeadStoreBug$MyInterface;
         4: astore        4
         6: aload         4
         8: instanceof    #48                 // class DeadStoreBug$RecordWithDouble
        11: ifeq          42
        14: aload         4
        16: checkcast     #48                 // class DeadStoreBug$RecordWithDouble
        19: astore_1
        20: aload_1
        21: invokevirtual #50                 // Method DeadStoreBug$RecordWithDouble.d:()D
        24: dstore        5
        26: dload         5
        28: dstore        7
        30: iconst_1
        31: ifeq          42
        34: dload         5
        36: dstore_2
        37: dload_2
        38: invokestatic  #54                 // Method java/util/OptionalDouble.of:(D)Ljava/util/OptionalDouble;
        41: areturn
        42: invokestatic  #59                 // Method java/util/OptionalDouble.empty:()Ljava/util/OptionalDouble;
        45: areturn
        46: astore_1
        47: new           #39                 // class java/lang/MatchException
        50: dup
        51: aload_1
        52: invokevirtual #41                 // Method java/lang/Throwable.toString:()Ljava/lang/String;
        55: aload_1
        56: invokespecial #45                 // Method java/lang/MatchException."<init>":(Ljava/lang/String;Ljava/lang/Throwable;)V
        59: athrow


REGRESSION : Last worked in version 22

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the code.
(And run through spotbugs).

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Compiled code does no dead store.
(And spotbugs does not warn).
ACTUAL -
Compiled code does dead store.
(And spotbugs warns).

---------- BEGIN SOURCE ----------
import java.util.Objects;
import java.util.OptionalDouble;
import java.util.OptionalInt;

public class DeadStoreBug {

	private final MyInterface value;

	private DeadStoreBug(final MyInterface aValue) {
		value = Objects.requireNonNull(aValue);
	}

	public OptionalInt getInt() {
		if (value instanceof RecordWithInt(final int i)) {
			return OptionalInt.of(i);
		}
		return OptionalInt.empty();
	}

	public OptionalDouble getDouble() {
		if (value instanceof RecordWithDouble(final double d)) {
			return OptionalDouble.of(d);
		}
		return OptionalDouble.empty();
	}

	public sealed interface MyInterface permits RecordWithInt, RecordWithDouble {
	}

	private record RecordWithInt(int i) implements MyInterface {
	}

	private record RecordWithDouble(double d) implements MyInterface {
	}
}

---------- END SOURCE ----------


Comments
Changeset: d886ae12 Branch: master Author: Chen Liang <liach@openjdk.org> Date: 2025-07-09 12:14:14 +0000 URL: https://git.openjdk.org/jdk/commit/d886ae12a2ee3ce519c736d8950a17a0ce63ca78
09-07-2025

A pull request was submitted for review. Branch: master URL: https://git.openjdk.org/jdk/pull/26107 Date: 2025-07-02 23:06:42 +0000
02-07-2025

I think this might be cause by JEP 455 - the code in getDouble is essentially translated to if (value instanceof RecordWithDouble v1 && v1.d() instanceof double d) and instanceof double is now affected by JEP 455.
02-07-2025

given that the compiler is not producing a compiler error but it is only producing dead code we think that this one should be a P4 instead of a P3, downgrading it
19-05-2025

Impact -> H (Regression) Likelihood -> L (Uncommon uses) Workaround -> M (Somewhere in-between the extremes) Priority -> P3
18-05-2025

The observations on Windows 11: JDK 23ea+7: Passed. JDK 23ea+8: Failed, dead store observed. JDK 24: Failed. JDK 25ea+6: spotbug can not run
18-05-2025