Hook: Think of Java startup like opening night at a theater: the building powers on, the cast is checked in, and only then does the lead actor step onto the stage.
Question: What happens when a Java program starts?
Answer: When you run java MyClass, the Java launcher starts the JVM, finds your main class, loads it, and prepares it to run. Before main executes, the JVM initializes that class, which means static fields and static blocks run first. Then it calls public static void main(String[] args) on the main thread and passes your command-line arguments as an array.
Interview-Ready Answer: “When a Java program starts, the java launcher starts the JVM, the JVM locates and loads the class with main, initializes that class, and then invokes public static void main(String[] args) on the main thread. A useful detail is that my application classes are usually loaded by the application class loader, while core JDK classes come from the bootstrap loader. Also, Java loads classes lazily, so only the classes I actually touch get initialized.”
“Program start” in Java means more than just jumping into your code. The JVM has to be created, the main class has to be found, the bytecode has to be checked, and the first call to main has to happen. After that, your own code may create more threads, objects, and classes. One important mental model: startup is mostly a chain of finding, checking, and initializing, not immediately “running everything in the project.”
java executable. That native launcher parses command-line options like heap size, class path, or module path.ExceptionInInitializerError.public static void main(String[] args). The args array is never null; if no arguments were passed, it is empty.main starts, your code may create objects and threads. Hot methods may later be compiled by the JIT compiler, which improves performance after startup rather than before it.| Phase | What it does | Why it matters |
|---|---|---|
| Load | Find class bytecode | Creates the class in the VM |
| Link | Verify, prepare, resolve | Makes the class safe and ready |
| Initialize | Run static code | Executes class startup logic |
main is initialized before main runs. Nested helper classes are often not loaded until you touch them.static final int may not trigger class initialization because the compiler can inline the value.You care about startup when building CLIs, serverless functions, containers, or microservices, because startup time affects cold starts and deployment readiness. You also care when debugging weird failures, because a problem in a static block can prevent the app from ever reaching main.
Imagine a checkout service in an e-commerce system. On startup, it reads configuration, connects to metrics, initializes a database pool, and registers HTTP routes. If a developer puts a database connection in a static initializer because it “runs before main,” the service may crash before it can even log a helpful message.
What goes wrong: the container starts, then immediately restarts in a loop. Logs show ExceptionInInitializerError or NoClassDefFoundError: Could not initialize class ..., readiness probes never pass, and customers see checkout timeouts or 503s. The bug is not in the business logic; it is in startup-time side effects that should have been delayed until after the app is ready.
import java.util.Arrays;
public class ProgramStartDemo {
// This runs before main() because the JVM initializes the main class first.
static {
System.out.println("[ProgramStartDemo] initialized before main()");
}
static class Config {
// A non-compile-time constant: touching it forces class initialization.
static String NAME = initName();
static {
System.out.println("[Config] static block ran");
}
private static String initName() {
System.out.println("[Config] static field initializer ran");
return "demo-app";
}
}
static class Worker {
Worker() {
System.out.println("[Worker] constructor ran");
}
void start() {
System.out.println("[Worker] business code runs");
}
}
public static void main(String[] args) {
System.out.println("[main] entered");
System.out.println("[main] args = " + Arrays.toString(args));
// The launcher passes an empty array when there are no arguments.
if (args.length == 0) {
System.out.println("[main] edge case: args is empty, not null");
}
// Accessing Config.NAME triggers lazy initialization of Config.
System.out.println("[main] Config.NAME = " + Config.NAME);
// Instance creation happens only when we explicitly new up an object.
Worker worker = new Worker();
worker.start();
// Failure path: show what happens when a class cannot be found.
if (args.length > 0 && "missing".equals(args[0])) {
try {
Class.forName("com.example.DoesNotExist");
} catch (ClassNotFoundException e) {
System.out.println("[main] failure path: " + e.getClass().getSimpleName() + " -> " + e.getMessage());
}
}
}
}
Follow-up & Tricky Questions:
main? The JVM starts the application’s main thread and invokes main there. If your program needs concurrency, it must create its own worker threads or use an executor.public static void main(String[] args) or an equivalent varargs form. A similar method with the wrong visibility, return type, or parameters will not be used as the entry point.ExceptionInInitializerError. Later attempts may surface NoClassDefFoundError because the class could not be initialized successfully.args ever come in as null? In normal Java application startup, no: the launcher passes a non-null array, and it is empty when there are no arguments. A null check is usually unnecessary, though checking args.length is still common.static final int initialize the class? Not necessarily. If it is a compile-time constant, the value can be inlined into callers, so the JVM may not need to initialize that class just to read the value.main? A standard Java SE application launched with java needs a valid entry point. Frameworks may hide the main method from you, but somewhere in the startup chain a real main still exists.Common Mistakes:
main can have any signature. Correction: the launcher requires the exact entry-point shape, or a compatible varargs form.Memory Hook: “Find it, check it, wake it up, then call main.” That is the whole startup story in one line.
Cheat Sheet:
java launcher starts the JVM.main.main in the main class.args is non-null and may be empty.Practice Tasks:
static final Integer to static final int and see whether accessing it still initializes the class.missing as an argument and observe the caught ClassNotFoundException.