DEV Community

Cover image for JVM, JRE, JDK, Bytecode & main(): 8 Questions I Had as a Beginner
Poushmita Paul
Poushmita Paul

Posted on

JVM, JRE, JDK, Bytecode & main(): 8 Questions I Had as a Beginner

Java Learning Notes — Telusko Core Java | Video 04

In the previous lesson, I finally wrote my first Java program and learned the basic:

Write → Compile → Run

workflow.

But after writing a simple Java program, I realized that there was much more happening behind the scenes.

I kept seeing terms like:

  • Bytecode
  • .class
  • JVM
  • JRE
  • JDK
  • main()
  • javac
  • WORA

And I had questions like:

What exactly is bytecode?

Why doesn't Java run the .java file directly?

What is the difference between JDK, JRE and JVM?

If Java is platform independent, why is the JVM platform dependent?

And why does Java need public static void main(String[] args)?

This lesson helped me connect these pieces.

As I worked through it, I realized that the easiest way to understand Java's execution model is to follow the journey of a Java program from the moment I write it until I see the output.

This article explains what I learned from the lesson, along with additional research I used to make these concepts easier to understand.

What This Article Covers

In this article, I will answer these eight questions:

  1. What is bytecode?
  2. What does javac do?
  3. Why is Java considered platform independent?
  4. Why is the JVM platform dependent?
  5. What is the purpose of main()?
  6. What is the difference between java Hello and javac Hello.java?
  7. What do JDK, JRE and JVM stand for?
  8. What does WORA mean?

I will also connect all of these concepts into one simple execution flow.

1. What is bytecode?

What I understood first

Before this lesson, I knew that Java code gets compiled.

But I didn't really understand:

Compiled into what?

The answer is:

Bytecode.

When I write Java source code in a file such as:

Hello.java
Enter fullscreen mode Exit fullscreen mode

the Java compiler does not normally convert it directly into machine code specific to Windows, Linux, or macOS.

Instead, it converts the Java source code into bytecode.

The simplified process is:

Java Source Code
      ↓
     javac
      ↓
   Bytecode
      ↓
    JVM
      ↓
   Execution
Enter fullscreen mode Exit fullscreen mode

The bytecode is usually stored inside a .class file.

For example:

Hello.java
    ↓
Hello.class
Enter fullscreen mode Exit fullscreen mode

So I can think of:

.java
↓
Source code

.class
↓
Bytecode
Enter fullscreen mode Exit fullscreen mode

Why doesn't Java directly create Windows or Linux machine code?

This is where Java's portability becomes important.

If the compiler generated machine code specifically for Windows, that output would not necessarily work directly on Linux or macOS.

Instead, Java uses an intermediate representation:

Bytecode

The JVM on each supported platform understands and executes that bytecode.

So:

             Same Bytecode
                  │
       ┌──────────┼──────────┐
       ↓          ↓          ↓
    Windows      Linux      macOS
      JVM         JVM        JVM
Enter fullscreen mode Exit fullscreen mode

This design is one of the major reasons Java became known for portability.

Is bytecode the same as machine code?

No.

This distinction is important.

Machine code is instructions designed for a specific processor architecture.

Java bytecode is an intermediate instruction format designed for the JVM.

So I remember:

Java Source Code
      ↓
    Bytecode
      ↓
      JVM
      ↓
Platform-specific execution
Enter fullscreen mode Exit fullscreen mode

🧠 Easy to Remember

Bytecode = compiled Java instructions stored in .class files and executed by the JVM.

🎯 Short Interview Answer

Bytecode is the intermediate instruction format produced by the Java compiler from Java source code. It is stored in .class files and executed by the JVM.

2. What does javac do?

What I understood first

I already learned about javac in Video 03, but this lesson helped me understand its role in the complete Java execution model.

javac is the:

Java compiler

Its job is to compile Java source code into bytecode.

For example:

javac Hello.java
Enter fullscreen mode Exit fullscreen mode

