Runtime taxonomy
C++ · JVM · EVM — storage duration, run-time data areas, data locations, lifetime, and cost

Academic teaching note · accuracy-checked edition · 2026

Where does data actually live?

A cross-runtime taxonomy of program storage across native C++, the Java Virtual Machine, and the Ethereum Virtual Machine — written as a source-grounded academic note with an interactive conceptual interface.

Code Long-lived state Execution stack Dynamic allocation Runtime control

This note proposes a comparative taxonomy for runtime data areas in three execution environments: ISO-style C++ as realized by native implementations, the Java Virtual Machine (JVM), and the Ethereum Virtual Machine (EVM). The taxonomy is deliberately conceptual. It classifies storage according to purpose, lifetime, management authority, and cost model, rather than treating familiar terms such as “stack,” “heap,” “memory,” or “storage” as portable categories.

The central argument is that C++, the JVM, and the EVM differ because they optimize for different forms of control: native execution and explicit lifetime management in C++, managed portability in the JVM, and deterministic replicated execution under gas in the EVM. A five-layer lens—code, long-lived state, execution stack, dynamic allocation or scratch space, and runtime control—helps identify common questions while preserving the important semantic differences among the systems.

Normative claims are anchored in established terminology: C++ storage duration categories, the JVM Specification’s run-time data areas, Solidity data-location documentation, and EIP-1153 transient storage semantics. Implementation terms such as text segment, BSS, Metaspace, or code cache are treated as explanatory examples rather than as language- or VM-level guarantees.

runtime data areas storage duration JVM specification Solidity data locations EVM storage gas model teaching taxonomy

Method: classify storage by role before applying runtime vocabulary.

The same noun can mislead. “Memory” in Solidity, “heap” in the JVM, and “dynamic storage duration” in C++ are not interchangeable. A more reliable method first asks what a storage area is for, how long it can live, who controls its reclamation, and what resource makes it costly.

PurposeDoes the area hold executable instructions, durable state, temporary call data, dynamically created objects, or runtime bookkeeping?
LifetimeDoes it live for a block, a function call, a thread, a process, a VM instance, a transaction, or across transactions?
ManagementIs storage released by lexical scope, the programmer, a garbage collector, VM rules, or protocol rules?
CostIs the limiting resource RAM, address space, collector pressure, stack depth, disk-backed state, or gas?
Source status

The taxonomy distinguishes normative vocabulary from implementation vocabulary. C++ storage duration, JVM run-time data areas, Solidity data locations, and EIP-1153 transient storage are specification-level or documentation-level concepts. Terms such as “heap segment,” “BSS,” “Metaspace,” and “code cache” are useful implementation descriptions, but they should not be presented as universal runtime guarantees.

Terminology guardrail

In Java and C++, memory model usually means the semantics of concurrent reads, writes, visibility, and ordering. This document is therefore titled a runtime data-area taxonomy. That name is less catchy, but much more precise.

Layer 1

Code Area

Executable representation: machine instructions, bytecode, JIT output, or deployed contract code.

Layer 2

Long-Lived or Durable State

State whose lifetime exceeds a single call: program or thread lifetime in C++, VM/class lifetime in the JVM, and transaction or cross-transaction state in the EVM.

Layer 3

Execution Stack

Per-call control and temporary values: frames, locals, operand stacks, return metadata.

Layer 4

Dynamic Allocation / Scratch Space

Runtime-created objects, heap allocations, or temporary linear memory whose size or lifetime is not fully determined by static declarations.

Layer 5

Runtime / Control

Bookkeeping and I/O channels: counters, native stacks, calldata, returndata, logs, gas, allocators, GC, and JIT machinery.

Meta-rule

Names are local

Use runtime vocabulary only after the layer and axis have been identified.

A five-layer map across three runtimes.

Hover, focus, or tap a layer to highlight the corresponding conceptual region in C++, the JVM, and the EVM. The point is not that these systems are implemented the same way; the point is that they answer comparable storage questions.

Layer highlighter

C / C++native process

typical executable + process layout

JVM / Javamanaged VM

specified run-time data areas + implementation details

EVM / Solidityon-chain machine

deterministic state transition engine

Three runtimes, three kinds of control.

C++: storage duration in a native implementation

At the language level, C++ classifies storage by duration: automatic, static, thread, and dynamic. Those categories describe the minimum potential lifetime of the storage that contains an object. A particular compiler, operating system, loader, and ABI may realize those categories through familiar regions such as executable text, read-only data, initialized data, BSS, thread-local storage, native call stacks, and allocator-managed free-store or heap regions. These implementation names are pedagogically useful, but they should not be confused with the formal language taxonomy.

Important distinction

