看看以下两种方法:
public static void foo() {
try {
foo();
} finally {
foo();
}
}
public static void bar() {
bar();
}
Run Code Online (Sandbox Code Playgroud)
运行bar()清楚导致a StackOverflowError,但运行foo()没有(程序似乎只是无限期运行).这是为什么?
当我在思考各种类型的内存使用情况时,我开始对Java在传递给方法时如何利用内存的整数感到困惑.
说,我有以下代码:
public static void main (String[] args){
int i = 4;
addUp(i);
}
public static int addUp(int i){
if(i == 0) return 0;
else return addUp(i - 1);
}
Run Code Online (Sandbox Code Playgroud)
在下面的示例中,我想知道我的以下逻辑是否正确:
但是,如果我总是通过数组传递它:
public static void main (String[] args){
int[] i = {4};
// int tempI = i[0];
addUp(i);
}
public static int addUp(int[] i){
if(i[0] == 0) return 0;
else return addUp(i[0] …Run Code Online (Sandbox Code Playgroud) 观察StackOverflowError时如何检索完整的调用堆栈?
考虑这个简单的例子:
public class Overflow {
public Overflow() {
new Overflow();
}
public static void a() {
new Overflow();
}
public static void main(String[] argv) {
a();
}
}
Run Code Online (Sandbox Code Playgroud)
现在报告的错误是:
Exception in thread "main" java.lang.StackOverflowError
at Overflow.<init>(Overflow.java:11)
[last line repeated many times]
Run Code Online (Sandbox Code Playgroud)
但我无法在堆栈跟踪中看到main和a方法.我的猜测是因为溢出,堆栈中的最新条目取代了最旧的条目(?).
现在,如何在输出中获取a和main堆栈条目?
其背景是,我得到了一个的StackOverflowError(但是这不是一个无限递归,因为增加堆栈大小时,它不会发生),它是很难发现代码中的问题.我只获取了多行java.util.regex.Pattern代码而不是代码所谓的信息.应用程序太复杂,无法在每次调用Patterns时设置断点.
用于演示目的的简单类:
public class Main {
private static int counter = 0;
public static void main(String[] args) {
try {
f();
} catch (StackOverflowError e) {
System.out.println(counter);
}
}
private static void f() {
counter++;
f();
}
}
Run Code Online (Sandbox Code Playgroud)
我执行了5次上面的程序,结果是:
22025
22117
15234
21993
21430
Run Code Online (Sandbox Code Playgroud)
为什么结果每次都不同?
我尝试设置最大堆栈大小(例如-Xss256k).然后结果更加一致,但每次都不相等.
Java版本:
java version "1.8.0_72"
Java(TM) SE Runtime Environment (build 1.8.0_72-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.72-b15, mixed mode)
Run Code Online (Sandbox Code Playgroud)
编辑
当JIT被禁用时(-Djava.compiler=NONE)我总是得到相同的数字(11907).
这是有道理的,因为JIT优化可能会影响堆栈帧的大小,并且JIT完成的工作肯定必须在执行之间变化.
尽管如此,我认为如果通过参考关于该主题的一些文档和/或JIT在这个特定示例中完成的工作的具体示例来确认该理论将导致框架大小改变将是有益的.
这是我在互联网上随机发现的关于动态编程的一些讲座中读到的一个问题.(我毕业了,我已经知道动态编程的基础了)
在解释为什么需要记忆的部分,即
// psuedo code
int F[100000] = {0};
int fibonacci(int x){
if(x <= 1) return x;
if(F[x]>0) return F[x];
return F[x] = fibonacci(x-1) + fibonacci(x-2);
}
Run Code Online (Sandbox Code Playgroud)
如果没有使用memoization,那么许多子问题将被重新计算很多次,这使得复杂性非常高.
然后在一个页面上,笔记有一个没有答案的问题,这正是我想问的问题.在这里,我使用的是准确的措辞及其显示的示例:
自动记忆:许多函数式编程语言(例如Lisp)都内置了对memoization的支持.
为什么不用命令式语言(例如Java)?
说明提供的LISP示例(它声称它是有效的):
(defun F (n)
(if
(<= n 1)
n
(+ (F (- n 1)) (F (- n 2)))))
Run Code Online (Sandbox Code Playgroud)
它提供的Java示例(它声称它是指数的)
static int F(int n) {
if (n <= 1) return n;
else return F(n-1) + F(n-2);
}
Run Code Online (Sandbox Code Playgroud)
在阅读本文之前,我甚至不知道在某些编程语言中内置支持memoization.
笔记中的声明是真的吗?如果是,那么为什么命令式语言不支持呢?
lisp java theory functional-programming imperative-programming
我们知道,ReentrantLock有一个最大的重入限制:Integer.MAX_VALUE; synchronized块是否也有重入限制?
更新:我发现很难为同步重入编写测试代码:
public class SyncReentry {
public static void main(String[] args) {
synchronized (SyncReentry.class) {
synchronized (SyncReentry.class) {
// ...write synchronized block for ever
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以帮助编写一些同步重入限制测试的代码吗?
甲骨文表示在Windows上
-Xsssize缺省值取决于虚拟内存
如何在给定的Oracle JVM 8中找出Java在Windows上分配的线程堆栈大小的值?
我已尝试从哪里找到Sun / Oracle JVM的默认XSS值的解决方案?
但它只打印0。
java -XX:+PrintFlagsFinal -version
Run Code Online (Sandbox Code Playgroud)
java -XX:+PrintFlagsFinal 应该打印实际的线程堆栈大小,而不是0。对我来说似乎是JVM bug。
我想调整JVM性能,并想知道为线程的堆栈分配了多少内存。它是为unix平台专门指定的。我无法为Windows获得此值,这很奇怪。
我今天一直在编写一个递归函数,递归深度取决于输入长度。
我想从纯兴趣的角度来看,是否有某种方法可以监视特定程序执行期间的最大调用堆栈深度,可能是在某些 JVM 日志或其他地方?
经过一番思考,我可以想象出一种分析方法来近似计算,但这将非常耗时,并且需要对 JVM 内部结构和字节码有很好的了解。
JVM 允许配置堆栈大小内存的限制,但我从未见过有关如何获得实际达到的限制的任何信息,而不是内存大小单位,而是分配的堆栈帧数。
我在"stackoverflow"网站上问一个关于"java堆栈溢出"的问题:)
对于特定输入进行一些递归函数调用的特定线程在Oracle Java 7(64位)中运行良好,配置的堆栈大小为228k(-Xss228k).
但是,为同一输入运行相同递归代码的同一线程会抛出Oracle Java 8(64位)中的java.lang.StackOverflowError,其堆栈大小为228k.如果堆栈大小增加到512k(-Xss512k),它在Java 8中运行良好.
知道为什么会这样吗?与Java 7相比,在Java 8(Hotspot JVM)中是否进行了任何更改,这可能会增加递归函数调用的堆栈内存消耗?如果需要,我可以提供更多细节.
(编辑)注意:相同的递归深度在Java 7中"始终"起作用,但在Java 8中"始终"失败,堆栈大小为228k.