If the source code is valid, the compiler can produce:

Hello.class
Enter fullscreen mode Exit fullscreen mode

So:

Hello.java
    ↓
  javac
    ↓
Hello.class
Enter fullscreen mode Exit fullscreen mode

The .class file contains the bytecode.

What does the compiler actually check?

The compiler doesn't simply convert text into another file.

It also checks whether the Java source code follows the language's rules.

For example, if I write invalid Java syntax, the compiler can report an error.

Suppose I forget a semicolon:

System.out.println("Hello World")
Enter fullscreen mode Exit fullscreen mode

Running:

javac Hello.java
Enter fullscreen mode Exit fullscreen mode

can produce a compilation error.

So I can think of javac as the stage that takes my Java source code and prepares it for execution by the JVM.

javac vs java

This distinction is extremely important:

javac
 ↓
Compile

java
 ↓
Run
Enter fullscreen mode Exit fullscreen mode

For example:

javac Hello.java
Enter fullscreen mode Exit fullscreen mode

compiles the source file.

Then:

java Hello
Enter fullscreen mode Exit fullscreen mode

runs the compiled class.

🧠 Easy to Remember

javac → compile

java → run

🎯 Short Interview Answer

javac is the Java compiler. It compiles Java source code into bytecode, which is stored in .class files and later executed by the JVM.

3. Why is Java considered platform independent?

What I understood first

This was one of the most important concepts for me.

We often hear:

Java is platform independent.

But what exactly does that mean?

It does not mean that Java magically ignores the operating system.

It means that Java's execution model allows the same compiled bytecode to be used across different supported platforms through their appropriate JVM implementations.

The complete picture

Suppose I write:

Hello.java
Enter fullscreen mode Exit fullscreen mode

I compile it:

javac Hello.java
Enter fullscreen mode Exit fullscreen mode

and get:

Hello.class
Enter fullscreen mode Exit fullscreen mode

That .class file contains bytecode.

Now imagine I move that compiled application to another supported operating system.

The JVM available on that platform can execute the bytecode.

So:

              Java Source
                   ↓
                 javac
                   ↓
              Bytecode
                   ↓
        ┌──────────┼──────────┐
        ↓          ↓          ↓
   Windows JVM  Linux JVM  macOS JVM
        ↓          ↓          ↓
      Run        Run        Run
Enter fullscreen mode Exit fullscreen mode

This is the basic idea behind Java's platform independence.

What is actually platform independent?

The important distinction is:

Java bytecode is designed to be portable.

The JVM itself is not identical across operating systems.

There can be different JVM implementations for different platforms.

That brings us to the next question.

🧠 Easy to Remember

Same bytecode + different platform JVMs = Java portability

🎯 Short Interview Answer

Java is considered platform independent because Java source code is compiled into platform-independent bytecode that can be executed on different supported operating systems through compatible JVM implementations.

4. Why is the JVM platform dependent?

What I understood first

At first, I found this confusing:

Java is platform independent, but the JVM is platform dependent. How can both be true?

The answer becomes simple when I separate the two.

Java bytecode is portable

The bytecode generated from Java source code is designed to be portable across supported platforms.

For example:

Hello.class
Enter fullscreen mode Exit fullscreen mode

can be transferred to another compatible platform.

The JVM interacts with the operating system

The JVM, however, needs to work with the underlying operating system and hardware.

For example, a JVM running on Windows needs to interact with Windows.

A JVM running on Linux needs to interact with Linux.

A JVM running on macOS needs to interact with macOS.

So we can think of:

             Same Java Bytecode
                     │
       ┌─────────────┼─────────────┐
       ↓             ↓             ↓
 Windows JVM     Linux JVM     macOS JVM
       ↓             ↓             ↓
    Windows        Linux         macOS
Enter fullscreen mode Exit fullscreen mode

The bytecode remains portable, but the JVM implementation is adapted to the platform.

This is the important distinction

Java/bytecode → platform independent

JVM → platform dependent

This distinction cleared up the apparent contradiction for me.

🧠 Easy to Remember

Java bytecode travels.

The JVM adapts to the platform.

🎯 Short Interview Answer

The JVM is platform dependent because each operating system and hardware environment requires a JVM implementation capable of interacting with that specific platform. Java bytecode remains portable because compatible JVMs execute it on different platforms.

5. What is the purpose of main()?

What I understood first

In the previous lesson, I saw code like:

```java id="r8w3tz"
System.out.println("Hello World");




But that statement alone wasn't enough to create a normal Java application.

I needed something like:



```java 
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}
Enter fullscreen mode Exit fullscreen mode

The important new part was:

public static void main(String[] args)
Enter fullscreen mode Exit fullscreen mode

At this stage, I don't need to memorize the meaning of every keyword yet.

The most important thing is to understand:

main() provides the standard entry point for a Java application.

What does "entry point" mean?

Think about a program as a journey.

The JVM needs to know:

"Where should I start executing this application?"

For a standard Java application launched with the Java launcher, the main() method provides that starting point.

So conceptually:

Start Java Application
        ↓
Find main()
        ↓
Begin execution
        ↓
Run statements
        ↓
Output
Enter fullscreen mode Exit fullscreen mode

The standard main method

The traditional form introduced here is:

public static void main(String[] args)
Enter fullscreen mode Exit fullscreen mode

For now, I remember the complete signature.

Later, I can learn what:

  • public
  • static
  • void
  • String[]
  • args

actually mean.

Trying to understand every keyword immediately can make the first Java lesson unnecessarily overwhelming.

Example

public class Hello {

    public static void main(String[] args) {
        System.out.println("Hello World");
    }

}
Enter fullscreen mode Exit fullscreen mode

Here:

class Hello
      ↓
contains main()
      ↓
JVM starts application execution there
Enter fullscreen mode Exit fullscreen mode

Is main() the only possible entry point in Java?

For the traditional standalone Java application model being taught here, the main method is the standard entry point.

Different Java technologies can have different application startup mechanisms, but for learning Core Java fundamentals, the important rule is:

The JVM looks for the recognized main method when launching a standard Java application.

🧠 Easy to Remember

main() = starting point of a standard Java application

🎯 Short Interview Answer

The main() method serves as the standard entry point for a standalone Java application. The Java launcher invokes this method to begin application execution.

6. What is the difference between java Hello and javac Hello.java?

What I understood first

These two commands look very similar, so it is easy to mix them up:

javac Hello.java
Enter fullscreen mode Exit fullscreen mode

and:

java Hello
Enter fullscreen mode Exit fullscreen mode

But they perform completely different jobs.

javac Hello.java

This means:

Compile the Java source file.

The process is:

Hello.java
    ↓
  javac
    ↓
Hello.class
Enter fullscreen mode Exit fullscreen mode

The .java file is the source code.

The .class file contains bytecode.

java Hello

This means:

Launch the compiled Hello class.

The Java launcher starts the JVM and loads the class so that the standard application entry point can be invoked.

The command normally uses the class name, not the .java or .class filename extension:

java Hello
Enter fullscreen mode Exit fullscreen mode

not:

java Hello.java
Enter fullscreen mode Exit fullscreen mode

for the traditional compile-then-run workflow being introduced here.

And not:

java Hello.class
Enter fullscreen mode Exit fullscreen mode

The complete sequence

Write:
Hello.java
   ↓
Compile:
javac Hello.java
   ↓
Creates:
Hello.class
   ↓
Run:
java Hello
   ↓
JVM
   ↓
Output
Enter fullscreen mode Exit fullscreen mode

🧠 Easy to Remember

javac Hello.java → Create bytecode

java Hello → Run the compiled class

🎯 Short Interview Answer

javac Hello.java compiles the Java source file into bytecode, while java Hello launches the compiled class and starts the application through the JVM.

7. What do JDK, JRE and JVM stand for?

What I understood first

This was probably the most confusing group of terms for me.

I kept seeing:

JDK
JRE
JVM

They all sounded like different versions of the same thing.

The easiest way I found to understand them is to think about their roles.

JDK
└── JRE
    └── JVM
Enter fullscreen mode Exit fullscreen mode

This is the conceptual hierarchy used in the lesson.

JVM — Java Virtual Machine

The JVM is responsible for:

Executing Java bytecode.

Think:

.class
  ↓
Bytecode
  ↓
JVM
  ↓
Execution
Enter fullscreen mode Exit fullscreen mode

JRE — Java Runtime Environment

The JRE represents the environment required to run Java applications.

The lesson's conceptual model includes:

  • JVM
  • Runtime libraries/components

So:

JRE
 ├── JVM
 └── Runtime libraries/components
Enter fullscreen mode Exit fullscreen mode

The key idea is:

JRE → runtime

JDK — Java Development Kit

The JDK is for development.

It includes development tools such as the Java compiler.

So:

JDK
 ├── Development tools
 └── Runtime components
       ↓
      JRE
       ↓
      JVM
Enter fullscreen mode Exit fullscreen mode

This is a conceptual model that is useful for learning.

A practical modern note

One thing I discovered while researching this topic is that modern Java distributions don't always package a separate downloadable product called a "JRE" in the same way older Java distributions did.

For learning the architecture, the:

JDK → JRE → JVM

model is still useful.

But when installing modern Java, I generally install a JDK for development rather than looking for a separate JRE download.

The simplest distinction

If I forget everything else, I want to remember:

JDK
↓
Develop Java

JRE
↓
Run Java

JVM
↓
Execute bytecode
Enter fullscreen mode Exit fullscreen mode

🧠 Easy to Remember

JDK → Development

JRE → Runtime

JVM → Executes bytecode

Or:

JDK contains the tools I need to build; the runtime environment lets Java applications run; the JVM executes the bytecode.

🎯 Short Interview Answer

JDK stands for Java Development Kit and provides development tools. JRE stands for Java Runtime Environment and provides the environment required to run Java applications. JVM stands for Java Virtual Machine and executes Java bytecode.

8. What does WORA mean?

What I understood first

I first encountered WORA in the introduction lesson:

Write Once, Run Anywhere

But this lesson made the idea much clearer because now I understood bytecode and the JVM.

How WORA works

Suppose I write:

```text id="o4y7q1"
Hello.java




I compile it:



```bash id="n3k5r8"
javac Hello.java
Enter fullscreen mode Exit fullscreen mode

and get:

Hello.class
Enter fullscreen mode Exit fullscreen mode

The .class file contains bytecode.

Now I can think of that bytecode as being portable across supported platforms because each platform can have a compatible JVM.

             Hello.class
              Bytecode
                  │
       ┌──────────┼──────────┐
       ↓          ↓          ↓
    Windows      Linux      macOS
      JVM         JVM        JVM
       ↓          ↓          ↓
      Run        Run        Run
Enter fullscreen mode Exit fullscreen mode

That's the basic idea behind:

Write Once, Run Anywhere

Why isn't the JVM itself portable in the same way?

Because the JVM has to interact with the underlying operating system and hardware.

So:

Bytecode
  ↓
Portable

JVM
  ↓
Platform-specific implementation
Enter fullscreen mode Exit fullscreen mode

This distinction is the key to understanding Java's platform independence.

Is WORA an absolute guarantee?

Not literally.

A Java application can still depend on things such as:

  • Native libraries
  • Operating-system-specific features
  • External services
  • Environment configuration
  • File-system assumptions

So I understand WORA as a description of Java's portable bytecode + JVM execution model, not as a promise that every application will work everywhere without any configuration.

🧠 Easy to Remember

WORA = Write Once, Run Anywhere

And the mechanism is:

Source → Bytecode → Platform-specific JVM → Execution

🎯 Short Interview Answer

WORA stands for Write Once, Run Anywhere. Java achieves this portability by compiling source code into bytecode that can be executed on different supported platforms through compatible JVM implementations.

🔄 The Complete Java Execution Model

After learning all these concepts, I found it much easier to understand Java as a complete process instead of memorizing separate definitions.

Step 1 — Write source code

I create:

Hello.java
Enter fullscreen mode Exit fullscreen mode

and write:

public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 2 — Compile

I run:

javac Hello.java
Enter fullscreen mode Exit fullscreen mode

The compiler converts the source code into bytecode.

Hello.java
    ↓
  javac
    ↓
Hello.class
Enter fullscreen mode Exit fullscreen mode

Step 3 — Launch

I run:

java Hello
Enter fullscreen mode Exit fullscreen mode

The Java launcher starts the runtime and loads the class.

Step 4 — JVM executes bytecode

The JVM loads and executes the bytecode.

Step 5 — main() provides the starting point

The standard main() method provides the entry point from which the application begins execution.

Step 6 — Output appears

Finally:

Hello World
Enter fullscreen mode Exit fullscreen mode

So the complete picture becomes:

       Hello.java
           │
           ↓
         javac
           │
           ↓
       Hello.class
        Bytecode
           │
           ↓
      java Hello
           │
           ↓
          JVM
           │
           ↓
        main()
           │
           ↓
        Output
Enter fullscreen mode Exit fullscreen mode

This is the mental model I want to carry forward.

🧩 JDK vs JRE vs JVM — Simple Comparison

Component Main Purpose Think
JDK Java development Build
JRE Java runtime environment Run
JVM Executes bytecode Execute

The conceptual relationship from the lesson is:

JDK
 ↓
JRE
 ↓
JVM
Enter fullscreen mode Exit fullscreen mode

And the execution flow is:

.java
 ↓
javac
 ↓
.class
 ↓
JVM
 ↓
Output
Enter fullscreen mode Exit fullscreen mode

⚠️ Common Beginner Mistakes

Confusing java and javac

Remember:

javac → compile
java  → run
Enter fullscreen mode Exit fullscreen mode

Running the source filename with java

Traditional compile-then-run workflow:

javac Hello.java
java Hello
Enter fullscreen mode Exit fullscreen mode

not:

java Hello.java
Enter fullscreen mode Exit fullscreen mode

Running .class with the Java launcher

Use:

java Hello
Enter fullscreen mode Exit fullscreen mode

not:

java Hello.class
Enter fullscreen mode Exit fullscreen mode

Thinking the JVM is platform independent

The bytecode is designed to be portable.

The JVM implementation is platform-specific.

Thinking JDK and JVM are the same thing

They are not.

JDK → Development tools
JRE → Runtime environment
JVM → Executes bytecode
Enter fullscreen mode Exit fullscreen mode

Forgetting the main() method

A standard standalone Java application needs an appropriate entry point for the Java launcher to start execution.

For the traditional form:

public static void main(String[] args)
Enter fullscreen mode Exit fullscreen mode

Assuming WORA means zero configuration

Java provides strong portability, but applications can still have platform-specific dependencies.

🧠 One-Minute Revision Sheet

If I have only one minute to revise this lesson, I want to remember:

.java
↓
Java source code

javac
↓
Java compiler

.class
↓
Bytecode

JVM
↓
Executes bytecode

main()
↓
Standard application entry point

JDK
↓
Development

JRE
↓
Runtime

JVM
↓
Execution

WORA
↓
Write Once, Run Anywhere
Enter fullscreen mode Exit fullscreen mode

And the complete workflow:

Write
 ↓
Compile
 ↓
Bytecode
 ↓
JVM
 ↓
main()
 ↓
Execute
 ↓
Output
Enter fullscreen mode Exit fullscreen mode

🎯 8 Interview Questions — Super Short Answers

What is bytecode?

Bytecode is the intermediate code produced by the Java compiler and stored in .class files. The JVM executes it.

