0% found this document useful (0 votes)
83 views36 pages

Lecture 2 Java Virtual Machine

Uploaded by

Abcd Efgh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
83 views36 pages

Lecture 2 Java Virtual Machine

Uploaded by

Abcd Efgh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 36

Maharaja Agrasen Institute of

Technology
CIC-212
Java Programming

Lecture 2

Java Virtual Machine


What this Topic is About
We look at the JVM as an example of a real-world runtime system
for a modern object-oriented programming language.

JVM is probably the most common and widely used VM in the


world, so you’ll get a better idea what a real VM looks like.
• JVM is an abstract machine.
• What is the JVM architecture?
• What is the structure of .class files?
• How are JVM instructions executed?
• What is the role of the constant pool in dynamic linking?

Also visit this site for more complete information about the JVM:
http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html

2
Abstract
Machines
Abstract machine implements an intermediate language in between the
high-level language (e.g. Java) and the low-level hardware (e.g.
Pentium) Implemented in Java:
High level Java Java Machine independent

Java compiler

JVM (.class files)


Java JVM interpreter
or JVM JIT compiler

Low level Pentium Pentium

3
Abstract
Machines
An abstract machine is intended specifically as a runtime
system for a particular (kind of) programming language.
• JVM is a virtual machine for Java programs.
• It directly supports object-oriented concepts such as
classes, objects, methods, method invocation etc.
• Easy to compile Java to JVM
1. easy to implement compiler
2. fast compilation
• Another advantage: portability

4
Class Files and Class File
External representation Format
(platform independent) JVM
Internal representation
.class files
(implementation dependent)
load
classes primitive types
arrays
objects strings
methods

The JVM is an abstract machine in the truest sense of the word.


The JVM specification does not give implementation details (can be
dependent on target OS/platform, performance requirements, etc.)
The JVM specification defines a machine independent “class file
format” that all JVM implementations must support.

5
Data Types
JVM (and Java) distinguishes between two kinds:

Primitive types:
• boolean: boolean
• numeric integral: byte, short, int, long, char
• numeric floating point: float, double
• internal, for exception handling: returnAddress
Reference types:
• class types
• array types
• interface types

Note: Primitive types are represented directly, reference types are


represented indirectly (as pointers to array or class instances).

6
Java JVM Run-time Data
Areas
Types of Java JVM Run-time Memory
Areas,

1. Program Counter (PC) Register


2. Java Virtual Machine Stacks
3. Heap Memory
4. Method Area
5. Run-time Constant Pool
6. Native Method Stacks
These six JVM run-time memory areas can
be broadly classified into two groups:

1. Managed per-thread – If the memory area


is uniquely allocated for every single
thread created. These data area are
initialized on thread start and destroyed
once the thread completes.
2. Shared with all threads – If the memory
area is common and can be accessed by
all the threads. These are initialized when
JVM is started and destroyed on
shutdown.
7
Java JVM Runtime Data Areas
1. Program Counter (PC)
Register

In general computer architecture


terms, program counter (PC) register
keeps track of the current instruction
executing at any moment. That is like a
pointer to the current instruction in
sequence of instructions in a program.
This is same in Java JVM terms also. We
have multithreaded architecture as Java
supports multithreading and so, a program
counter (PC) Register is created every
time a new thread is created. PC keeps a
pointer to the current statement that is
being executed in its thread. If the current
executing method is ‘native’, then the
value of program counter register will be
undefined.
Java JVM Runtime Data Areas
2. Java Virtual Machine Stacks
JVM stacks are used to store Java virtual machine frames. JVM will not do
any manipulation directly with the stacks and they are only storage units for
frames. Memory size of stacks can be of two types, fixed and varying size.
Varying size can dynamically expand as per the need. Java JVM frames are
created when a method is invoked, it performs the dynamic linking. JVM
stacks are created and managed for each thread.

• StackOverflowError – this error occurs in fixed size JVM stacks, if the


memory size is not sufficient during the program execution.

• OutOfMemoryError – in dynamic sized stacks, while trying to expand for


more memory need and there is no additional memory available to allocate
and we get OutOfMemoryError.
Java JVM Runtime Data Areas
3. Heap Memory
Heap data area is used to store objects of classes and arrays. Heap memory
is common and shared across multiple threads. This is where the garbage
collector comes into picture. Heap data area is created at VM startup.
Claiming the memory back is done automatically by the garbage collector
(GC). This is one of the best feature of Java. If the allocated memory is not
sufficient at run-time JVM can throw OutOfMemoryError.

