使用 Java 1.6 和 Windows 7 操作系统进行深度递归时出现 java.lang.StackOverflowError

2024-02-09

我有一个程序,在执行时会遇到非常深的递归。在这中间,我得到java.lang.StackOverflowError我的应用程序冻结了。我使用的是 JDK 1.6 和 Windows 7 操作系统。

奇怪的是,我不明白这个StackOverflowError使用 Java 1.5 和 Windows XP 运行我的应用程序时使用相同的代码库。我知道默认堆栈大小因平台和操作系统而异。但对于 Java 1.5 和 Windows XP,我使用以下命令将堆栈大小设置为 256k-Xss命令并没有收到此错误。在 Windows 7 操作系统和 Java 1.6 中使用相同的 256k,我收到此错误。

堆栈大小为 256k,我的应用程序在 Windows XP 中运行没有任何问题,并且抛出一个错误StackOverflowError在 Windows 7 操作系统中。

那么请提供任何信息,从 Windows 7 操作系统到 Windows XP,线程堆栈大小有何不同?


我认为答案是,JDK 1.5忽略将默认堆栈大小设置为特定值。假设,如果您的默认堆栈大小为 512K,并且(您相信)将其设置为 256K,那么最终它的值仍为 512K。随着JDK 6您还可以将默认大小设置为 256K,但这里确实会具有此值。这可能就是您的 Windows 7 出现错误(较早)的原因!


看这个-Xss 默认值 table:

Platform         Default
----------------------------------
Windows IA32     64 KB
Linux IA32       128 KB
Windows x86_64   128 KB
Linux x86_64     256 KB
Windows IA64     320 KB
Linux IA64       1024 KB (1 MB)
Solaris Sparc    512 KB 

在这里您可以看到,默认值与您运行的平台不同。

See: http://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/jrdocs/refman/optionX.html#wp1024112 http://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/jrdocs/refman/optionX.html#wp1024112

此外,因为你得到了StackOverflowError在一个系统上,32 位 VM 将存储地址具有 4 字节内存。 64位VM将用8个字节存储相同的内容!因此,假设您将堆栈大小值设置为 256K(是的,它是 kBytes),则 32 位系统(可能是您的 XP 系统)可以在其堆栈内存中存储 65,536 个地址。 64 位系统(Windows 7 系统)只能存储 32,768 个地址。这可能是这两个系统之间的问题。

一般来说,Javaobjects32 位虚拟机与 64 位虚拟机消耗相同大小的内存。显然,如果你有一个Object这是参考了其他 100 个Objects,它将增加主要的大小Object在 64 位 JVM 上增加 400 字节。

另外据说:

请注意,在某些版本的 Windows 上,操作系统可能会舍入线程 使用非常粗粒度的堆栈大小。如果要求的尺寸是 小于默认大小 1K 或更多,堆栈大小向上舍入 为默认值;否则,堆栈大小将向上舍入为倍数 1 MB。

64k 是每个线程允许的最小堆栈空间量。

See: http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#threads_oom http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#threads_oom

不幸的是,我没有找到任何具体的解释,如何粗粒度正在表达。

尝试在两个平台上运行以下示例程序来猜测堆栈大小彼此之间有多少差异:

public class StackOverflowTest {
    public static void main(String[] args) {
        recurse(0);
    }

    private static void recurse(int i) {
        try {
            recurse(++i);
        } catch (StackOverflowError e) {
            System.out.println(i);
            System.exit(0);
        }
    }
}

我机器上的结果是:

Windows 7 (64-bit)

Stack calls     Java           Stack size
------------------------------------------
11424           JDK 5 64-bit   default
11424           JDK 5 64-bit   -Xss256K
11424           JDK 5 64-bit   -Xss1024K
6260            JRE 6 32-bit   default
4894            JRE 6 32-bit   -Xss256K
35405           JRE 6 32-bit   -Xss1024K
10448 to 10468  JDK 7 64-bit   default
2255 to 2274    JDK 7 64-bit   -Xss256K
10448 to 10468  JDK 7 64-bit   -Xss1024K
10396 to 41894  JDK 8 64-bit   default
2203 to 4590    JDK 8 64-bit   -Xss256K
10396 to 41894  JDK 8 64-bit   -Xss1024K

(如果该列表可以从您正在运行的其他系统扩展,那就太好了!)

正如您所看到的,堆栈大小完全是个谜。事实上,不同的 Java 版本消耗的堆栈内存空间不同。

此外,如果您设置堆栈大小-Xss,该值在 Java 5 版本中将被忽略。

使用 JDK 7,您不会始终获得与其他版本相同的结果。 JDK 8 也是如此,其范围差异很大。

也许您可以自己弄清楚,如果它在您自己的系统上仅略有不同或没有差异。

进一步阅读:http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.5.2 http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.5.2

该规范允许 Java 虚拟机堆栈要么是 固定大小或动态扩展并按要求签订合同 计算。如果Java虚拟机栈的大小是固定的, 每个 Java 虚拟机堆栈的大小可以选择 创建该堆栈时独立。

所以,问题是,这是什么意思动态扩展?

