Java Inside the JVM
The JVM is the program that runs Java bytecode. A compiler turns source code into bytecode first, and the JVM runs that bytecode on the machine.
Source code runs as bytecode
This source compiles into two class files. The JVM loads the bytecode and runs it.
public class Main {
public static void main(String[] args) {
Greeter greeter = new Greeter();
System.out.println(greeter.greet("bytecode"));
}
}
class Greeter {
public String greet(String name) {
return "Hello, " + name;
}
}The class object names its members
The runtime keeps a Class object for every loaded class. This program reads the declared method names from it and prints them in sorted order.
import java.lang.reflect.Method;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Method[] methods = Greeter.class.getDeclaredMethods();
String[] names = new String[methods.length];
for (int i = 0; i < methods.length; i++) {
names[i] = methods[i].getName();
}
Arrays.sort(names);
System.out.println("Class: " + Greeter.class.getSimpleName());
for (String name : names) {
System.out.println("Method: " + name);
}
}
}
class Greeter {
public String greet(String name) {
return "Hello, " + name;
}
}Example
import java.io.InputStream;
public class Main {
public static void main(String[] args) throws Exception {
String javap = System.getProperty("java.home") + "/bin/javap";
String listing = run(javap, "-p", "Greeter.class");
for (String line : listing.split("\n")) {
String trimmed = line.trim();
if (trimmed.startsWith("class") || trimmed.contains("greet(")) {
System.out.println(trimmed);
}
}
String code = run(javap, "-c", "Greeter.class");
long invokes = code.lines().filter(line -> line.contains("invoke")).count();
System.out.println("invoke lines: " + invokes);
}
static String run(String... command) throws Exception {
Process process = new ProcessBuilder(command).redirectErrorStream(true).start();
String text;
try (InputStream in = process.getInputStream()) {
text = new String(in.readAllBytes());
}
process.waitFor();
return text;
}
}
class Greeter {
public String greet(String name) {
return "Hello, " + name;
}
}Key points
- javac compiles each source file into a class file of bytecode.
- The JVM starts by interpreting bytecode.
- The JIT compiler translates hot bytecode into native machine code while the program runs.
- The classpath is one shared shelf where every class is visible to every other class.
- The modulepath enforces each module exports list, so hidden packages stay hidden.
- The garbage collector frees objects that no reference reaches.
- Programs never call the garbage collector directly.
- javap reads a class file and prints its bytecode in text form.
In this example, the program runs javap on the Greeter class file through ProcessBuilder and prints only the filtered lines, so the class header, the method signature, and the invoke count are the evidence.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What does javap show?