A large Gatling simulation fails to compile with a StackOverflowError or a Method too large error - what causes each, and how do you fix them?
answer
- Two different compile-time walls
- Long chains cost compiler stack
- The constructor is the oversized method
- -Xss for one, splitting for the other
basics
~20 sBoth come from very long builder chains. StackOverflowError means the compiler ran out of stack, so raise its -Xss. Method too large means the Simulation constructor exceeded the JVM's per-method bytecode limit, so move chains into other classes.
solid answer
~40 sGatling scenarios use method chaining heavily, and the compiler recurses over the chain as it type-checks it — a long enough chain exhausts the compiler's own stack and you get a `StackOverflowError` at build time. The fix is to give the compiling JVM more stack with `-Xss`, wherever that JVM is configured: Maven, Gradle, sbt, or the IDE. Gatling's install guide suggests `-Xss100M` for the Scala compiler. `Method too large` is a different wall: the whole scenario is built in your `Simulation`'s constructor, and the JVM caps how large one method's bytecode may be. No stack setting helps; you must split the chains into `ChainBuilder` values held elsewhere and `exec` them from the constructor. Both are compile-time failures, unrelated to load-generator memory.
code
java · 18 linesimport io.gatling.javaapi.core.*;
import static io.gatling.javaapi.core.CoreDsl.*;
import static io.gatling.javaapi.http.HttpDsl.*;
public class BigSimulation extends Simulation {
static final class Chains {
static final ChainBuilder BROWSE = exec(http("Home").get("/"));
static final ChainBuilder CHECKOUT = exec(http("Cart").get("/cart"));
}
{
setUp(scenario("Shopper")
.exec(Chains.BROWSE, Chains.CHECKOUT)
.injectOpen(atOnceUsers(1)));
}
}go deeper
Be ready to recall that both failures happen at build time, before any load is generated.
Be ready to separate the two: compiler stack exhaustion versus the JVM's per-method bytecode limit, and the different fix each needs.
Be ready to diagnose from the message alone, apply the right remedy, and put the stack setting in the build rather than in each developer's IDE.
Be ready to treat hitting either wall as a signal that a simulation needs decomposing, and to set the convention that keeps it decomposed.
These two build failures look alike — both appear when a simulation gets big, both stop the build, neither mentions Gatling — and they have completely different causes and completely different fixes. Confusing them wastes hours. ## Two different walls | symptom | cause | fix | does -Xss help? | |---|---|---|---| | `StackOverflowError` while compiling | the compiler recurses over a very long method chain and exhausts its own stack | raise the compiler JVM's stack size, or split the chain | **yes** | | `Method too large` compile error | the generated bytecode for a single method exceeded the JVM's hard per-method size limit | move chains out of the oversized method | **no** | ## Why long chains are hard on the compiler A Gatling scenario is one enormous expression. `scenario("x").exec(...).exec(...).pause(...).exec(...)` is a left-nested tree of method calls, and a compiler type-checks such a tree by descending it. The deeper the nesting, the more compiler stack frames are live at once. Gatling's own FAQ states the relationship plainly: the longer the chain, the bigger the stack the compiler needs. So the first remedy is more stack for the process doing the compiling. That is **not** the JVM that will run the load test — it is Maven's, Gradle's, sbt's or your IDE's compiler process, and each is configured differently. Gatling's installation guidance recommends setting `-Xss` to `100M` for the Scala compiler, and adding `-Xss100M` to the Scala compiler options in the IDE. The second remedy is the same one that fixes the other error: break the chain up. A chain of twenty `exec` calls type-checks comfortably; a chain of two thousand does not. ## Why the constructor is the method that overflows `Method too large` names a method, and on a Gatling simulation that method is almost always your `Simulation` subclass's **constructor**. The reason is structural. Gatling instantiates your simulation reflectively, through its no-argument constructor, and expects the whole definition — scenarios, chains and the `setUp` call — to have been registered by the time construction finishes. So everything you write at the top level of the class body ends up compiled into the constructor. A hundred inline chains means a hundred chains' worth of bytecode in one method, and the JVM enforces a fixed upper bound on the bytecode of any single method. Raising `-Xss` cannot help: this is not a stack problem, it is a size limit on the compiled artefact. ## The fix: a chain library Move the chains out of the constructor and into other classes or objects, so their bytecode lands in *those* types' initialisers instead. Then the constructor only references them. ```java public class BigSimulation extends Simulation { static final class Chains { static final ChainBuilder BROWSE = exec(http("Home").get("/")); static final ChainBuilder CHECKOUT = exec(http("Cart").get("/cart")); } { setUp(scenario("Shopper") .exec(Chains.BROWSE, Chains.CHECKOUT) .injectOpen(atOnceUsers(1))); } } ``` In Scala the equivalent is what Gatling's FAQ actually shows: put the chains in `object ChainLibrary1`, `object ChainLibrary2`, and so on, then `exec(chain1, chain2, ... chain100)` from the simulation. If one library object itself grows too large, split it again — the limit applies per method, so more, smaller holders is always a valid answer. ## Choosing between the two remedies 1. **If the build fails only on one machine or only in the IDE**, you are almost certainly looking at a stack setting that differs between environments. Fix the setting, and fix it in the build so it is not per-developer folklore. 2. **If the build fails everywhere and mentions the method size**, no setting will save you. Split. 3. **If a simulation is big enough to hit either wall**, treat that as a design signal as well as a build problem. A single scenario with thousands of inline steps is unreadable, unreviewable and impossible to reuse; naming its parts as chain values fixes the build *and* the maintenance problem in one move. ## What this is not Neither failure has anything to do with the load generator's runtime memory, the number of virtual users, or heap settings for the run. Both happen before a single request is sent. If someone proposes raising `-Xmx` on the run to fix a compile error, that is the tell that the two phases have been conflated.
- Does raising -Xss fix a Method too large error in a Gatling build?No. That error is a hard limit on how large one compiled method may be, not a shortage of compiler stack. The only fix is to make the method smaller — in practice, to move chains out of the simulation's constructor into other classes or objects and reference them from there.
- Which method is too large when a Gatling simulation hits that error?Your `Simulation` subclass's constructor. Gatling instantiates the class reflectively through its no-argument constructor and expects `setUp` to have run by the time construction finishes, so everything written at the top level of the class body compiles into that one method.
saying these in an interview costs you the question
- Raising -Xss to fix a Method too large error
- Blaming the load generator's heap for a compile failure
- Assuming Gatling caps how many actions a scenario may hold
- Fixing the stack size per developer instead of in the build