Core and Web-based Java

Java Platform, JVM, Types and Program Execution

PGCP-AC

Java separates source-language rules from runtime execution through class files and the Java Virtual Machine. Understanding compilation, loading, types, conversions, runtime memory and program startup provides the foundation for object-oriented code, libraries, exceptions, collections and server applications.

1. From source to execution

Java source is compiled into class files containing bytecode. A JVM loads classes, verifies their structure, links references, initializes classes when required and executes instructions. Execution may combine interpretation and just-in-time compilation. The JDK supplies development tools such as javac as well as runtime facilities. Portability comes from a defined bytecode and runtime contract; a suitable JVM is still required for each platform.

A conventional Java 17 application starts with public static void main(String[] args). Packages organize names; imports make names convenient to use without copying code into a file. A public top-level class normally shares its name with the source file. The classpath tells tools where to locate classes and libraries. Compilation errors prevent valid class generation; runtime exceptions occur during execution of otherwise compiled code.

2. Values and storage

Java has eight primitive types. Integer types have specified widths; char is an unsigned 16-bit UTF-16 code unit, not a complete representation of every Unicode character. Boolean is a logical type and is not an integer in Java expressions. Reference variables hold references to objects or null. Arrays and strings are reference types. Fields receive default values, but local variables must be definitely assigned before use.

public class Total {
    public static void main(String[] args) {
        int count = 4;
        double average = 15.0 / count;
        System.out.println(average); // 3.75
    }
}

Each invocation has a stack frame containing execution information and local variables; objects are managed by the runtime. The JVM specification defines logical runtime areas and implementations may optimize physical allocation. Garbage collection reclaims unreachable storage; it is not a substitute for closing external resources. Avoid assuming that a reference has a predictable address or that every JVM has identical internal memory organization.

3. Runtime areas and primitive ranges

The JVM's logical runtime areas include per-thread stacks and program counters, shared heap storage and class-related runtime structures. Stack frames contain local-variable slots and an operand stack used while executing bytecode. Class loading, verification, preparation, resolution and initialization are related but distinct stages; declaring a reference is not the same operation as constructing an instance.

PrimitiveWidth or role
byteSigned 8-bit integer
shortSigned 16-bit integer
intSigned 32-bit integer
longSigned 64-bit integer
charUnsigned 16-bit UTF-16 code unit
float32-bit floating-point value
double64-bit floating-point value
booleanLogical true or false; no language-level sizeof operator

For a signed b-bit integer, the range is minus 2 raised to b-1 through 2 raised to b-1 minus one. A narrowing cast can discard information. Integer arithmetic overflow wraps according to Java's fixed-width rules rather than behaving like C++ signed overflow.

4. JDK, runtime and JVM

The Java Development Kit (JDK) supplies tools for developing and running Java software. These include the compiler javac, launcher java, documentation and archive tools, the standard libraries and a runtime implementation.

The JVM is the abstract execution environment defined for class files. A concrete JVM implementation loads and verifies classes, manages runtime data, executes bytecode, compiles frequently used paths when profitable, manages threads and performs garbage collection.

Historically, the term JRE described a separately distributed runtime containing a JVM and libraries without development tools. Modern JDK releases and application runtime images have changed packaging practices, but the conceptual distinction between development tools and runtime facilities remains useful.

“Write once, run anywhere” means compiled class files target a defined runtime contract. It does not mean one native executable runs directly on every processor. Each platform needs a compatible JVM and platform-dependent libraries or assumptions can still reduce portability.

5. Compilation and class files

Hello.java --javac--> Hello.class --JVM--> program execution

javac performs lexical, syntactic, type, access and definite-assignment checks before emitting valid class files. A class file contains bytecode, symbolic references, method information and metadata rather than ordinary source or one platform's final machine code.

javac -d out src/com/example/Hello.java
java -cp out com.example.Hello

The -d option places output in a directory hierarchy matching packages. The launcher receives a binary class name, not a source path. The classpath tells classpath-based tools where to locate application classes and libraries.

A compile-time error such as an unknown variable prevents normal class generation for that compilation unit. A runtime exception occurs after valid code has begun executing, such as integer division by zero.

Java lexical tokens

Before parsing declarations and statements, the compiler divides source text into tokens. Keywords such as class, if and return have reserved language meanings. Identifiers name types, methods, variables, packages and other program elements. Literals write fixed values such as 42, 3.5, 'A', true and "text". Operators form expressions, while separators such as parentheses, braces, commas, semicolons and dots organize program structure.

Identifiers are case-sensitive and cannot be a keyword or the literals true, false and null. They may contain permitted Unicode letters, digits after the first character, currency symbols and connector characters, although conventional Java names favor readable letters and digits. Whitespace and comments separate tokens but ordinarily do not become executable instructions. A lexical error, malformed literal or missing separator is diagnosed before type checking can succeed.

6. Loading, linking and initialization

Class use involves related but distinct steps:

  1. Loading: a class loader obtains class binary data and creates the runtime representation.
  2. Verification: the JVM checks structural and bytecode safety constraints.
  3. Preparation: storage for static fields is prepared with initial default values.
  4. Resolution: symbolic references are translated to runtime references, eagerly or lazily as permitted.
  5. Initialization: static field initializers and static initialization blocks execute in textual order.

Merely declaring Widget widget; does not construct a Widget. Loading a class is not the same as creating an instance and preparation defaults are not the same as explicit static initialization.

7. Program entry point

package com.example;

public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, " + (args.length == 0 ? "world" : args[0]));
    }
}

For the conventional Java 17 application launcher entry point:

  • public makes the method accessible to the launcher;
  • static allows invocation without constructing Hello;
  • void means no value is returned;
  • main is the recognized method name;
  • String[] args contains command-line arguments after the class name.

String... args is equivalent for this parameter purpose. Java is case-sensitive: Main and main are different identifiers. Returning an operating-system status is normally done with process facilities rather than changing main's return type.

8. Packages, imports and file naming

A package organizes types into a namespace and supports access control. Its declaration should correspond to the source organization expected by the build. A public top-level class is normally stored in a source file with the same case-sensitive name.

An import makes a type or static member available by a shorter source name. It does not copy source code, construct objects or necessarily load the class at that moment. Types in java.lang are implicitly available by simple name. Types in the same package need no import.

Wildcard imports do not recursively import subpackages and two imported types with the same simple name require disambiguation through a fully qualified name.

9. Primitive types

Java defines exactly eight primitive types:

TypeMeaningImportant property
byteSigned integer8 bits
shortSigned integer16 bits
intSigned integer32 bits
longSigned integer64 bits
charUTF-16 code unitUnsigned 16 bits
floatBinary floating point32 bits
doubleBinary floating point64 bits
booleanLogical valuetrue or false

For a signed integer width b, the range is -2^(b-1) through 2^(b-1)-1. Java does not define boolean as an integer and there is no language-level sizeof operator for asking primitive storage size.

A char stores one UTF-16 code unit. Many characters fit in one code unit, while supplementary Unicode characters require a surrogate pair. Code that processes user-perceived characters must not assume String.length() always counts complete characters.

10. Literals

Integer literals are ordinarily int when representable. Use an L suffix for a long literal when necessary and prefer uppercase L because lowercase l resembles the digit one.

long population = 8_100_000_000L;
int mask = 0b1111_0000;
int color = 0xFF_AA_00;
double rate = 1.8e1;
float ratio = 0.75F;
char newline = '\n';

Floating-point literals are double by default; assigning one to float requires an F suffix or an explicit conversion. Underscores can improve readability between digits but cannot appear in arbitrary positions.

11. Reference types and null

Classes, interfaces, arrays, enums, records and strings are reference types. A reference variable can identify an object compatible with its declared type or contain null.

String first = new String("Java");
String alias = first;
String absent = null;

first and alias hold references to the same object. Assigning alias = null changes that variable only; it does not modify the object or the first variable. Dereferencing null produces NullPointerException at runtime.

Java passes argument values by value. Passing an object reference copies the reference value, so a method can mutate the shared object but cannot reassign the caller's variable by assigning its parameter.

12. Default values and definite assignment

Instance fields, static fields and array components receive default values. Numeric fields become zero, boolean becomes false, char becomes the zero code unit and reference fields become null.

Local variables do not receive automatic default values for source-language use. The compiler performs definite-assignment analysis:

int result;
if (args.length > 0) {
    result = 10;
}
// System.out.println(result); // compile-time error: not definitely assigned

Initializing every local to an arbitrary zero merely to silence the compiler can hide missing logic. Ensure every control-flow path assigns a meaningful value before use.

13. Numeric promotion and arithmetic

Arithmetic on byte, short and char operands commonly promotes them to int. Thus:

byte a = 10;
byte b = 20;
int sum = a + b;
// byte wrong = a + b; // compile-time error without a narrowing conversion

If either operand has a wider numeric type, binary numeric promotion chooses an appropriate common type. Integer division discards the fractional remainder:

System.out.println(15 / 4);   // 3
System.out.println(15.0 / 4); // 3.75

The operand types decide the operation before assignment. double answer = 15 / 4; calculates integer 3 and then widens it to 3.0.

14. Widening, narrowing and overflow

A widening primitive conversion generally moves to a type able to represent the source range, although moving a large integer to floating point can lose precision. A narrowing conversion requires an explicit cast and may discard high bits, range or precision.

int value = 130;
byte narrowed = (byte) value; // -126 after low-bit preservation

Fixed-width integer overflow wraps using two's-complement arithmetic. For example, Integer.MAX_VALUE + 1 produces Integer.MIN_VALUE. This is defined Java behavior, but usually indicates a domain defect. Exact arithmetic helpers such as Math.addExact can throw on overflow when detection is required.

Floating-point values include infinities, signed zero and NaN. Floating-point division by zero behaves differently from integer division by zero.

15. Strings and equality

String is a final reference type whose instances are immutable. Concatenation produces a result without changing existing strings. String literals may refer to interned instances, but program logic should compare string content using equals rather than relying on reference identity with ==.

String input = new String("java");
System.out.println(input == "java");      // false: identity
System.out.println(input.equals("java")); // true: content

Immutability supports sharing and safe use as map keys when equality and hash behavior are consistent. For repeated text construction, use a mutable builder rather than creating excessive intermediate results.

16. Runtime data areas

The JVM specification describes logical runtime areas:

  • each thread has a program counter and JVM stack;
  • each method invocation creates a frame with local-variable slots, an operand stack and execution data;
  • the heap stores class instances and arrays managed by garbage collection;
  • the method area concept stores per-class structures such as runtime constants, field information and method code;
  • native method support has related runtime structures.

These are logical roles, not a promise that every implementation maps each one to a simple fixed physical region. JIT escape analysis and other optimizations may change physical allocation while preserving observable language behavior.

17. Garbage collection and resources

An object becomes eligible for garbage collection when no live path from runtime roots can reach it. Eligibility does not promise immediate reclamation or a predictable order. Assigning null is rarely a required manual memory-management step; object lifetime is usually controlled by scope and references.

Garbage collection reclaims managed memory. It does not reliably close files, database connections, sockets or locks. Those external resources require explicit structured cleanup, commonly try-with-resources.

18. Complete execution trace

package demo;

public class Average {
    private static final int SUBJECTS = 4;

    public static void main(String[] args) {
        int total = args.length == 0 ? 60 : Integer.parseInt(args[0]);
        double average = (double) total / SUBJECTS;
        System.out.printf("Average: %.2f%n", average);
    }
}
  1. javac resolves names and types and emits demo/Average.class.
  2. The launcher locates demo.Average through its runtime path.
  3. The JVM loads, links and initializes the class, assigning SUBJECTS its constant value.
  4. A main frame receives the argument array.
  5. The selected string is parsed or the default is used.
  6. The explicit cast makes the division floating point.
  7. Formatting writes the result; normal completion ends the non-daemon application work.

Invalid numeric input compiles successfully but throws during execution, demonstrating the distinction between compile-time type correctness and runtime data validity.

19. Practical considerations

  1. javac compiles source; java launches a class.
  2. Class files contain bytecode, not universally final native code.
  3. JDK includes development tools; JVM is the execution environment.
  4. Imports shorten names and do not copy or instantiate classes.
  5. String and arrays are reference types.
  6. Fields receive defaults; local variables require definite assignment.
  7. Char is one UTF-16 code unit, not necessarily a complete character.
  8. Integer division occurs before widening the result.
  9. Narrowing casts can lose information and integer overflow wraps.
  10. Garbage collection does not replace external-resource cleanup.

Continue learning

Related notes

Put this topic into timed practice

Open mock tests when you want full-exam pacing, or keep drilling in practice mode.