The C++ standard vocabulary is storage duration. “Text segment,” “BSS,” “stack,” and “heap” are implementation vocabulary. They are often accurate for real systems, but not the normative categories of the language itself.

JVM: specified run-time data areas with implementation freedom

The JVM Specification defines run-time data areas used during program execution. Some are created when the JVM starts and destroyed when it exits; others are per-thread and are created and destroyed with the thread. The specification names the pc register, JVM stacks, heap, method area, run-time constant pool, and native method stacks. Object allocation occurs from the heap, while frames on JVM stacks contain local variables, operand stacks, dynamic linking information, and return state. Garbage collectors, JIT compilers, Metaspace, and code caches are implementation mechanisms layered beneath or beside the abstract specification.

Specification versus implementation

“Metaspace” and “code cache” are useful HotSpot implementation terms. In an academic comparison, keep them subordinate to specification terms: method area, heap, JVM stacks, pc register, run-time constant pool, and native method stacks.

EVM: deterministic state transition under gas

The EVM is a deterministic stack machine whose execution must be reproducible by network participants. It operates on a bounded stack of 256-bit words, uses transient linear memory during message-call execution, reads call input from calldata, and writes durable contract state through storage slots. EIP-1153 adds transient storage: a transaction-scoped key-value store accessed with TLOAD and TSTORE and cleared at the end of the transaction. Gas makes computation, memory expansion, and state access explicit economic costs rather than hidden implementation overheads.

The EVM inversion

In ordinary programming, “memory” may sound more durable than “stack.” In Solidity/EVM vocabulary, memory is temporary scratch space for execution, while storage is the durable account-state location. transient storage is state-like, but it is reset at transaction end.

The unified comparison table.

This table compresses the taxonomy into a quick lookup. Treat it as a concept map, not a promise that every implementation names or lays out memory exactly this way.

Question C / C++ JVM / Java EVM / Solidity
Where does code live? Executable instructions in an implementation-defined native process image, commonly described as a text or code segment. Bytecode and method metadata in the method-area abstraction; native/JIT code may reside in an implementation code cache. Contract bytecode associated with an account and executed by the EVM.
Where does long-lived state live? Objects with static or thread storage duration; commonly realized through data, BSS, read-only data, and TLS regions. Class metadata, run-time constant pools, and class-associated state in VM-defined structures; exact physical placement is implementation-dependent. Persistent storage slots for cross-transaction state; transient storage for transaction-scoped key-value state.
Where do local temporaries live? Automatic storage, commonly realized with stack frames, subject to optimization and register allocation. JVM frames containing local variables and operand stacks; JIT compilation may optimize representation. Operand-stack values, memory, and calldata-backed references depending on EVM rules and compiler choices.
Where do runtime-created objects go? Dynamic storage via new, allocation functions, allocators, or C allocation APIs used by the program. The Java heap for class instances and arrays, with representation and optimization controlled by the VM. memory for transient reference-type data; storage only when state must persist; calldata for read-only external input.
Who frees or reclaims it? Automatic objects end with scope or block exit; dynamic storage is released by matching deallocation mechanisms, often mediated through RAII. The VM manages frames and run-time areas; heap storage is reclaimed by automatic storage management when objects become unreachable under the implementation’s GC policy. VM/protocol rules: memory is discarded after a message call, transient storage after a transaction, and persistent storage remains until changed by a state transition.
What is the dominant cost? RAM, cache behavior, allocator overhead, fragmentation, and the correctness burden of manual lifetime management. Heap pressure, GC latency or throughput, stack limits, class loading, and JIT warmup or optimization effects. Gas, especially for persistent state access, writes, memory expansion, and externalized execution costs.
What is the biggest trap? Treating platform segment names as if they were the C++ language’s formal storage-duration taxonomy. Treating one JVM implementation’s memory layout as if it were mandated by the JVM Specification. Treating Solidity memory as durable, or treating transient storage as persistent account storage.

Lifetime spectrum

Lifetime C / C++ JVM / Java EVM / Solidity
One expression / blockTemporary objects and automatic block-scope objects.Frame-local values and operand-stack entries.Stack values and compiler-managed temporaries.
One function / method callCall frame; automatic locals.JVM frame; locals and operand stack.Fresh memory for a message call; stack activity.
One threadThread-local storage.Per-thread JVM stack, pc register, native method stack.Not the governing model.
One process / VM instanceStatic storage for the duration of the program; dynamic allocations until deallocated or program termination.Heap objects until unreachable and reclaimed; method-area structures and loaded classes until unloading or VM exit.Not the governing model.
One transactionNot native to the language model.Not native to the VM model.Transient storage and transaction-scoped execution context; memory remains per message call.
Across transactionsExternal persistence only: file, database, shared service.External persistence only: file, database, shared service.Persistent account storage changed only through state transitions.

