What Java is, how JDK, JRE and JVM fit together, the JVM's architecture, and every tricky question about public static void main.
Published September 25, 2026
These are the questions that open almost every Java interview. They sound easy, which is exactly why interviewers use them: a vague answer here sets a weak tone for the rest of the conversation. For each question, lead with the short answer, then add the key points if the interviewer wants more. The Learn it in depth links go to the full lessons on each topic.
Short answer (say this first): Java is a high-level, class-based, object-oriented programming language. Its source code compiles to platform-neutral bytecode, which runs on any machine that has a Java Virtual Machine. That is the "write once, run anywhere" promise.
Key points to cover:
Learn it in depth → Classes and Objects
Short answer: Platform independence, object orientation, automatic memory management, strong type safety and security, built-in multithreading, and a rich standard library.
Key points to cover:
free), no raw pointer arithmetic, checked exceptions, and array bounds checks.Common trap: calling Java "interpreted". Modern JVMs interpret bytecode at first, then JIT-compile frequently used code to native code. That's why long-running Java services perform well.
Short answer: The Java Virtual Machine is the runtime engine that loads, verifies and executes Java bytecode. It's what makes Java platform independent: the bytecode is the same everywhere, and each operating system gets its own JVM implementation.
Key points to cover:
Learn it in depth → JVM Memory Areas
Short answer: The JVM runs bytecode. The JRE is the JVM plus the standard class libraries, which is everything needed to run Java programs. The JDK is the JRE plus development tools (javac, jar, javadoc, jdb, jshell), which is everything needed to build them.
Key points to cover:
| Contains | Who needs it | |
|---|---|---|
| JVM | Class loader, runtime data areas, execution engine (interpreter + JIT), GC | Part of every Java runtime |
| JRE | JVM + core libraries (java.lang, java.util, …) | Anyone running a Java app |
| JDK | JRE + compiler, debugger and tooling | Developers and build servers |
Common trap: saying you still download a separate JRE. Since Java 11, Oracle and most vendors ship only the JDK. For deployment, you create a trimmed runtime with jlink, or use a JRE-style base image from a vendor such as Eclipse Temurin.
Learn it in depth → JVM Memory Areas
Short answer: Three main parts: the class loader subsystem, the runtime data areas, and the execution engine.
Key points to cover:
.class files. It has three phases:
Common trap: saying "the heap is per thread". The heap and method area are shared. Stacks, PC registers and native stacks are per thread.
Learn it in depth → JVM Memory Areas
Short answer: It always needs a Java runtime, but that runtime doesn't have to be installed system-wide. You can bundle a runtime with the application.
Key points to cover:
jlink (Java 9+) builds a custom, trimmed runtime that contains only the modules your app uses. It's often a fraction of the full JDK's size.jpackage (Java 14+) wraps the app and its runtime into a native installer (.msi, .dmg, .deb).Short answer: No. Every JDK includes a full Java runtime, because the development tools themselves (javac, for example) are Java programs that need it.
Key points to cover:
jre/ folder.jre directory. The runtime is built into the JDK's modules, but it's still there.jlink image, has no compiler.public static void main(String[] args).Short answer: It's the entry point the JVM looks for when you launch a class. Each keyword has a reason:
public: the JVM launcher must be able to call it from outside the class.static: the JVM can call it without creating an object first.void: it returns nothing. To report an exit status, use System.exit(code).main: the name the launcher searches for.String[] args: the command-line arguments. String... args (varargs) is also accepted.public class Greeter {
public static void main(String[] args) {
String name = args.length > 0 ? args[0] : "world";
System.out.println("Hello, " + name); // java Greeter Asha → Hello, Asha
}
}
Key points to cover:
static public void main is legal).final and synchronized are allowed on it too.String[] argv works.void main() { IO.println("Hi"); }. The launcher still prefers the classic static main(String[]) when it exists.Learn it in depth → Classes and Objects
main is not declared static?Short answer: Up to Java 20, the class compiles, but launching it fails with the error "Main method is not static in class X, please define the main method as: public static void main(String[] args)". The JVM had no object to call a non-static method on.
Key points to cover:
main is perfectly legal Java.main() on it.main method?Short answer: Not in the true sense, because static methods aren't overridden. A subclass can declare its own static main, but that hides the parent's method; it doesn't override it.
Key points to cover:
java Child, the JVM runs Child.main. If you launch java Parent, it runs Parent.main. Each class's main is independent.@Override annotation on a static method is a compile error. That's a quick way to prove the point.Learn it in depth → Inheritance and Polymorphism
main method?Short answer: Yes. main is an ordinary static method, so you can declare other main methods with different parameter lists.
public class App {
public static void main(String[] args) {
System.out.println("launcher entry point");
main(42); // call the overload yourself
}
public static void main(int code) {
System.out.println("overload called with " + code);
}
}
main method?Short answer: No. The launcher calls only the entry-point signature, main(String[] args). The overloads run only if your code calls them.
Key points to cover:
main() with no parameters is also a valid entry point. If both main(String[]) and main() exist, the launcher picks main(String[]).main method?Short answer: Not in modern Java. Up to Java 6, you could print from a static initialiser block, which ran when the class loaded, before the launcher complained about the missing main. Since Java 7, the launcher checks for main before initialising the class, so the program fails with "Main method not found" and the static block never runs.
public class NoMain {
static {
System.out.println("printed on Java 6 only");
// Java 6: printed, then an error unless you call System.exit(0) here
// Java 7+: "Error: Main method not found in class NoMain" and nothing is printed
}
}
Common trap: the widely repeated answer "it worked until Java 8" is wrong. The change came in Java 7. And since Java 25, the honest modern answer is that you don't need the classic main at all: a compact source file with void main() does the job.
Q: If bytecode is platform independent, why do we need different JDK downloads per OS? A: The JVM, and the native parts of the runtime, are written for a specific operating system and CPU. The bytecode is the same everywhere; the program that runs it isn't.
Q: What's the difference between the JIT compiler and javac?
A: javac compiles .java source to bytecode ahead of time. The JIT compiler runs inside the JVM, and turns frequently executed bytecode into optimised native machine code while the program runs, using runtime profiling information that javac never has.
Q: What does the bytecode verifier protect against?
A: It checks that loaded bytecode is well formed and type safe before it runs. That means no stack overflows or underflows within a frame, no treating an int as an object reference, and no jumping into the middle of an instruction. This matters because class files can come from untrusted sources.
Q: Which class loaders exist, and what is parent delegation?
A: The bootstrap loader (core classes), the platform loader (other Java SE modules), and the application loader (your classpath). A loader first asks its parent to load a class, and only loads it itself if the parent can't. That stops application code from replacing core classes such as java.lang.String.
Q: How do you pass arguments to main in an IDE or with Maven?
A: From the command line: java MyApp a b c. In an IDE, set them in the run configuration's "Program arguments". With Maven's exec plugin: mvn exec:java -Dexec.args="a b c". With Spring Boot: mvn spring-boot:run -Dspring-boot.run.arguments="--port=9000".