问题:请分析一下Java中StackOverflowError
异常和OutOfMemoryError异常之间联系与区别,什么时候会产生StackOverflowError异常?什么时候产生OutOfMemoryError异常?
答:在Java虚拟机规范中是这样描述这两类异常的:
(1)如果
线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异
常;
(2)如果虚拟机在扩展栈时无法申请到足够的
内存空间,则抛出OutOfMemoryError异
常。
对于Java虚拟机规范中的描述,对这两种异常有着清晰的区分,但还是存在一些相互重叠的地方:当栈空间无法继续分配的时候,我们不能确定到底时内存大小
限制还是栈的最大深度受到限制而抛出异常。
在单线程的环境中,无论时由于栈帧太大,还是虚拟机容量太小,当内存无法分配时虚拟机总是抛出StackOverflowError异常而不是OutOfMemoryError异常。在多线程的环境中,通过不断建立线程的方式可以产生内存溢出异常。但是,这种方式产生的内存溢出异常与栈空间是否足够并没有什么关系,在这种情况下,给每个线程的栈分配的内存越大,反而越容易产生内存溢出异常。原因主要是:每个线程分配到的栈容量越大,可以建立的线程数量自然就越少,建立线程时就越容易把剩下的内存耗尽。如果是建立过多的线程导致内存溢出,在不能减少线程数或者更换64位虚拟机的情况下,就只能通过减少最大堆和减少栈容量来换取更多的线程的支持能力。