@@ -69,10 +69,12 @@ private StackStreamFactory() {}
6969 // lazily add subclasses when they are loaded.
7070 private static final Set <Class <?>> stackWalkImplClasses = init ();
7171
72+ // Number of elements in the buffer reserved for VM to use
73+ private static final int RESERVED_ELEMENTS = 1 ;
74+ private static final int MIN_BATCH_SIZE = RESERVED_ELEMENTS + 2 ;
7275 private static final int SMALL_BATCH = 8 ;
7376 private static final int BATCH_SIZE = 32 ;
7477 private static final int LARGE_BATCH_SIZE = 256 ;
75- private static final int MIN_BATCH_SIZE = SMALL_BATCH ;
7678
7779 // These flags must match the values maintained in the VM
7880 @ Native private static final int DEFAULT_MODE = 0x0 ;
@@ -196,7 +198,7 @@ protected AbstractStackWalker(StackWalker walker, int mode, int maxDepth) {
196198 protected abstract int batchSize (int lastBatchFrameCount );
197199
198200 /*
199- * Returns the next batch size, always >= minimum batch size (32)
201+ * Returns the next batch size, always >= minimum batch size
200202 *
201203 * Subclass may override this method if the minimum batch size is different.
202204 */
@@ -538,8 +540,7 @@ protected void initFrameBuffer() {
538540 protected int batchSize (int lastBatchFrameCount ) {
539541 if (lastBatchFrameCount == 0 ) {
540542 // First batch, use estimateDepth if not exceed the large batch size
541- // and not too small
542- int initialBatchSize = Math .max (walker .estimateDepth (), SMALL_BATCH );
543+ int initialBatchSize = Math .max (walker .estimateDepth ()+RESERVED_ELEMENTS , MIN_BATCH_SIZE );
543544 return Math .min (initialBatchSize , LARGE_BATCH_SIZE );
544545 } else {
545546 if (lastBatchFrameCount > BATCH_SIZE ) {
@@ -747,19 +748,31 @@ protected Integer consumeFrames() {
747748 return n ;
748749 }
749750
751+ /*
752+ * Typically finding the caller class only needs to walk two stack frames
753+ * 0: StackWalker::getCallerClass
754+ * 1: API
755+ * 2: caller class
756+ *
757+ * So start the initial batch size with the minimum size.
758+ */
750759 @ Override
751760 protected void initFrameBuffer () {
752- this .frameBuffer = new ClassFrameBuffer (walker , getNextBatchSize () );
761+ this .frameBuffer = new ClassFrameBuffer (walker , MIN_BATCH_SIZE );
753762 }
754763
755764 @ Override
756765 protected int batchSize (int lastBatchFrameCount ) {
757- return MIN_BATCH_SIZE ;
766+ // this method is only called when the caller class is not found in
767+ // the first batch. getCallerClass may be invoked via core reflection.
768+ // So increase the next batch size as there may be implementation-specific
769+ // frames before reaching the caller class's frame.
770+ return SMALL_BATCH ;
758771 }
759772
760773 @ Override
761774 protected int getNextBatchSize () {
762- return MIN_BATCH_SIZE ;
775+ return SMALL_BATCH ;
763776 }
764777 }
765778
@@ -785,7 +798,7 @@ protected void initFrameBuffer() {
785798 * Each specialized AbstractStackWalker subclass may subclass the FrameBuffer.
786799 */
787800 abstract static class FrameBuffer <F > {
788- static final int START_POS = 2 ; // 0th and 1st elements are reserved
801+ static final int START_POS = RESERVED_ELEMENTS ;
789802
790803 // buffers for VM to fill stack frame info
791804 int currentBatchSize ; // current batch size
0 commit comments