spotBugs and JDK-8194978: Javac produces dead code for try-with-resource

Vicente Romero vicente.romero at oracle.com
Mon Jan 28 11:33:43 UTC 2019


Hi,

On 1/25/19 3:44 PM, Enrico Olivelli wrote:
> Up
>
> Regards
> Enrico
>
> Il 10 gen 2019 8:13 PM, "Enrico Olivelli" <eolivelli at gmail.com 
> <mailto:eolivelli at gmail.com>> ha scritto:
>
>     Kindly pinging on this..
>
>     Cheers
>     Enrico
>
>     Il lun 7 gen 2019, 14:28 Enrico Olivelli <eolivelli at gmail.com
>     <mailto:eolivelli at gmail.com>> ha scritto:
>
>         Two questions/ideas:
>         1) Wouldn't it be possible for javac to annotate such code
>         blocks and
>         write into the class file that that code is "synthetic" ? I really
>         don't know where to store such flags, but maybe someone could
>         elaborate more this idea
>

I don't think that this is a good idea. There is no perfect fix in this 
area as we have discussed. Adding annotations to blocks doesn't seems 
like the right direction here

>         2) Why isn't javac adding  the "$closeResource" method ?
>

that method is not being generated anymore in recent versions of javac

>
>         Enrico
>

Vicente

