FastStackGetter { private FastStackGetter(Object javaLangAccess, Method getElementMethod, Method getDepthMethod) { this.javaLangAccess = javaLangAccess; this.getElementMethod = getElementMethod; this.getDepthMethod = getDepthMethod; } private  FastStackGetter(Object javaLangAccess, Method getElementMethod, Method getDepthMethod); @NullableDecl static FastStackGetter createIfSupported(); StackTraceElement getStackTraceElement(Throwable throwable, int n); int getStackTraceDepth(Throwable throwable);  }
@Test public void testFastStackGetter() { FastStackGetter stackGetter = FastStackGetter.createIfSupported(); Throwable throwable = new UserCode().throwable; assertThat(stackGetter.getStackTraceElement(throwable, 0).getMethodName()).isEqualTo("methodC"); assertThat(stackGetter.getStackTraceElement(throwable, 1).getMethodName()).isEqualTo("methodB"); assertThat(stackGetter.getStackTraceElement(throwable, 2).getMethodName()).isEqualTo("methodA"); StackTraceElement[] stack = throwable.getStackTrace(); assertThat(stack.length).isAtLeast(5); assertThat(stackGetter.getStackTraceDepth(throwable)).isEqualTo(stack.length); for (int n = 0; n < stack.length; n++) { assertThat(stackGetter.getStackTraceElement(throwable, n)).isEqualTo(stack[n]); } try { StackTraceElement unused = stackGetter.getStackTraceElement(throwable, stack.length); fail("expected IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException expected) { } try { StackTraceElement unused = stackGetter.getStackTraceElement(throwable, -1); fail("expected IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException expected) { } }