Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8073432

Object.getClass() throws stackless NPE, due to C2 intrinsic

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Fixed
    • Icon: P3 P3
    • 9
    • 9
    • hotspot
    • None
    • team

        C2 intrinsifies Object.getClass(), and it puts the fastthrow-ed NPE exception on failure path.
        This means users that (blindly) use obj.getClass() as weird make-shift NPE check will receive
        the stackless NPE, which will confuse them and/or complicate debugging.

        Sample program that prints the number of lines in the (exception + stacktrace) dump:

        import java.io.PrintWriter;
        import java.io.StringWriter;

        public class Test {
                public static void main(String... args) {
                        for (int c = 0; c < 1000000; c++) {
                                try {
                                        callWith(null);
                                } catch (NullPointerException ex) {
                                        StringWriter sw = new StringWriter();
                                        PrintWriter pw = new PrintWriter(sw);
                                        ex.printStackTrace(pw);
                                        pw.close();
                                        System.out.println(sw.toString().split("\n").length);
                                }
                        }
                }

                public static void callWith(Object obj) {
                        obj.getClass();
                }
        }

        Yields:

        $ java Test | uniq -c
           5772 3
          55684 1
          48128 3
         890416 1

        I interpret this as follows: 5772 invocations happened in interpreter mode and got the full stack trace, then C2 kicked in and 55684 invocations ran with stackless NPEs, then deopt happened and we bailed to interpreter again, and finally we reached C2 where we have all the stackless NPEs. Enabling the stacktraces in fastthrow expectedly gives:

        $ java -XX:-OmitStackTraceInFastThrow Test | uniq -c
        1000000 3

        From my brief read of C2 code, fastthrow-ed built-in exceptions seem to serve the deoptimization goals, and I am not sure they should leak to the users.

              mcimadamore Maurizio Cimadamore
              shade Aleksey Shipilev
              Votes:
              0 Vote for this issue
              Watchers:
              10 Start watching this issue

                Created:
                Updated:
                Resolved: