Why does String creation using `newInstance()` method behave different when using `var` compared to using explicit type `String`?

Java17, same problem. The explanation is clearly: bug.

decompiling it, the relevant section:

        20: anewarray     #2                  // class java/lang/Object
        23: invokevirtual #35                 // Method java/lang/reflect/Constructor.newInstance:([Ljava/lang/Object;)Ljava/lang/Object;
        26: checkcast     #41                 // class java/lang/String
        29: astore        4
        31: ldc           #23                 // String A string
        33: ldc           #23                 // String A string
        35: invokevirtual #43                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z

astore 4 is where the result goes, which is nowhere: slot 4 is not used any further. Instead, the same string constant is loaded twice, trivially resulting in, effectively, "A string".equals("A string"), which is of course true.

Replacing var with String, recompiling, and rerunning javap:

        20: anewarray     #2                  // class java/lang/Object
        23: invokevirtual #35                 // Method java/lang/reflect/Constructor.newInstance:([Ljava/lang/Object;)Ljava/lang/Object;
        26: checkcast     #41                 // class java/lang/String
        29: astore        4
        31: ldc           #23                 // String A string
        33: aload         4
        35: invokevirtual #43                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z

Identical in every way, except the second ldc is the correct aload 4.

I’m having a hard time figuring out what’s happening here. It feels more like the var is somehow causing that ldc to duplicate (in contrast to an analysis incorrectly thinking that the values are guaranteed to be identical; javac intentionally does very little such optimizations).

I’m having a really hard time figuring out how this has been in 2 LTS releases. Impressive find.

Next step is to verify on the latest JDK (18), and then to file a bug. I did a quick look if it has been reported already, but I’m not sure what search terms to use. I didn’t find any report in my search, though.

NB: The decompilation traces were produced using javap -c -v NewInstanceUsingReflection.

EDIT: Just tried on ecj (Eclipse Compiler for Java(TM) v20210223-0522, 3.25.0, Copyright IBM Corp 2000, 2020. All rights reserved.) – bug doesn’t happen there.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)