>
>         Il giorno ven 9 nov 2018 alle ore 23:01 Alex Buckley
>         <alex.buckley at oracle.com <mailto:alex.buckley at oracle.com>> ha
>         scritto:
>         >
>         > On 11/9/2018 12:31 PM, Vicente Romero wrote:
>         > > My evaluation on this issue is that javac is generating code
>         > > according to the spec, see JLS11 14.20.3.1 [1]. There is
>         an explicit
>         > > check for null on the resource before invoking the close()
>         method.
>         > > This is the null check javac is generating.
>         >
>         > I confirm that the explicit null check on the resource
>         variable is
>         > required, per the translation in
>         >
>         https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-14.20.3.1-140
>         <https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-14.20.3.1-140>
>         > -- it has been specified that way since JLS7.
>         >
>         > > Fix for JDK-8194978 went a bit further trying to eliminate
>         dead code
>         > > for some cases for which javac could statically determine
>         that the
>         > > resource would be different from null. In particular if
>         the resource
>         > > was initialized with a new class expression.
>         >
>         > I confirm it's acceptable to not perform the null check in
>         generated
>         > code if you can prove the resource variable is non-null.
>         Frankly,
>         > though, there is so much that can occur in a "new class
>         expression" --
>         > `new Outer(a(b(c)))<>.new <String>Inner(d(e(f)))` -- that I
>         would be
>         > wary of trying to prove anything.
>         >
>         > > It could be argued that we could try to analyze the body
>         and if we
>         > > find out that a NPE must be thrown in the body of the try,
>         then the
>         > > null check on the resource would be deemed unnecessary.
>         But then we
>         > > can get to an implementation that will be out of sync with
>         the spec
>         > > plus it probably won't cover all cases.
>         >
>         > Right, let's not be too clever.
>         >
>         > Alex
>         >
>         > > Thanks,
>         > > Vicente
>         > >
>         > > [1]
>         > >
>         https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-14.20.3.1
>         <https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-14.20.3.1>
>         > >
>         > > On 11/9/18 10:22 AM, Ismael Juma wrote:
>         > >> Any comments on this? Many people are disabling spotBugs when
>         > >> compiling with Java 11 due to this issue:
>         > >>
>         > >> https://github.com/spotbugs/spotbugs/issues/756
>         <https://github.com/spotbugs/spotbugs/issues/756>
>         > >>
>         > >> Ismael
>         > >>
>         > >> On Thu, Sep 13, 2018 at 10:05 PM Ismael Juma
>         <mlists at juma.me.uk <mailto:mlists at juma.me.uk>
>         > >> <mailto:mlists at juma.me.uk <mailto:mlists at juma.me.uk>>> wrote:
>         > >>
>         > >>     Hi all,
>         > >>
>         > >>     JDK-8194978 introduced some changes to the bytecode
>         generated by
>         > >>     javac for the try with resource construct. In the
>         following code,
>         > >>     it seems to generate a null check on a reference
>         after invoking a
>         > >>     method on it:
>         > >>
>         > >>         public static void readFileAsString(String path)
>         throws
>         > >>     IOException {
>         > >>             try (FileChannel fc =
>         FileChannel.open(Paths.get(path))) {
>         > >>                 fc.size();
>         > >>             }
>         > >>
>         > >>         }
>         > >>
>         > >>     In line 16 to 22 of the bytecode, it looks like we
>         check for null
>         > >>     after calling a method on the fc reference:
>         > >>
>         > >>           16: aload_1
>         > >>           17: invokevirtual #6         // Method
>         > >>     java/nio/channels/FileChannel.size:()J
>         > >>           20: pop2
>         > >>           21: aload_1
>         > >>           22: ifnull        52
>         > >>           25: aload_1
>         > >>           26: invokevirtual #7         // Method
>         > >>     java/nio/channels/FileChannel.close:()V
>         > >>
>         > >>     Is this intentional? I ask because this pattern
>         triggers a
>         > >>     spotBugs warning since it often implies a bug in
>         user's code:
>         > >>
>         > >>     RCN | Nullcheck of fc at line 10 of value previously
>         dereferenced
>         > >>     in TryTest.readFileAsString(String, Charset)
>         > >>
>         > >>     Note that this works fine in Java versions older than
>         Java 11.
>         > >>     Since this spotBugs warning is generally useful, it
>         would be handy
>         > >>     if javac did not trigger it. Alternatively, if
>         there's a good way
>         > >>     to detect the code that was generated by javac,
>         spotBugs could be
>         > >>     updated to ignore it. For reference, this was
>         discussed in the
>         > >>     spotBugs issue tracker:
>         > >>
>         > >> https://github.com/spotbugs/spotbugs/issues/756
>         <https://github.com/spotbugs/spotbugs/issues/756>
>         > >>
>         > >>     And method bytecode in full:
>         > >>
>         > >>       public static void
>         readFileAsString(java.lang.String) throws
>         > >>     java.io.IOException;
>         > >>         Code:
>         > >>            0: aload_0
>         > >>            1: iconst_0
>         > >>            2: anewarray     #2         // class
>         java/lang/String
>         > >>            5: invokestatic  #3         // Method
>         > >>   
>          java/nio/file/Paths.get:(Ljava/lang/String;[Ljava/lang/String;)Ljava/nio/file/Path;
>         > >>            8: iconst_0
>         > >>            9: anewarray     #4         // class
>         > >>     java/nio/file/OpenOption
>         > >>           12: invokestatic  #5         // Method
>         > >>   
>          java/nio/channels/FileChannel.open:(Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljava/nio/channels/FileChannel;
>         > >>           15: astore_1
>         > >>           16: aload_1
>         > >>           17: invokevirtual #6         // Method
>         > >>     java/nio/channels/FileChannel.size:()J
>         > >>           20: pop2
>         > >>           21: aload_1
>         > >>           22: ifnull        52
>         > >>           25: aload_1
>         > >>           26: invokevirtual #7         // Method
>         > >>     java/nio/channels/FileChannel.close:()V
>         > >>           29: goto          52
>         > >>           32: astore_2
>         > >>           33: aload_1
>         > >>           34: ifnull        50
>         > >>           37: aload_1
>         > >>           38: invokevirtual #7         // Method
>         > >>     java/nio/channels/FileChannel.close:()V
>         > >>           41: goto          50
>         > >>           44: astore_3
>         > >>           45: aload_2
>         > >>           46: aload_3
>         > >>           47: invokevirtual #9         // Method
>         > >>   
>          java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
>         > >>           50: aload_2
>         > >>           51: athrow
>         > >>           52: return
>         > >>         Exception table:
>         > >>            from    to  target type
>         > >>               16    21    32   Class java/lang/Throwable
>         > >>               37    41    44   Class java/lang/Throwable
>         > >>
>         > >>     Thanks,
>         > >>     Ismael
>         > >>
>         > >
>
>     -- 
>
>
>     -- Enrico Olivelli
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20190128/7453ab56/attachment-0001.html>


More information about the compiler-dev mailing list