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

NullPointerException in sun.reflect.GeneratedMethodAccessor when wrong number of method arguments are passed during reflection invocation

XMLWordPrintable

      FULL PRODUCT VERSION :
      java version "1.8.0_92"
      Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
      Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      Linux Mint 17.1 - 64 bit, uname -a output is:

      Linux 3.13.0-37-generic #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux


      A DESCRIPTION OF THE PROBLEM :
      I have a pretty straightforward code which does a lookup of a method using reflection and then invokes on it, passing it some params. If the wrong number of method params are passed it is expected to receive an exception like: java.lang.IllegalArgumentException: wrong number of arguments and initially when the method is looked up and invoked for a few times, it does throw that correct error. Here's an example stacktrace which has the correct exception message:

      Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:497)
      at org.myapp.ReflectionMethodInvokerBugTest.main(ReflectionMethodInvokerBugTest.java:20)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:497)
      at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)




      However, the issues starts to appear when the method has been looked up via reflection and invoked upon for a good number of times. So after a period of "warm up" (I could reproduce it consistently after 500 lookups and invocations) if I do the same steps as above, it runs into a NPE like this:

      Exception in thread "main" java.lang.IllegalArgumentException: java.lang.NullPointerException@4769b07b
      at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:497)
      at org.myapp.ReflectionMethodInvokerBugTest.main(ReflectionMethodInvokerBugTest.java:20)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:497)
      at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

      Notice that the exception that's now thrown is java.lang.IllegalArgumentException: java.lang.NullPointerException@4769b07b and also notice that the stacktrace now shows that the method invocation is now being handled by what appears to be a dynamically generated internal JRE class:

      at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)


      The simple program to reproduce this is available in the source code section of this bug report.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the code that's shown in the source code section of this bug

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The exception thrown should include the correct exception message which is - java.lang.IllegalArgumentException: wrong number of arguments
      ACTUAL -
      java.lang.IllegalArgumentException: java.lang.NullPointerException@4769b07b

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------

      package org.myapp;

      import java.lang.reflect.Method;

      /**
       * @author Jaikiran Pai
       */
      public class ReflectionMethodInvokerBugTest {

          public static void main(String[] args) throws Exception {
              final ReflectionMethodInvokerBugTest self = new ReflectionMethodInvokerBugTest();
              // This count is used to decide when to pass an invalid number of arguments to the method during the reflection call.
              // This should be sufficiently high to reproduce the NPE, since the JRE generates the dynamic (internal) method invoker
              // after the method has been invoked a good number of times.
              final int warmupCount = 500;
              for (int i = 0; i < 1000; i++) {
                  final Method method = self.getClass().getMethod("doSomething", String.class);
                  if (i > warmupCount) {
                      // intentionally pass wrong argument
                      method.invoke(self, null);
                  } else {
                      method.invoke(self, "test-" + i);
                  }
              }

          }

          public void doSomething(final String foo) {
              System.out.println(foo);
          }
      }

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

            liach Chen Liang
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: