Your language · Java
Memory and the runtime
How the runtime stores objects, garbage collection, and copies versus references.
Learn: Memory and the Java runtime9 minute read
The runtime is everything that happens after you press Run: how Java code becomes something a machine can execute, where variables and objects are stored, and how memory is freed. Interviewers ask about it to check that you understand what your code really does. The answers also help you read errors such as OutOfMemoryError in a long CI run (a run on a server that tests your code automatically), or explain why changing a list in one place changed it somewhere else.
Step 1: JDK, JRE and JVM
javac compiles .java files into .class files that hold bytecode, a set of instructions for a virtual machine rather than for a real processor. The JVM (Java Virtual Machine) loads and runs that bytecode. It also compiles often-used code to machine code while the program runs (the JIT compiler) and frees memory with a garbage collector. The JRE is the JVM plus the standard library, enough to run programs, and the JDK adds tools such as javac and jar. Build machines and CI agents (the servers that build your project and run its tests) need a JDK.
The same bytecode runs on any JVM, so a JAR (a Java program packed into one file) built on Windows runs on a Linux CI agent. The bytecode is portable, and the JVM is built per platform.
Step 2: the stack and the heap
A thread is one path of running code; a program can run several at the same time (see Threads). Each thread has its own stack, a block of memory for method calls. Every method call adds a frame that holds the call's parameters and local variables, and the frame is removed when the method returns. A local primitive such as int count stores its value in the frame. A local object variable stores only a reference, the address of the object. All objects and arrays live on the heap, which every thread shares.
import java.util.*;
public class Main {
static int depth = 0;
static void dive() { depth++; dive(); }
public static void main(String[] args) {
List<String> a = new ArrayList<>();
List<String> b = a; // two references, one heap object
b.add("shared");
System.out.println(a + " same object: " + (a == b));
List<String> c = new ArrayList<>(a); // a copy: a new heap object
c.add("only in c");
System.out.println(a + " " + c);
try {
dive();
} catch (StackOverflowError e) {
System.out.println("stack overflow after many calls: " + (depth > 1000));
}
System.out.println("is an Exception: " + Exception.class.isAssignableFrom(StackOverflowError.class));
}
}
[shared] same object: true [shared] [shared, only in c] stack overflow after many calls: true is an Exception: false
Endless recursion fills a thread's stack and throws StackOverflowError. Keeping too many objects reachable fills the heap and throws OutOfMemoryError. Both are Errors, not Exceptions (see Exceptions). The maximum heap is set with -Xmx; without it, the JVM takes a quarter of the memory it can see. Class metadata (information about each loaded class) lives in Metaspace (since Java 8), and the string pool is in the heap (since Java 7).
Step 3: garbage collection
The garbage collector starts from GC roots, such as local variables of running methods and static fields, and marks every object it can reach. Everything else is garbage, even objects that only point at each other. Most collectors are generational: new objects are checked often because most die young, and survivors move to an old area that is checked less often. On a normal machine the JVM picks the G1 collector. System.gc() is only a request.
An object can be collected once the last reference to it is gone: the variable is set to null, reassigned, or its method returns. Memory leaks in test frameworks are almost always references kept by mistake, such as a static list that collects every page or drivers (browser controllers) that are never quit.
Step 4: reflection and copies
Reflection lets code inspect and use classes while the program runs: list methods, read annotations (markers such as @Test) and call methods by name. TestNG and JUnit (Java test frameworks) use it to find and call methods marked @Test, and Selenium's PageFactory (a helper that sets up page elements) uses it to fill @FindBy fields. It is slower than a direct call and its errors appear only at run time, so everyday test code rarely needs it.
Assigning an object variable copies the reference, never the object. To get an independent list, copy it with new ArrayList<>(list) or List.copyOf(list). These are shallow copies: the list is new, but the elements inside are still the same objects, shared with the original list.
How to answer in an interview
For "heap or stack?", describe one line of code: "In User u = new User(); the variable u is in the method's stack frame and holds a reference. The User object is on the heap. When the method returns, the frame goes away, and the object is collected later if nothing else refers to it." For JDK versus JRE versus JVM, describe them as nested layers: JVM, then JVM plus libraries, then everything plus tools.
Common mistakes
- Saying objects are stored on the stack.
- Thinking an object is freed the moment its method returns.
- Calling
OutOfMemoryErroran exception you should catch. - Expecting
System.gc()to free memory at once. - Thinking
b = acopies a list.
Recap
javac makes bytecode and the JVM runs it anywhere. Each thread's stack holds frames with local values and references, and the shared heap holds every object. The garbage collector frees what nothing can reach. Too-deep recursion overflows the stack, and too many reachable objects fill the heap.
8 questions0/8 solved
| Status | Question | Difficulty | Asked in |
|---|---|---|---|
| Not started | Stack or heap? | Easy | Asked in: Capgemini, TCS, Wipro |
| Not started | JDK vs JRE vs JVM; why Java is platform independent | Easy-Medium | Asked in: Infosys, Wipro |
| Pro+ | Heap versus stack memory | Medium | Asked in: Capgemini, TCS, Wipro |
| Pro+ | How does garbage collection work? | Medium | Asked in: Accenture, TCS |
| Pro+ | When can an object be garbage collected? | Medium | Asked in: Accenture, TCS |
| Pro+ | StackOverflowError or OutOfMemoryError? | Easy-Medium | Asked in: Capgemini, TCS, Wipro |
| Pro+ | What is reflection and where would a framework use it? | Medium | Asked in: TCS |
| Pro+ | Facts about JVM memory areas | Medium | Asked in: Capgemini, Infosys, TCS +1 |
The first 2 questions of each topic are free. Pro+ opens every question.