One counter, three storage stories.

A counter looks trivial, but it reveals the deepest runtime difference: native process state, managed VM state, and blockchain state do not have the same lifetime.

// C++: static storage lasts for the duration of the program.
static int counter = 0;

int increment() {
    int local = ++counter;  // local: automatic storage
    return local;
}
ElementC++JavaSolidity
counterStatic storage duration; lasts for the duration of the program unless externally persisted.Class-associated static field; lifetime tied to class loading, class unloading, and VM behavior.Persistent contract storage; survives across transactions until changed by a transaction.
localAutomatic object, commonly represented in a stack frame, register, or optimized away.Frame-local value in a JVM stack frame, subject to JIT optimization.Temporary value represented through stack and memory choices made by the compiler under EVM constraints.
Restart behaviorProcess restart resets unless saved externally.VM restart resets unless saved externally.Contract storage remains on-chain unless modified by a transaction.

Where the lens leaks.

A good taxonomy should show its own edges. These are the places where the five-layer map is useful but not exact.

“Stack” does not mean the same object everywhere.

C++ programmers often mean a native call stack. The JVM has per-thread JVM stacks whose frames contain local variables and operand stacks, and it also may use native method stacks. The EVM operand stack is a bounded 1024-deep stack of 256-bit words for computation, not a general call stack in the same sense.

“Heap” is not just “where big things go.”

In Java, class instances and arrays are allocated from the heap and reclaimed by the garbage collector. In C++, dynamic storage is managed through allocation and deallocation mechanisms controlled by the program and its allocators. In Solidity, the term “heap” is not the right surface vocabulary; use memory, storage, calldata, transient storage, and stack.

“Persistent” is relative.

Static state in C++ and class-associated state in the JVM can feel persistent during one run, but they disappear at process or VM termination unless written elsewhere. EVM storage is persistent in a stronger protocol-level sense: it is part of blockchain state and changes only through state transitions.

Implementations optimize away the picture.

Compilers and JITs can keep values in registers, remove allocations through escape analysis, inline calls, reorder code subject to semantics, and change physical layout. The taxonomy describes conceptual placement and lifetime, not a debugger guarantee.

“Transient storage” is not ordinary memory and not durable storage.

Transient storage is accessed like storage through keyed 32-byte words, but its lifetime is transaction-scoped. It can communicate temporary state across internal calls in one transaction, yet it is discarded at transaction end and is not committed as persistent account state.

One sentence per runtime.

C++

I run in a native implementation: language-level storage durations define minimum potential lifetimes, while platforms commonly realize code, static data, automatic frames, thread-local storage, and dynamic allocation through executable sections, stacks, allocators, and ABI conventions.

JVM

I run inside a specified managed abstract machine: run-time data areas are named by the JVM Specification, heap objects are automatically managed, frames are per-thread, and physical layout remains implementation-specific.

EVM

I run as a deterministic state transition: persistent storage is durable and gas-sensitive, memory is transient per message call, calldata is read-only input, transient storage is transaction-scoped, and every operation is priced by gas.

Exam-safe mnemonic

P · L · M · C

For any variable, ask: Purpose — what is it for? Lifetime — how long can it live? Management — who releases it? Cost — what resource makes it expensive?

References

  • [C++ storage duration]C++ distinguishes static, thread, automatic, and dynamic storage duration. Implementation segment names such as text, data, BSS, and heap are useful but non-normative vocabulary. Accessible reference: cppreference — storage duration.
  • [JVMS SE 25 §2.5]The Java Virtual Machine Specification defines run-time data areas including the pc register, JVM stacks, heap, method area, run-time constant pool, and native method stacks. Oracle JVMS §2.5.
  • [Solidity data locations]Solidity documents storage, memory, and calldata as data locations for reference types; calldata is non-modifiable and non-persistent. Solidity docs — data location.
  • [Solidity storage layout]Solidity specifies storage and transient-storage layout rules; the layouts are independent, and only value types are supported for transient storage. Solidity docs — storage and transient-storage layout.
  • [Solidity memory layout]Solidity memory uses a free-memory pointer, places new objects at that pointer, and does not free memory during execution under the current model. Solidity docs — memory layout.
  • [Ethereum EVM overview]Ethereum’s developer documentation describes the EVM as a stack machine with 1024 stack items, each a 256-bit word, and distinguishes memory, storage, transient storage, and gas-priced execution. ethereum.org — EVM.
  • [EIP-1153]EIP-1153 defines the TLOAD and TSTORE opcodes and specifies that transient-storage values are discarded at the end of the transaction. EIP-1153.
  • [Ethereum execution specifications]The Ethereum Execution Layer Specifications provide an executable Python reference implementation and tests for execution-layer behavior. Ethereum execution-specs.