然后我在源代码中发现了一个错误,如果您运行在早期的 Java 6 版本上,这可能会引起您的兴趣:

http://bugs.java.com/view_bug.do?bug_id=6316197 http://bugs.java.com/view_bug.do?bug_id=6316197

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Java 1.6 和 Windows 7 操作系统进行深度递归时出现 java.lang.StackOverflowError 的相关文章

  • Java EE:如何获取我的应用程序的 URL?

    在 Java EE 中 如何动态检索应用程序的完整 URL 例如 如果 URL 是 localhost 8080 myapplication 我想要一个可以简单地将其作为字符串或其他形式返回给我的方法 我正在运行 GlassFish 作为应
  • 如何在 Play java 中创建数据库线程池并使用该池进行数据库查询

    我目前正在使用 play java 并使用默认线程池进行数据库查询 但了解使用数据库线程池进行数据库查询可以使我的系统更加高效 目前我的代码是 import play libs Akka import scala concurrent Ex
  • 在画布上绘图

    我正在编写一个 Android 应用程序 它可以在视图的 onDraw 事件上直接绘制到画布上 我正在绘制一些涉及单独绘制每个像素的东西 为此我使用类似的东西 for int x 0 x lt xMax x for int y 0 y lt
  • 制作一个交互式Windows服务

    我希望我的 Java 应用程序成为交互式 Windows 服务 用户登录时具有 GUI 的 Windows 服务 我搜索了这个 我发现这样做的方法是有两个程序 第一个是服务 第二个是 GUI 程序并使它们进行通信 服务将从 GUI 程序获取
  • JAXb、Hibernate 和 beans

    目前我正在开发一个使用 Spring Web 服务 hibernate 和 JAXb 的项目 1 我已经使用IDE hibernate代码生成 生成了hibernate bean 2 另外 我已经使用maven编译器生成了jaxb bean
  • Spark 1.3.1 上的 Apache Phoenix(4.3.1 和 4.4.0-HBase-0.98)ClassNotFoundException

    我正在尝试通过 Spark 连接到 Phoenix 并且在通过 JDBC 驱动程序打开连接时不断收到以下异常 为简洁起见 下面是完整的堆栈跟踪 Caused by java lang ClassNotFoundException org a
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • 操作错误不会显示在 JSP 上

    我尝试在 Action 类中添加操作错误并将其打印在 JSP 页面上 当发生异常时 它将进入 catch 块并在控制台中打印 插入异常时出错 请联系管理员 在 catch 块中 我添加了它addActionError 我尝试在jsp页面中打
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • Spring @RequestMapping 带有可选参数

    我的控制器在请求映射中存在可选参数的问题 请查看下面的控制器 GetMapping produces MediaType APPLICATION JSON VALUE public ResponseEntity
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • JRE 系统库 [WebSphere v6.1 JRE](未绑定)

    将项目导入 Eclipse 后 我的构建路径中出现以下错误 JRE System Library WebSphere v6 1 JRE unbound 谁知道怎么修它 右键单击项目 特性 gt Java 构建路径 gt 图书馆 gt JRE
  • 如何在控制器、服务和存储库模式中使用 DTO

    我正在遵循控制器 服务和存储库模式 我只是想知道 DTO 在哪里出现 控制器应该只接收 DTO 吗 我的理解是您不希望外界了解底层域模型 从领域模型到 DTO 的转换应该发生在控制器层还是服务层 在今天使用 Spring MVC 和交互式
  • AWS 无法从 START_OBJECT 中反序列化 java.lang.String 实例

    我创建了一个 Lambda 函数 我想在 API 网关的帮助下通过 URL 访问它 我已经把一切都设置好了 我还创建了一个application jsonAPI Gateway 中的正文映射模板如下所示 input input params
  • 无法捆绑适用于 Mac 的 Java 应用程序 1.8

    我正在尝试将我的 Java 应用程序导出到 Mac 该应用程序基于编译器合规级别 1 7 我尝试了不同的方法来捆绑应用程序 1 日食 我可以用来在 Eclipse 上导出的最新 JVM 版本是 1 6 2 马文 看来Maven上也存在同样的
  • 如何从终端运行处理应用程序

    我目前正在使用加工 http processing org对于一个小项目 但是我不喜欢它附带的文本编辑器 我使用 vim 编写所有代码 我找到了 pde 文件的位置 并且我一直在从 vim 中编辑它们 然后重新打开它们并运行它们 重新加载脚
  • 如何从泛型类调用静态方法?

    我有一个包含静态创建方法的类 public class TestClass public static
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • 编译器抱怨“缺少返回语句”,即使不可能达到缺少返回语句的条件

    在下面的方法中 编译器抱怨缺少退货声明即使该方法只有一条路径 并且它包含一个return陈述 抑制错误需要另一个return陈述 public int foo if true return 5 鉴于Java编译器可以识别无限循环 https
  • 节拍匹配算法

    我最近开始尝试创建一个移动应用程序 iOS Android 它将自动击败比赛 http en wikipedia org wiki Beatmatching http en wikipedia org wiki Beatmatching 两

随机推荐