为什么较大的Xss没有给出较大的最大堆栈深度?

时间:2019-12-29 11:18:18

标签: macos jvm hotspot

首先,代码:

public class StackSOF {
    private int deep = 0;
    public void stackLeak() {
        deep++;
        stackLeak();
    }    
    public static void main(String[] args) {
        StackSOF sof = new StackSOF();        
        try {
            sof.stackLeak();
        } catch (Throwable e) {
            System.out.println(" stack deep = " + sof.deep + "\n\r" + e);
        }
    }
}

在macOS 10.15.2上,以及AdoptOpenJDK中的11.0.5 + 10。

$ java -Xint -Xss159k StackSOF
 stack deep = 4422
java.lang.StackOverflowError
$ java -Xint -Xss160k StackSOF
 stack deep = 668
java.lang.StackOverflowError
$ java -Xint -Xss161k StackSOF
 stack deep = 4422
java.lang.StackOverflowError

为什么160k的最大堆栈深度小于159k?

1 个答案:

答案 0 :(得分:2)

我认为这是不正确的行为,需要解决。我已经提交了错误JDK-8236569

事实证明,-Xss并非4K的倍数在macOS上根本不起作用。

-Xss参数被处理两次。第一个(主)线程的堆栈大小由启动器配置。启动器simply calls pthread_attr_setstacksize无需预处理参数。

但是,如果EINVAL不是系统页面大小的倍数,则pthread_attr_setstacksize的Mac OS X文档明确声明该函数返回stacksize。此行为不同于Linux,Linux pthread_attr_setstacksize可以接受奇数值。

-Xss也由JVM处理,在这种情况下,值为页面大小的rounded

  // Make the stack size a multiple of the page size so that
  // the yellow/red zones can be guarded.
  JavaThread::set_stack_size_at_create(align_up(stack_size_in_bytes, vm_page_size()));

因此,新线程将具有正确调整的堆栈大小。如果您将测试代码更改为在新线程中运行,它将表现出预期的效果。

public class StackSOF {
    private int deep = 0;
    public void stackLeak() {
        deep++;
        stackLeak();
    }    
    public static void main(String[] args) {
        new Thread(() -> {
            StackSOF sof = new StackSOF();
            try {
                sof.stackLeak();
            } catch (Throwable e) {
                System.out.println(" stack deep = " + sof.deep + "\n\r" + e);
            }
        }).start();
    }
}

由于四舍五入关系,159k和160k之间没有区别:

$ java -Xint -Xss159k StackSOF
 stack deep = 666
java.lang.StackOverflowError
$ java -Xint -Xss160k StackSOF
 stack deep = 666
java.lang.StackOverflowError
$ java -Xint -Xss161k StackSOF
 stack deep = 708
java.lang.StackOverflowError