减少 Java 运行时的最大堆栈大小

发布于 2024-07-24 15:40:47 字数 163 浏览 2 评论 0原文

我正在尝试编写一个junit测试来防止一段代码陷入无休止的迭代中,这最终会导致StackOverflow。

所以我正在寻找一种方法来减少运行时的堆栈大小,以便 Junittest 更快地失败。

将最大堆栈设置为 jvm 参数是不可能的,因为该测试是更大的测试套件的一部分。

I'm attempting to write a junit test to guard against a piece of code getting stuck in a endless iteration which will eventually cause a StackOverflow.

so i'm looking for a way to decrease the stack size at runtime so the Junittest will fail faster.

setting the max stack as a jvm argument is not possible because the test is part of a much larger test suite.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

嗼ふ静 2024-07-31 15:40:47

您可以运行一个递归方法,该方法将运行给定的次数,然后执行给定的操作。 不过听起来很不稳定:(

类似这样的东西:

public void eatStackThenExecute(int depth, Runnable action)
{
    // Maybe put some locals here (and use them) to eat more stack per iteration?
    if (depth == 0)
    {
        action();
    }
    else
    {
        eatStackThenExecute(depth - 1, action);
    }
}

编辑:智能 JVM 可能会在这里优化尾部调用,所以我们可能需要在递归调用之后做“一些事情”来阻止这种情况的发生...

Ick 'n东西:(

You could run a recursive method which will run itself a given number of times and then execute a given action. Sounds pretty flaky though :(

Something like:

public void eatStackThenExecute(int depth, Runnable action)
{
    // Maybe put some locals here (and use them) to eat more stack per iteration?
    if (depth == 0)
    {
        action();
    }
    else
    {
        eatStackThenExecute(depth - 1, action);
    }
}

EDIT: It's possible that smart JVMs will optimise the tail call here, so it may be that we'd need to do "something" after the recursive call to stop that from happening...

Ick 'n stuff :(

笛声青案梦长安 2024-07-31 15:40:47

不可能在运行时设置堆栈大小,但也许您可以:

  • 在不同线程内调用该代码段 - 保留对其的引用;
  • 定期轮询thread.getStackTrace(),如果其大小大于x,则失败;
  • 取消执行是否正确终止的检查。

未编译的概念验证代码(未正确检查所有边缘条件):

AtomicBoolean success = new AtomicBoolean(false);

Thread t= new Thread(new Runnable() {
   public void run() {
       codeToTest();
       success.set(true);
   }

});

t.start();

while ( t.isAlive() ) {
     if ( t.getStackTrace().length > 50 )
          fail("Stack trace too large");

     Thread.sleep(50);
}

assertTrue(sucess.get());

It's not possible to set the stack size at runtime, but perhaps you can:

  • invoke that piece of code inside a different thread - retaining the reference to it;
  • periodically poll thread.getStackTrace() and fail if its size is larger than x;
  • cancel the check if execution terminates correctly.

not-compiled proof of concept code ( does not properly check all edge conditions ):

AtomicBoolean success = new AtomicBoolean(false);

Thread t= new Thread(new Runnable() {
   public void run() {
       codeToTest();
       success.set(true);
   }

});

t.start();

while ( t.isAlive() ) {
     if ( t.getStackTrace().length > 50 )
          fail("Stack trace too large");

     Thread.sleep(50);
}

assertTrue(sucess.get());
近箐 2024-07-31 15:40:47

您只能在启动时设置这样的参数,但是您可以从 Java 启动另一个进程。 因此,您可以让单元测试启动具有较小堆栈大小的第二个进程来执行测试。

You can only set parameters like this at startup, however you can start another process from Java. So you could make your unit tests start a second process with a smaller stack size to perform your test.

人生戏 2024-07-31 15:40:47

这有点……好吧,有趣……但这可能是值得的。

  1. 获取您的 .class 文件并使用 jasper 反编译它。
  2. 编辑生成的 JVM 汇编式代码,并为要以此方式测试的例程添加或更改“.limit stack x”参数。
  3. 使用 Jasmin 重新编译。
  4. 运行并测试。

This gets a bit... well, interesting... but it might be worth it.

  1. Take your .class file and decompile it with jasper.
  2. Edit the resulting JVM assembly-esque code and add or alter the ".limit stack x" argument for the routine you want to test in this manner.
  3. Recompile with Jasmin.
  4. Run it and test.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文