pvgoddijn
pvgoddijn

Reputation: 12898

Decrease max stacksize at runtime in Java

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.

Upvotes: 3

Views: 1235

Answers (4)

Peter Lawrey
Peter Lawrey

Reputation: 533432

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.

Upvotes: 1

Alan
Alan

Reputation: 3895

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.

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1499770

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 :(

Upvotes: 5

Robert Munteanu
Robert Munteanu

Reputation: 68268

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());

Upvotes: 2

Related Questions