The java command starts an operating system process that initializes a JVM implementation, configures its runtime environment, loads the application’s entry class, and invokes the entry point.
Learning Question
What happens when I run java MyApp?
It is easy to treat the java command as if it simply calls main. In reality, the command first launches and configures a JVM process. Application code runs only after that runtime is ready enough to load and invoke the entry point.
The first mental model is:
javastarts the JVM process before the JVM starts the Java application.
Process Creation
From the operating system’s point of view, java is a native executable.
When you run a command such as:
java -cp app.jar com.example.Mainthe operating system starts a process for the Java launcher. That process receives command-line arguments, environment variables, current working directory information, inherited file handles, and operating system resources.
Inside that process, the Java launcher locates and initializes the JVM implementation. In a typical OpenJDK or HotSpot environment, this means loading native JVM runtime code and passing startup options into it.
The Java application has not run yet.
Runtime Configuration
Startup options shape the JVM runtime before application code begins.
Examples include:
- classpath or module path settings
- heap size options such as
-Xmsand-Xmx - garbage collector selection and logging options
- system properties passed with
-Dname=value - agent options
- diagnostic, JIT, or memory-related flags
These options influence class discovery, memory layout, diagnostics, runtime services, and optimization behavior.
This is why the same class files can behave differently when launched with different options or in different runtime environments.
Finding the Entry Point
For a traditional class-based launch, the JVM must find an entry class and a valid main method.
The familiar entry point is:
public static void main(String[] args)Before this method can run, the JVM must load the entry class, link it, initialize it if required, prepare an argument array, and invoke the method on an initial Java thread.
For executable JAR files, the launcher may read manifest metadata to find the main class. For modular applications, module-related launch rules apply. Those paths differ in packaging details, but the boundary remains the same: the launcher and JVM must identify what application code to enter.
Startup Does Not Load Everything
Starting a Java program does not mean every class in the application is loaded immediately.
The JVM loads classes as they are needed according to the execution path, linking rules, initialization rules, reflection, framework behavior, and class loader activity.
This matters in large applications. A program may start successfully and later fail only when a rarely used class or method path is reached. It may also spend startup time loading and initializing many framework classes before the application is ready to serve work.
The Main Thread
The entry point runs on a Java thread. Developers usually call it the main thread.
That thread has its own Java stack. As methods are invoked, frames are pushed onto that stack. The thread shares the heap and class metadata with other threads in the same JVM process.
From the beginning, Java execution is thread-based runtime execution, not source text being read line by line by the operating system.
Common Startup Failures
Startup failures often identify which boundary failed:
| Symptom | Likely Boundary |
|---|---|
ClassNotFoundException | Runtime class discovery failed |
NoClassDefFoundError | A class needed at runtime is missing or unusable |
NoSuchMethodError | Runtime loaded a class version without the expected method |
ExceptionInInitializerError | Class initialization ran application code and failed |
Could not find or load main class | The launcher could not locate a valid entry class |
These are not all the same problem. Some are classpath or module path problems. Some are dependency version problems. Some are application initialization failures.
Core Mental Model
Keep these boundaries separate:
- The operating system starts a native
javaprocess. - The launcher initializes and configures a JVM implementation.
- Startup options shape the runtime before application code runs.
- The JVM locates, loads, links, and initializes the entry class as needed.
- The application begins when the JVM invokes the entry method on a Java thread.
- Not every class is loaded at startup.
Final Summary
The java command does not directly execute Java source or simply jump into main.
It starts a JVM process, configures the runtime, finds the entry point, prepares class metadata and thread state, and then invokes application code inside the managed runtime.