Excel不相邻列如何打印在一起-英雄云拓展知识分享
141
2023-11-07
【摘要】 本书摘自《深入理解 Java 虚拟机 JVM 高级特性与最佳实践(第3版)》一书中第2章,第4节,周志明著。
2.4.2 虚拟机栈和本地方法栈溢出
由于HotSpot 虚拟机中并不区分虚拟机栈和本地方法栈,因此对于HotSpot 来说, -Xoss 参数(设置本地方法栈大小)虽然存在,但实际上是没有任何效果的,栈容量只能由-Xss 参数来设定。关于虚拟机栈和本地方法栈,在《Java 虚拟机规范》中描述了两种异常:
1)如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出 StackOverflowError 异常。
2)如果虚拟机的栈内存允许动态扩展,当扩展栈容量无法申请到足够的内存时,将抛 出 OutOfMemoryError 异常。
《Java 虚拟机规范》明确允许Java 虚拟机实现自行选择是否支持栈的动态扩展,而 HotSpot 虚拟机的选择是不支持扩展,所以除非在创建线程申请内存时就因无法获得足够内 存而出现OutOfMemoryError 异常,否则在线程运行时是不会因为扩展而导致内存溢出的, 只会因为栈容量无法容纳新的栈帧而导致 StackOverflowError 异常。
为了验证这点,我们可以做两个实验,先将实验范围限制在单线程中操作,尝试下面 两种行为是否能让 HotSpot 虚拟机产生 OutOfMemoryError 异常:
口使用-Xss 参数减少栈内存容量。
结果:抛出 StackOverflowError 异常,异常出现时输出的堆栈深度相应缩小。 口定义了大量的本地变量,增大此方法帧中本地变量表的长度。
结果:抛出 StackOverflowError异常,异常出现时输出的堆栈深度相应缩小。 首先,对第一种情况进行测试,具体如代码清单2-4所示。
代码清单2-4 虚拟机栈和本地方法栈测试(作为第1点测试程序)
/**
*VM Args:-Xss128k
* @author zzm
*/
public class JavaVMStackSOF {{
private int stackLength =1;
public void stackLeak() {
stackLength++;
stackLeak();
}
public static void main(String[]args)throws Throwable {
JavaVMStackSOF oom =new JavaVMStackSOF();
try {
oom.stackLeak();
}catch(Throwable e){
System.out.println("stack length:" +oom.stackLength); throw e;
}
}
运行结果:
stack length:2402
Exception in thread "main" java.lang.StackOverflowError
at org.fenixsoft.oom.JavaVMStackSOF.leak(JavaVMStackSOF.java:20) at org.fenixsoft.oom.JavaVMStackSOF.leak(JavaVMStackSOF.java:21) at org.fenixsoft.oom.JavaVMStackSOF.leak(JavaVMStackSOF.java:21)
……后续异常堆栈信息省略
对于不同版本的Java 虚拟机和不同的操作系统,栈容量最小值可能会有所限制,这 主要取决于操作系统内存分页大小。譬如上述方法中的参数-Xss128k 可以正常用于32位 Windows 系统下的JDK6, 但是如果用于64位Windows 系统下的JDK 11,则会提示栈容量 最小不能低于180K, 而 在Linux 下这个值则可能是228K, 如果低于这个最小限制,HotSpot 虚拟器启动时会给出如下提示:
The Java thread stack size specified is too small.Specify at least 228k
我们继续验证第二种情况,这次代码就显得有些“丑陋”了,为了多占局部变量表空 间,笔者不得不定义一长串变量,具体如代码清单2-5所示。
实验结果表明:无论是由于栈帧太大还是虚拟机栈容量太小,当新的栈帧内存无法分 配的时候,HotSpot 虚拟机抛出的都是 StackOverflowError 异常。可是如果在允许动态扩展 栈容量大小的虚拟机上,相同代码则会导致不一样的情况。譬如远古时代的 Classic 虚拟机, 这款虚拟机可以支持动态扩展栈内存的容量,在Windows 上 的JDK 1.0.2 运行代码清单2-5 的话(如果这时候要调整栈容量就应该改用-oss 参数了),得到的结果是:
stack length:3716
java.lang.OutOfMemoryError
at org.fenixsoft.oom.JavaVMStackSOF.leak(JavaVMStackSOF.java:27) at org.fenixsoft.oom.JavaVMStackSOF.leak(JavaVMStackSOF.java:28) at org.fenixsoft.oom.JavaVMStackSOF.leak(JavaVMStackSOF.java:28)
……后续异常堆栈信息省略
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们 18664393530@aliyun.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~