4. Method Area
In general, method area is a logical part of heap area. But that is left to the
JVM implementers to decide. Method area has per class structures and
fields. Nothing but static fields and structures. It also includes the method
data, method and constructor code, run-time constant pool. Method area is
created at JVM startup and shared among all the threads. JVM will throw
OutOfMemoryError if the allocated memory area is not sufficient during the
run-time.
Java JVM Runtime Data Areas
5. Run-time Constant Pool
Run-time constant pool is created out of the method area and it is
created by JVM when a class or interface is created. Run-time
constant pool contains the constant_pool table which is
applicable for per class or interface. It contains the literals. JVM
will throw OutOfMemoryError when it cannot find memory to
allocate to run-time constant pool.
6. Native Method Stacks
JVM that supports native methods will have native method
stacks. It is used for native methods, and created per thread. If
the native methods cannot be loaded by a JVM then it need not
have native method stacks. Memory size is managed similar to
general JVM stacks like fixed or dynamic. JVM will throw
StackOverflowError or OutOfMemoryError accordingly.
Java Stacks
JVM is a stack based machine.
JVM instructions
• implicitly take arguments from the stack top
• put their result on the top of the stack
The stack is used to
• pass arguments to methods
• return a result from a method
• store intermediate results while evaluating expressions
• store local variables

This works similarly to (but not exactly the same as) what we
previously discussed about stack-based storage allocation and
routines.

12
Java Frame
The Java stack consists of frames. The JVM specification does not say
exactly how the stack and frames should be implemented.
The JVM specification specifies that a stack frame has areas for:

Pointer to runtime constant pool


args A new call frame is created by executing
+ some JVM instruction for invoking a
local vars
method (e.g. invokevirtual,
operand stack invokenonvirtual, ...)
The operand stack is initially empty,
but grows and shrinks during execution.

13
Java Frame
The role/purpose of each of the areas in a stack frame:

pointer to Used implicitly when executing JVM


constant pool instructions that contain entries into the
args constant pool (more about this later).
+ Space where the arguments and local variables
local vars
of a method are stored. This includes a space
operand stack for the receiver (this) at position/offset 0.

Stack for storing intermediate results


during the execution of the method.
• Initially it is empty.
• The maximum depth is known at
compile time.

14
Java Frame
An implementation using registers such as SB, ST, and LB and a
dynamic link is one possible implementation.
SB to previous frame on the stack

LB
dynamic link
to runtime constant pool
args JVM instructions store and load
+ (for accessing args and locals) use
local vars addresses which are numbers
from 0 to #args + #locals - 1
operand stack

ST
15
JVM Interpreter
The core of a JVM interpreter is basically this:
do {
byte opcode = fetch an opcode;
switch (opcode) {
case opCode1 :
fetch operands for opCode1;
execute action for opCode1;
break;
case opCode2 :
fetch operands for opCode2;
execute action for opCode2;
break;
case ...
} while (more to do)

16
Instruction-set: typed
instructions!
JVM instructions are explicitly typed: different opCodes for instructions
for integers, floats, arrays, reference types, etc.

This is reflected by a naming convention in the first letter of the opCode


mnemonics:

Example: different types of “load” instructions


iload integer load
lload long load
fload float load
dload double load
aload reference-type load

17
Instruction-set: typed
instructions!
JVM instructions have three kinds of operands:
- from the top of the operand stack
- from the bytes following the opCode
- part of the opCode itself
Each instruction may have different “forms” supporting different
kinds of operands.
Example: different forms of “iload”
Assembly code Binary instruction code layout
iload_0 26
iload_1 27
iload_2 28
iload_3 29
iload n 21 n
wide iload n 196 21 n

18
Instruction-set: accessing
arguments and locals
arguments and locals area inside a stack frame

0:
1: args: indexes 0 .. #args - 1
2:
3: locals: indexes #args .. #args + #locals - 1

• A load instruction takes something


Instruction examples:
from the args/locals area and pushes
iload_1 istore_1 it onto the top of the operand stack.
iload_3 astore_1 • A store instruction pops something
aload 5 fstore_3 from the top of the operand stack
aload_0 and places it in the args/locals area.

19
Instruction-set: non-local
memory access
In the JVM, the contents of different “kinds” of memory can be
accessed by different kinds of instructions.
accessing locals and arguments: load and store instructions
accessing fields in objects: getfield, putfield
accessing static fields: getstatic, putstatic

Note: Static fields are a lot like global variables. They are allocated
in the “method area” where also code for methods and
representations for classes (including method tables) are stored.

Note: getfield and putfield access memory in the heap.


Note: JVM doesn’t have anything similar to registers L1, L2, etc.

20
Instruction-set: operations on
numbers
Arithmetic
add: iadd, ladd, fadd, dadd
subtract: isub, lsub, fsub, dsub
multiply: imul, lmul, fmul, dmul
etc.
Conversion
i2l, i2f, i2d,
l2f, l2d, f2d,
f2i, d2i, …

21
Instruction-set …

Operand stack manipulation


pop, pop2, dup, dup2, swap, …

Control transfer
Unconditional: goto, jsr, ret, …
Conditional: ifeq, iflt, ifgt, if_icmpeq, …

22
Instruction-set …
Method invocation:
invokevirtual: usual instruction for calling a method on an
object.
invokeinterface: same as invokevirtual, but used
when the called method is declared in an interface (requires a
different kind of method lookup)
invokespecial: for calling things such as constructors,
which are not dynamically dispatched (this instruction is also
known as invokenonvirtual).
invokestatic: for calling methods that have the “static”
modifier (these methods are sent to a class, not to an object).
Returning from methods:
return, ireturn, lreturn, areturn, freturn,

23
Instruction-set: Heap
Memory Allocation
Create new class instance (object):
new

Create new array:


newarray: for creating arrays of primitive types.
anewarray, multianewarray: for arrays of reference
types.

24
Instructions and the
“Constant Pool”
Many JVM instructions have operands which are indexes pointing to
an entry in the so-called constant pool.
The constant pool contains all kinds of entries that represent
“symbolic” references for “linking”. This is the way that instructions
refer to things such as classes, interfaces, fields, methods, and
constants such as string literals and numbers.
These are the kinds of constant pool entries that exist:
• Class_info • Integer
• Fieldref_info • Float
• Methodref_info • Long
• InterfaceMethodref_info • Double
• String • Name_and_Type_info
• Utf8_info (Unicode characters)

25
Instructions and the
“Constant Pool”
That previous picture is rather complicated, let’s simplify it a little:
Format: 180 indexbyte1 indexbyte2

Fieldref

Class Name_and_Type

Utf8Info Utf8Info Utf8Info


fully qualified name of field field descriptor
class name

26
Instructions and the “Constant Pool”
Java Virtual Machine instructions do not rely on the
Table 4.3. Constant pool tags
run-time layout of classes, interfaces, class
instances, or arrays. Instead, instructions refer to Constant Type Value

symbolic information in the constant_pool table. CONSTANT_Class 7

All constant_pool table entries have the following CONSTANT_Fieldref 9


general format: CONSTANT_Methodref 10
CONSTANT_InterfaceMethodref 11
cp_info
CONSTANT_String 8
{
u1 tag; CONSTANT_Integer 3
u1 info [ ]; CONSTANT_Float 4
}
CONSTANT_Long 5
Each item in the constant_pool table must begin
CONSTANT_Double 6
with a 1-byte tag indicating the kind
of cp_info entry. The contents of the info array CONSTANT_NameAndType 12

vary with the value of tag. The valid tags and their CONSTANT_Utf8 1
values are listed in Table 4.3. Each tag byte must be CONSTANT_MethodHandle 15
followed by two or more bytes giving information CONSTANT_MethodType 16
about the specific constant. The format of the
CONSTANT_InvokeDynamic 18
additional information varies with the tag value.

27
Instructions and the “Constant Pool”
The CONSTANT_Class_info Structure
The CONSTANT_Class_info structure is used to represent a class or an interface:

CONSTANT_Class_info
{
u1 tag;
u2 name_index;
}

The items of the CONSTANT_Class_info structure are the following:

tag: The tag item has the value CONSTANT_Class (7).

name_index: The value of the name_index item must be a valid index into
the constant_pool table. The constant_pool entry at that index must be
a CONSTANT_Utf8_info structure representing a valid binary class or interface name
encoded in internal form .

28
Instructions and the “Constant Pool”
The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and
CONSTANT_InterfaceMethodref_info Structures
Fields, methods, and interface methods are represented by similar structures:
Tag:
The tag item of a CONSTANT_Fieldref_info structure has the
CONSTANT_Fieldref_info
value CONSTANT_Fieldref (9).
{ The tag item of a CONSTANT_Methodref_info structure has the
u1 tag; value CONSTANT_Methodref (10).
The tag item of a CONSTANT_InterfaceMethodref_info structure has the
u2 class_index;
value CONSTANT_InterfaceMethodref (11).
u2 name_and_type_index;
} class_index:
The value of the class_index item must be a valid index into the constant_pool table.
The constant_pool entry at that index must be a CONSTANT_Class_info structure
CONSTANT_Methodref_info representing a class or interface type that has the field or method as a member.
{ The class_index item of a CONSTANT_Methodref_info structure must be a class
u1 tag; type, not an interface type.
The class_index item of a CONSTANT_InterfaceMethodref_info structure must
u2 class_index; be an interface type.
u2 name_and_type_index; The class_index item of a CONSTANT_Fieldref_info structure may be either a class
type or an interface type.
}
name_and_type_index:
CONSTANT_InterfaceMethodref_infoThe value of the name_and_type_index item must be a valid index into
the constant_pool table. The constant_pool entry at that index must be
{
a CONSTANT_NameAndType_info structure. Thisconstant_pool entry indicates
u1 tag; the name and descriptor of the field or method.
u2 class_index; In a CONSTANT_Fieldref_info, the indicated descriptor must be a field descriptor.
Otherwise, the indicated descriptor must be a method descriptor.
u2 name_and_type_index; If the name of the method of a CONSTANT_Methodref_info structure begins with a
} `` '<' ('\u003c'), then the name must be the special name <init>, representing an instance
initialization method. The return type of such a method must be void.

29
Instructions and the “Constant Pool”
The constant entries format is part of the Java class file format.

Luckily, we have a Java assembler that allows us to write a kind of


textual assembly code and that is then transformed into a
binary .class file.

This assembler takes care of creating the constant pool entries for us.
When an instruction operand expects a constant pool entry the
assembler allows you to enter the entry “in place” in an easy syntax.

Example:
getfield mypackage/Queue i I

30
Instructions and the “Constant Pool”
Fully qualified class names and descriptors in constant pool UTF8
entries.
1. Fully qualified class name: a package + class name string. Note
this uses “/” instead of “.” to separate each level along the path.

2. Descriptor: a string that defines a type for a method or field.


Java descriptor
boolean Z
integer I
Object Ljava/lang/Object;
String[] [Ljava/lang/String;
int foo(int,Object) (ILjava/lang/Object;)I

31
Linking
In general, linking is the process of resolving symbolic references in
binary files.

Most programming language implementations have what we call


“separate compilation”. Modules or files can be compiled separately
and transformed into some binary format. But since these separately
compiled files may have connections to other files, they have to be
linked.

=> The binary file is not yet executable, because it has some kind of
“symbolic links” in it that point to things (classes, methods, functions,
variables, etc.) in other files/modules.

Linking is the process of resolving these symbolic links and replacing


them by real addresses so that the code can be executed.

32
Loading and Linking in
In JVM, loading and linking of class files happens at runtime, while
the program is running!
JVM
Classes are loaded as needed.

The constant pool contains symbolic references that need to be


resolved before a JVM instruction that uses them can be executed
(this is the equivalent of linking).

In JVM a constant pool entry is resolved the first time it is used by a


JVM instruction.
Example:
When a getfield is executed for the first time, the constant pool
entry index in the instruction can be replaced by the offset of the field.

33
Closing Example
As a closing example on the JVM, we will take a look at the
compiled code of the following simple Java class declaration.

class Factorial {

int fac(int n) {
int result = 1;
for (int i=2; i<n; i++) {
result = result * i;
}
return result;
}
}

34
Closing Example
Compiling and Disassembling
% javac Factorial.java
% javap -c -verbose Factorial
Compiled from Factorial.java
class Factorial extends java.lang.Object {
Factorial();
/* Stack=1, Locals=1, Args_size=1 */
int fac(int);
/* Stack=2, Locals=4, Args_size=2 */
}

Method Factorial()
0 aload_0
1 invokespecial #1 <Method java.lang.Object()>
4 return

35
Compiling and
Method int Disassembling
// address: 0
fac(int)
1 2
...i
// stack: this n result
3

0 iconst_1 // stack: this n result i 1


1 istore_2 // stack: this n result i
2 iconst_2 // stack: this n result i 2
3 istore_3 // stack: this n result i
4 goto 14
7 iload_2 // stack: this n result i result
8 iload_3 // stack: this n result i result i
9 imul // stack: this n result i result*i
10 istore_2 // stack: this n result i
11 iinc 3 1 // stack: this n result i
14 iload_3 // stack: this n result i i
15 iload_1 // stack: this n result i i n
16 if_icmplt 7 // stack: this n result i
19 iload_2 // stack: this n result i result
20 ireturn

36

Common questions

Powered by AI

The JVM handles method overloading and overriding at the bytecode level through its method invocation instructions and the constant pool's Methodref entries. Overloading is resolved at the compile-time by the compiler selecting the appropriate method signature, whereas overriding is managed at runtime using dynamic dispatch. The invokevirtual and similar instructions use Methodref entries to determine the actual method to call dynamically based on the object's type at runtime, rather than the reference type. This flexibility allows Java to support polymorphism and dynamic typing efficiently .

The Run-time Constant Pool is crucial in JVM execution as it provides a centralized storage of constants and symbolic references that methods and instructions throughout a class need. This pool speeds up execution by allowing quick access to frequently used constants and facilitates the JVM's dynamic linking capabilities, enabling resolution of method and field references at runtime. This dynamic resolution during execution makes Java programs flexible and adaptable to changes. It also supports the JVM's ability to execute platform-independent bytecode by maintaining all symbolic constants needed across different hardware platforms in a uniform manner .

The JVM ensures thread safety within its runtime data areas through isolated thread-specific stacks and synchronized access to shared data structures like the heap and method area. Each thread maintains an independent stack and program counter to hold method frames individually, preventing interference in execution among threads. Synchronization mechanisms, such as locks and monitors, are used to manage access to shared data, ensuring memory consistency and preventing race conditions. This architecture supports Java's robust concurrency model, leveraging the OS and hardware capabilities to provide a scalable environment for multithreaded applications .

The JVM optimizes execution time of method calls in a multi-threaded environment by implementing various techniques like Just-In-Time (JIT) compilation and efficient stack management. JIT compilation translates frequently executed bytecode into native machine code at runtime, significantly reducing execution time of hot spots. Each thread has its own program counter and stack, minimizing overhead associated with context switching and allowing independent method execution. Additionally, JVM's garbage collection runs concurrently with application threads, ensuring efficient memory management without halting program execution, which is crucial in handling multiple threads effectively .

JVM instructions utilize the constant pool by referring to symbolic references instead of direct addresses. Unlike traditional compiled languages that resolve symbols and addresses at compile time into symbol tables, JVM defers binding until execution, allowing dynamic loading and linking. The constant pool facilitates this process with entries like Methodref, Fieldref, and Class_info that can be resolved at runtime as needed, allowing a level of indirection that provides flexibility and adaptiveness to runtime conditions. This contrasts with static symbol tables in traditional languages, limiting such adaptability .

JVM handles memory management for object allocation through the heap memory area, which is shared among all threads and used to store class instances and arrays. Upon JVM startup, the heap is created and managed by the garbage collector, which automatically reclaims memory occupied by objects no longer reachable from a thread's operation stack or static variables. This process prevents memory leaks and optimizes resource utilization, with the garbage collector freeing up space when memory demand exceeds availability. Consequently, this system allows developers to focus on application logic without manual memory deallocation .

Dynamic linking is a critical aspect of the JVM's constant pool as it allows symbolic references within class files to be resolved at runtime, thereby enabling flexibility and efficiency. The constant pool contains symbolic information necessary for executing methods and accessing fields. When a JVM instruction uses a constant pool entry for the first time, the symbolic reference is resolved into a direct value or address, improving execution efficiency. This process removes the need for a fixed linkage at compile time, thus offering runtime adaptability and facilitating efficient execution .

As a stack-based machine, the JVM uses the stack for all its instruction executions, including pushing method arguments, managing return values, and storing intermediate computation results. This impacts execution by simplifying the instruction set since operations implicitly address the stack's top, allowing for concise opcodes. This design reduces the need for complex addressing modes and makes the instruction set more compact. However, this can potentially lead to excessive stack operations for complex expressions compared to register-based architectures. The instruction set's simplicity aids JIT compilers in optimizing these operations for faster performance .

The Java Virtual Machine Stacks play a pivotal role in method invocations and managing local variables by providing storage for frames, each corresponding to a method call. When a method is invoked, a new frame is created, containing space for the local variables, the operand stack, and any additional information needed for execution. The frames facilitate parameter passing, local variable assignments, and the execution of method operations. JVM stacks are crucial for maintaining method execution state across concurrent threads, with each thread having its own stack. This isolation enhances the thread-safety of method invocations and intermediate computations .

The JVM architecture enables execution on different hardware platforms by acting as an intermediate layer between Java programs and the physical hardware. This architecture utilizes a class file format that is platform-independent, allowing the same .class files to be executed on any device with a JVM. The abstract nature of the JVM ensures portability because it provides a uniform instruction set interpreted or compiled just-in-time by the JVM on each specific platform. Additionally, the JVM uses run-time data areas and operations such as dynamic linking and garbage collection to manage memory and execution in a way that abstracts from the underlying hardware differences .

You might also like