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

StackWalker.getCallerClass() throws UOE if invoked reflectively

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P3 P3
    • None
    • 11, 17, 21
    • core-libs
    • None

      As the attached example program demonstrates, `StackWalker.getCallerClass()` can throw an `UnsupportedOperationException` if called reflectively. Currently this only happens if we invoke `StackWalker.getCallerClass()` recursively reflectively, but this issue will become more prominent once we fix JDK-8285447.
      ```
      import java.lang.reflect.Method;
      import java.util.List;
      import java.util.ArrayList;

      public class ReflectiveGetCallerClassTest {
          private static StackWalker WALKER = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
          private static Method gcc, inv;
          static {
              try {
                  inv = Method.class.getDeclaredMethod("invoke", Object.class, Object[].class);
                  gcc = ReflectiveGetCallerClassTest.class.getDeclaredMethod("getCallerClass");
              } catch (SecurityException se) {
                  // This test can't run if a security manager prohibits "getStackWalkerWithClassReference"
                  System.err.println(se);
                  System.exit(0);
              } catch (Exception e) {
                  System.err.println(e);
                  System.exit(1);
              }
          }

          public static void getCallerClass() {
              System.out.println(WALKER.getCallerClass());
          }

          // Create a list of Object[] of the form:
          // { m, first }
          // { m, { m, first } }
          // { m, { m, { m, first } } }
          static List<Object[]> prepareArgs(Object[] first, Method m, int depth) {
              List<Object[]> l = new ArrayList<Object[]>(depth + 1);
              l.add(first);
              while (depth-- > 0) {
                  l.add(new Object[] { m, l.get(l.size() - 1) });
              }
              return l;
          }

          public static void main(String[] args) throws Throwable {
              // gcc is ReflectiveGetCallerClassTest::getCallerClass()
              // inv is Method::invoke()
              for (Object[] params : prepareArgs(new Object[] { gcc, new Object[] { null, null } }, inv, 10)) {
                  inv.invoke(inv, inv, params);
              }
          }
      }
      ```

            simonis Volker Simonis
            simonis Volker Simonis
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: