我想知道当您尝试捕获StackOverflowError并提出以下方法时会发生什么:
class RandomNumberGenerator {
static int cnt = 0;
public static void main(String[] args) {
try {
main(args);
} catch (StackOverflowError ignore) {
System.out.println(cnt++);
}
}
}
现在我的问题是:
为什么此方法打印“ 4”?
我以为是因为System.out.println()
在调用堆栈上需要3个段,但是我不知道3的来源。当您查看的源代码(和字节码)时System.out.println()
,通常导致的方法调用要多于3(因此,调用堆栈上的3个段是不够的)。如果是由于优化而应用了Hotspot
VM(方法内联),我想知道其他VM上的结果是否会有所不同。
编辑 :
由于输出似乎是高度特定于JVM的,因此我使用 Java(TM)SE Runtime Environment(内部版本1.6.0_41-b02),
Java HotSpot(TM)64位服务器VM(内部版本20.14-b01,混合模式)获得了结果4。
解释为什么我认为这个问题与理解Java堆栈不同:
我的问题不是关于为什么cnt>
0(显然是因为System.out.println()
需要堆栈大小并St
在打印某些内容之前抛出另一个),而是为什么它具有4的特定值,分别是0、3、8、55或其他值系统。
我认为其他人在解释为什么cnt> 0方面做得很好,但是关于为什么cnt =
4以及为什么cnt在不同设置之间变化如此之大的细节还不够多。我将在这里尝试填补这一空白。
让
System.out.println
当我们第一次进入main时,剩下的空间是XM。每个递归调用占用R更多的内存。因此,对于1个递归调用(比原来多1个),内存使用量为M
+R。假设在C个成功的递归调用之后抛出StackOverflowError,即M + C * R <= X和M + C *(R +
1)>X。在出现第一个StackOverflowError时,还剩下X-M-C * R内存。
为了能够运行System.out.prinln
,我们需要在堆栈上保留P的空间。如果碰巧X-M-C * R> =
P,则将打印0。如果P需要更多空间,则我们从堆栈中删除帧,以cnt ++为代价获得R内存。
当println
是最后能够运行,X - M - (C - CNT)* R> = P。因此,如果P是大对于特定系统,那么CNT将是大的。
让我们用一些例子来看一下。
示例1: 假设
然后C = floor((XM)/ R)= 49,cnt = ceiling((P-(X-M-C * R))/ R)= 0。
示例2: 假设
那么C = 19,cnt = 2。
示例3: 假设
那么C = 20,cnt = 3。
示例4: 假设
那么C = 19,cnt = 2。
因此,我们看到系统(M,R和P)和堆栈大小(X)都会影响cnt。
附带说明,catch
开始需要多少空间并不重要。只要没有足够的空间容纳catch
,那么cnt就不会增加,因此不会有外部影响。
编辑
我收回我所说的话catch
。它确实发挥了作用。假设它需要T数量的空间才能启动。当剩余空间大于T时,cnt开始增加,而println
当剩余空间大于T
+ P 时,cnt开始运行。这为计算增加了一个额外的步骤,并进一步混淆了已经很混乱的分析。
编辑
我终于有时间进行一些实验以支持我的理论。不幸的是,该理论似乎与实验不符。实际发生的情况非常不同。
实验设置:具有默认java和default-jdk的Ubuntu 12.04服务器。Xss从70,000开始(以1字节为增量)到460,000。
结果位于:https
:
//www.google.com/fusiontables/DataSource?docid=1xkJhd4s8biLghe6gZbcfUs3vT5MpS_OnscjWDbM
我创建了另一个版本,其中删除了每个重复的数据点。换句话说,仅显示与先前不同的点。这使得更容易看到异常。https://www.google.com/fusiontables/DataSource?docid=1XG_SRzrrNasepwZoNHqEAKuZlHiAm9vbEdwfsUA
我想知道当您试图捕获StackOverflowError时会发生什么,并提出了以下方法: 现在我的问题是: 为什么这个方法打印'4'? 我想可能是因为在调用堆栈上需要3个段,但我不知道3这个数字来自哪里。当您查看的源代码(和字节码)时,通常会导致比3个多得多的方法调用(因此调用堆栈中的3个段是不够的)。如果这是因为Hotspot VM应用的优化(方法内联),我想知道在另一个VM上结果是否会有所不同
问题内容: 众所周知,(大多数)浮点数没有精确存储(使用IEEE-754格式时)。因此,不应这样做: ......因为它会导致,除非一些特定的任意精度的类型/类使用(BigDecimal的中的Java/Ruby的,bcmath时在PHP中,[数学::BigInt有 / 数学::BigFloat在Perl,仅举几例)来代替。 但是,我想知道为什么当尝试打印该表达式的结果时,脚本语言(Perl和PHP
问题内容: 我生成了x的两个矩阵: 第一矩阵:和。 第二矩阵:和。 使用以下代码,第一个矩阵花费了8.52秒完成: 使用此代码,第二个矩阵花费了259.152秒来完成: 运行时间显着不同的原因是什么? 正如评论所说,仅打印需要秒,而给。 正如其他指出它对他们正常工作的人一样,例如,我尝试了Ideone.com,这两段代码以相同的速度执行。 测试条件: 我从 Netbeans 7.2 运行了此测试,
所以我有这个代码,叫我白痴哈哈,但是我不能让它打印7。 代码: 我需要知道如何改变与函数中的参数同名的变量。 任何帮助都将不胜感激,如果你不明白这个问题,我很乐意解释更多。
在python为什么 我想当时,这应该是正确的。应该给我,但是为什么没有?如果这是对的,为什么当,它给我?
问题内容: 我不明白为什么编译器从字典中打印值会有所不同?我使用的是Swift 3,Xcode8。这是错误还是优化内容的怪异方法? 编辑 更奇怪的是: 有些价值观过去了,有些则跌破了,有些则保持不变!1.1小于1.1000000000000001,而2.3大于2.2999999999999998,1.2仅为1.2 问题答案: 如注释中已经提到的,a 不能精确存储值。Swift根据IEEE 754