What does javac do?

javac compiles Java source code into bytecode.

Why is Java platform independent?

Java source code is compiled into portable bytecode that can run on different platforms through compatible JVM implementations.

Why is the JVM platform dependent?

The JVM must interact with the specific operating system and hardware platform, so JVM implementations are platform-specific.

What is the purpose of main()?

main() is the standard entry point used to start a standalone Java application.

What is the difference between java Hello and javac Hello.java?

javac Hello.java compiles the source code, while java Hello launches the compiled class.

What are JDK, JRE and JVM?

JDK provides development tools, JRE provides the runtime environment, and JVM executes Java bytecode.

What does WORA mean?

WORA means Write Once, Run Anywhere and refers to Java's portable bytecode execution model across supported platforms.

What I Learned From This Lesson

This lesson connected almost everything I had learned in the previous three lessons.

At first, I was looking at these as separate terms:

Java
javac
.class
JVM
JRE
JDK
main()
WORA

Now I can connect them.

Java Source Code
      ↓
    .java
      ↓
    javac
      ↓
  Bytecode
      ↓
    .class
      ↓
    JVM
      ↓
   main()
      ↓
  Execution
      ↓
   Output
Enter fullscreen mode Exit fullscreen mode

And around that execution process:

JDK
 ↓
Development tools

JRE
 ↓
Runtime environment

JVM
 ↓
Executes bytecode
Enter fullscreen mode Exit fullscreen mode

The biggest thing I understood is that Java's platform independence doesn't mean the JVM is the same everywhere.

Instead:

The bytecode is portable, while each platform provides an appropriate JVM implementation to execute it.

That one idea made WORA much easier for me to understand.

A Note for Other Beginners

If you are confused by JVM, JRE, JDK and bytecode, don't try to memorize four definitions separately.

Start with one simple journey:

Write Java
    ↓
.java
    ↓
javac
    ↓
.class
    ↓
Bytecode
    ↓
JVM
    ↓
main()
    ↓
Output
Enter fullscreen mode Exit fullscreen mode

Then remember the roles:

JDK → develop

JRE → runtime

JVM → execute

Once this mental model becomes clear, many later Java concepts become much easier to understand.

📚 Related Java Learning Resources

This article is part of my Java Learning Notes — Telusko Core Java series.

If you are following the series from the beginning:

👉 Video 01 — Java Introduction: 8 Questions I Had as a Beginner and Their Easy Answers

👉 Video 02 — Setting Up Java: 6 Questions I Had About JDK, VS Code, LTS and PATH

👉 Video 03 — Writing Your First Java Code: 5 Questions I Had as a Beginner

I also wrote a separate article while researching the history behind Java:

👉 Java Introduction: What Is Java, Who Created It, and How Sun Microsystems Became Oracle?

🔗 My Java Learning Notes

I am maintaining the complete structured notes and resources in my GitHub repository.

👉 Java Learning Notes — Telusko Core Java

The GitHub repository contains my concise learning notes and resources, while these DEV.to articles go deeper into the questions and concepts that I found confusing during my learning.

Final Takeaway

For me, Video 04 was the lesson where the Java execution model finally started making sense.

I can now look at:

Hello.java
Enter fullscreen mode Exit fullscreen mode

and understand what happens next:

Hello.java
    ↓
javac
    ↓
Hello.class
    ↓
Bytecode
    ↓
JVM
    ↓
main()
    ↓
Output
Enter fullscreen mode Exit fullscreen mode

And I can remember the three terms that initially confused me:

JDK → Development
JRE → Runtime
JVM → Execution
Enter fullscreen mode Exit fullscreen mode

The next step is to stop just understanding how Java runs and start understanding the actual Java language itself — variables, data types, and how we store information in a program.


This is part of my ongoing Java learning journey. I'm documenting what I learn, the questions I get stuck on, and the explanations that finally make the concepts click for me — hopefully they can help another beginner too.

Top comments (0)