Vous êtes sur la page 1sur 16

GE - Transport

DPLH

Knowing Java Run Environment

Version 1.1/05 Jan ,2006

Vishal Kakapuri

MindTree Consulting Private Limited,


#42, 27th Cross, Banashankari II Stage
Bangalore - 560 070
www.mindtree.com

1
Table of Contents

1. INTRODUCTION.........................................................................................................................................2
1.1 PURPOSE OF THE DOCUMENT.............................................................................................................................3
1.2 REFERENCES AND PRIOR READINGS...................................................................................................................3
2. REVISION HISTORY...................................................................................................................................3
12.3.1 Verification of the Binary Representation.........................................................................................9
12.3.3 Resolution of Symbolic References.................................................................................................10

1. Introduction
This writing is based upon the thoughts that were discussed at a session presented
by me, in one of the GETG Group sessions at MindTree –West Campus.

2
1.1 Purpose of the document
This paper presents an overview of the Java run time environment.

1.2 References and Prior Readings

SL# Reference / Prior Reading Location of Availability

1. Java sun site http://java.sun.com/docs/books/


2.
3.

2. Revision history

Version Date Author(s) Reviewer(s) Change Description

1.0 12-06-2005 Vishal Base Version


Kakapuri
1.1 08-01-2006 Vishal Sharanbasav Modified the document format
Kakapuri

3 TOPICS COVERED

3
1) LOOKING AT THE JAVA ENVIRONMENT……………………………………………………. 5
2) EXECUTING YOUR CODE. ……………………………………………………. 6
3) DEFINING JAVA VIRTUAL MACHINE …………………………………………………….15
4) VIRTUAL MACHINE PARTS …………………………………………………….16

Looking at the Java Environment.

The first thought that occurs in my mind, to include in this discussion is,”what
does a java environment actually consist of?” Well it may not be a difficult thing to
be thought about – but would say that java environment primarily consists of
4
Compile time environment.
Run time environment.

In java whatever code you write – passes through two stages/phases – as said
above one is the compile time and the second is the run time environment, before
you actually see the results of your code in front of you.

The compile time starts and ends with the execution of the java’s “javac”
command on a java program something like this “javac program_name.java”. This
command actually invokes the java compiler and converts your text format of the
java code/program to some intermediate format called byte-code. This byte-code
is acceptable by all the Java runtime environments – for this reason the java is
assumed to be a portable language. Yes, this being also true, that each operating
system environment needs to have its own run-time environment specific to it. The
new file that is generated by the java compile time environment has the extension
“. class” added to it instead of the source’s “.java”. So the new file that is generated
is “program_name.class”.

What happens to the byte-code that you obtained during the compile time
procedure? Well it goes through the second stage of execution through the virtual
interpreter that interprets this byte-code and provides you with the results. This
virtual interpreter that provides you with the execution environment is known as
Java Virtual Machine (also known shortly as JVM). We will delve into some of the
details of the Java Virtual Machine, in this discussion, later. One thing that I would
like to tell here is how we actually invoke the JVM. That is simple too. – It happens
through the java’s “java” command which is actually an exe file written through
some native code that interacts with the operating system and helps you runs your
code.

Java language is considered secure – since you cannot interact with the memory or
operating system directly through any java program. It does not mean that there is
no scope for it. Yes there is a scope for it. It happens through Java Native coding.
Java includes a JNI (Java Interface API) though which you can write a C function,
call it and run it. And through that C-code you can do any low level operations –I
mean operations at the OS level (handle memory structures, perform scheduling
etc.). I think this should be sufficient for JNI definition – keeping the intricacies
away (not being in the scope of the current discussion).

Executing your code

Well another question that strikes my mind is-“How is your code executed by the
JVM?” Putting the reply in some simple terms – I may say that it happens in two
steps: -
5
 Your class is loaded first by your JVM.
 Your loaded class is executed by your JVM.

But the truth is that this is not as simple as it seems. Run your java program like
this: “java –verbose program_name.java” and you will have a fair idea of how
much it takes to actually provide you with the results - you are happy with!

BYTE-CODE
(.CLASS file)
BYTE-CODE COMPILER

CLASS
LOADED

JVM

LOADED
CLASS
ACTUALLY
EXECUTED

Results
Fig: - Java code execution.

Now next let us try having an insight of what it means to loading a class and how
does it work for us.

Loading a class is a primary function of the JVM which it does though some Class
Loader (CL) programs. It refers to the process of finding the binary format of a
class with a particular name.

The following transcript (in the grayed box below) explains something regarding
the same. It has been taken from the O’reilly On Java dot com site and the article
‘Inside Class Loaders’ is provided by Andreas Schaefer.

6
The class loaders work like the federal bank of each country, issuing their own
currency. The border of each country defines the visibility and usability of the
currency and makes it possible to have multiple currencies in the world.

Class loaders and their usage follow a few simple rules:

• Class loaders are hierarchically organized, where each one has a parent
class loader, except the bootstrap class loader (the root).
• Class loaders should (practically: must) delegate the loading of a class to
the parent, but a custom class loader can define for itself when it should
do so.
• A class is defined by its class type and the effective class loader.
• A class is only loaded once and then cached in the class loader to ensure
that the byte code cannot change.
• Any symbolic links are loaded by the effective class loader (or one of its
ancestors), if this is not already done. The JVM can defer this resolution
until the class is actually used.
• An upcast of an instance to another class fails when the class of the
instance and the class of the symbolic link do not match (meaning their
class loaders do not match).

So far as the Class Loading organization is considered – they are classified as


Bootstrap CL, System CL, and Custom built CLs’ if any (I mean that you can write
your own class loaders for example several web/application servers use their own
custom class loaders to handle the class loading and their execution in a web
application environment).

Bootstrap CL

System CLs

Customer CLs
Fig: - Class Loader Organization

Here as soon as you hit the java command the JVM is initiated. Which in turn calls
in the Bootstrap class loader to load the classes into the JVM as well as extensions
to the JVM? The Bootstrap class loader calls in the System Class loader.

7
The System class loader will load the classes provided by the CLASSPATH
environment or passed to the java command as an value to its ‘-classpath’
option. The tasks in the above figure are always performed in a bottom to top
approach. For example to load a class, the bootstrap Loader will delegate the task
to the system class loader to load the JDK ClassLoader class which in turn trys to
call in any Custom ClassLoader written or other wise loads the main class in your
application.

While doing all this there is something more explained by the Java Sun
Specification (The below transcripts identified as gray boxes have been taken from
Java language specification http://java.sun.com/docs/books/jls -
/second_edition/html/execution.doc.html) regarding the execution of a class and
which I would like to include here for some understanding of a ClassLoader
behavior and execute your class. It explains the steps, which a JVM performs to
actually execute your code – namely Loading, Linking, creating class instances and
finalization etc.

A java virtual machine starts its execution by calling in the main method of your
class.

Loading: - The loading process is implemented by the class ClassLoader and its subclasses.
Different subclasses of ClassLoader may implement different loading policies. In particular, a
class loader may cache binary representations of classes and interfaces; prefetch them based on
expected usage, or load a group of related classes together. These activities may not be
completely transparent to a running application if, for example, a newly compiled version of a
class is not found because an older version is cached by a class loader. It is the responsibility of
a class loader, however, to reflect loading errors only at points in the program they could have
arisen without prefetching or group loading.

If an error occurs during class loading, then an instance of one of the following subclasses of
class LinkageError will be thrown at any point in the program that (directly or indirectly) uses
the type:

• ClassCircularityError: A class or interface could not be loaded because it would be its


own superclass or superinterface
• ClassFormatError: The binary data that purports to specify a requested compiled class or
interface is malformed.
• NoClassDefFoundError: No definition for a requested class or interface could be found
by the relevant class loader.

Because loading involves the allocation of new data structures, it may fail with an
OutOfMemoryError.

8
Linking: - Linking is the process of taking a binary form of a class or interface type and
combining it into the runtime state of the Java virtual machine, so that it can be executed. A
class or interface type is always loaded before it is linked.

Three different activities are involved in linking: verification, preparation, and resolution of
symbolic references.The precise semantics of linking are given in chapter 5 of The Java Virtual
Machine Specification, Second Edition. Here we present an overview of the process from the
viewpoint of the Java programming language.

This specification allows an implementation flexibility as to when linking activities (and,


because of recursion, loading) take place, provided that the semantics of the language are
respected, that a class or interface is completely verified and prepared before it is initialized,
and that errors detected during linkage are thrown at a point in the program where some
action is taken by the program that might require linkage to the class or interface involved in
the error.

For example, an implementation may choose to resolve each symbolic reference in a class or
interface individually, only when it is used (lazy or late resolution), or to resolve them all at
once while the class is being verified (static resolution). This means that the resolution process
may continue, in some implementations, after a class or interface has been initialized.

Because linking involves the allocation of new data structures, it may fail with an
OutOfMemoryError.

12.3.1 Verification of the Binary Representation

Verification ensures that the binary representation of a class or interface is structurally correct.
For example, it checks that every instruction has a valid operation code; that every branch
instruction branches to the start of some other instruction, rather than into the middle of an
instruction; that every method is provided with a structurally correct signature; and that every
instruction obeys the type discipline of the Java virtual machine language.

For the specification of the verification process, see the separate volume of this series, The Java
Virtual Machine Specification, Second Edition.

If an error occurs during verification, then an instance of the following subclass of class
LinkageError will be thrown at the point in the program that caused the class to be verified:

• VerifyError: The binary definition for a class or interface failed to pass a set of required
checks to verify that it obeys the semantics of the Java virtual machine language and that
it cannot violate the integrity of the Java virtual machine. 12.3.2 Preparation of a Class or
Interface Type

Preparation involves creating the static fields (class variables and constants) for a class or
9
interface and initializing such fields to the default values. This does not require the execution of
any source code; explicit initializers for static fields are executed as part of initialization, not
preparation.

Implementations of the Java virtual machine may precompute additional data structures at
preparation time in order to make later operations on a class or interface more efficient. One
particularly useful data structure is a "method table" or other data structure that allows any
method to be invoked on instances of a class without requiring a search of super classes at
invocation time.

12.3.3 Resolution of Symbolic References

The binary representation of a class or interface references other classes and interfaces and their
fields, methods, and constructors symbolically, using the binary names of the other classes and
interfaces. For fields and methods, these symbolic references include the name of the class or
interface type that declares the field or method as well as the name of the field or method itself,
together with appropriate type information.

Before a symbolic reference can be used it must undergo resolution, wherein a symbolic
reference is checked to be correct and, typically, replaced with a direct reference that can be
more efficiently processed if the reference is used repeatedly.

If an error occurs during resolution, then an error will be thrown. Most typically, this will be an
instance of one of the following subclasses of the class IncompatibleClassChangeError, but it
may also be an instance of some other subclass of IncompatibleClassChangeError or even an
instance of the class IncompatibleClassChangeError itself. This error may be thrown at any
point in the program that uses a symbolic reference to the type, directly or indirectly:

• IllegalAccessError: A symbolic reference has been encountered that specifies a use or


assignment of a field, or invocation of a method, or creation of an instance of a class, to
which the code containing the reference does not have access because the field or
method was declared private, protected, or default access (not public), or because the
class was not declared public.

This can occur, for example, if a field that is originally declared public is changed to be private
after another class that refers to the field has been compiled.

• InstantiationError: A symbolic reference has been encountered that is used in a class


instance creation expression, but an instance cannot be created because the reference
turns out to refer to an interface or to an abstract class.

This can occur, for example, if a class that is originally not abstract is changed to be abstract
after another class that refers to the class in question has been compiled

• NoSuchFieldError: A symbolic reference has been encountered that refers to a specific

10
field of a specific class or interface, but the class or interface does not contain a field of
that name.

This can occur, for example, if a field declaration was deleted from a class after another class
that refers to the field was compiled.

• NoSuchMethodError: A symbolic reference has been encountered that refers to a specific


method of a specific class or interface, but the class or interface does not contain a
method of that signature.

This can occur, for example, if a method declaration was deleted from a class after another class
that refers to the method was compiled

Additionally, an UnsatisfiedLinkError (a subclass of LinkageError) may be thrown if a class


declares a native method for which no implementation can be found. The error will occur if the
method is used, or earlier, depending on what kind of resolution strategy is being used by the
virtual machine.

For more you may refer to: -

http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html

Further steps that follow the Loading and linking involve initialization and
creation of new class instances and finalization process.

11
Initialization of a class consists of executing its static initializers and the initializers for
static fields declared in the class. Initialization of an interface consists of executing the
initializers for fields declared in the interface.

Before a class is initialized, its direct superclass must be initialized, but interfaces
implemented by the class need not be initialized. Similarly, the superinterfaces of an
interface need not be initialized before the interface is initialized.

A class or interface type T will be initialized immediately before the first occurrence of
any one of the following:

• T is a class and an instance of T is created.


• T is a class and a static method declared by T is invoked.
• A static field declared by T is assigned.
• A static field declared by T is used and the reference to the field is not a compile-
time constant. References to compile-time constants must be resolved at compile
time to a copy of the compile-time constant value, so uses of such a field never
cause initialization

A new class instance is explicitly created when evaluation of a class instance creation
expression causes a class to be instantiated.

A new class instance may be implicitly created in the following situations:

• Loading of a class or interface that contains a String literal may create a new
String object to represent that literal. (This might not occur if the same String
has previously been interned.)
• Execution of a string concatenation operator that is not part of a constant
expression sometimes creates a new String object to represent the result. String
concatenation operators may also create temporary wrapper objects for a value
of a primitive type.

Finalization: - The class Object has a protected method called finalize; this method
can be overridden by other classes. The particular definition of finalize that can be
invoked for an object is called the finalizer of that object. Before the storage for an
object is reclaimed by the garbage collector, the Java virtual machine will invoke the
finalizer of that object.

Finalizers provide a chance to free up resources that cannot be freed automatically by an


automatic storage manager. In such situations, simply reclaiming the memory used by an
object would not guarantee that the resources it held would be reclaimed.

The Java programming language does not specify how soon a finalizer will be invoked,
except to say that it will happen before the storage for the object is reused. Also, the
language does not specify which thread will invoke the finalizer for any given object. It
is guaranteed, however, that the thread that invokes the finalizer will not be holding any
user-visible synchronization locks when the finalizer is invoked. If an uncaught

12
exception is thrown during the finalization, the exception is ignored and finalization of
that object terminates.

The finalize method declared in class Object takes no action.

The fact that class Object declares a finalize method means that the finalize
method for any class can always invoke the finalize method for its superclass, which
is usually good practice. (Unlike constructors, finalizers do not automatically invoke the
finalizer for the superclass; such an invocation must be coded explicitly.)

For efficiency, an implementation may keep track of classes that do not override the
finalize method of class Object, or override it in a trivial way, such as:

protected void finalize() throws Throwable {


super.finalize();
}
We encourage implementations to treat such objects as having a finalizer that is not
overridden, and to finalize them more efficiently.

A finalizer may be invoked explicitly, just like any other method.

The package java.lang.ref describes weak references, which interact with garbage
collection and finalization. As with any API that has special interactions with the
language, implementers must be cognizant of any requirements imposed by the
java.lang.ref API. This specification does not discuss weak references in any way.
Readers are referred to the API documentation for details.

Next comes the Class unloading process which is explained by the specification
something like:

13
An implementation of the Java programming language may unload classes. A
class or interface may be unloaded if and only if its defining class loader may be
reclaimed by the garbage collector. Classes and interfaces loaded by the
bootstrap loader may not be unloaded.

Here is the rationale for the rule given in the previous paragraph:

Class unloading is an optimization that helps reduce memory use. Obviously,


the semantics of a program should not depend on whether and how a system
chooses to implement an optimization such as class unloading. To do otherwise
would compromise the portability of programs. Consequently, whether a class
or interface has been unloaded or not should be transparent to a program.

Finally happens the program exit: - The java specification says:

A program terminates all its activity and exits when one of two things happens:

• All the threads that are not daemon threads terminate.


• Some thread invokes the exit method of class Runtime or class System and the
exit operation is not forbidden by the security manager.

The above what I tried to included or describe is to give a person a general


understanding of what is meant by execution of your class from a java point.

A more detailed knowledge of it can be obtained from: -


http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html

14
Defining Java Virtual Machine

We are always curious about something, which we cannot see. Something like
when your nose senses something being cooked delicious – you are curious to see
what it is? I believe curiosity leads us to discover the hidden.

A case similar is for a Java Developer when he runs a java program and wants to
know what made it run. It cannot be so simple – that issuing a command like java
<program_name> does everything. You get the results in seconds – but if you run a
program with a ‘–verbose’ you will know that how much effort is required to
actually provide you with the results.

A java program cannot run on its own – it needs support and environment. The
Java Class Loading Architecture (Java API’s) provides the support and the Java
Virtual Machine (JVM) provides the environment. Taken together (Java API’s and
JVM) it form the Java Platform.

JAVA API’s + JVM

JAVA PLATFORM

Fig: - Java Platform.

A JVM is a piece of software that is responsible for running Java programs. A new
JVM is started whenever you type in java program_name on the command line.
And similarly each web application you start in a web based environment runs in
its own JVM. It is called a virtual machine since it is software that emulates a
physical computer. Java programs are built to be run on this virtual machine,
allowing them to be run on any real machine that has a JVM.

In simple terms, Java Class Loading Architecture (this term will be referred here
onwards as JCLA for simplicity) provides the required energy to the Java Virtual
Machine (JVM) – which in turn provides the required space, so that your code can
be converted to an OS understandable/interact-able format and you can have the
results or output. After all, OS is everything in every computing environment.
JVM for this reason is also known as ‘abstract computer’ that handles all the
activities – for your program execution. A program runs inside your JVM over an
OS. Each OS type has a JVM specific to it. Means that UNIX based system JVM is
different than a Windows based system.

15
Virtual Machine Parts

The "virtual hardware" of the Java Virtual Machine can be divided into four
basic parts: the registers, the stack, the garbage-collected heap, and the method
area. These parts are abstract, just like the machine they compose, but they must
exist in some form in every JVM implementation.

The size of an address in the JVM is 32 bits. The JVM can, therefore, address up
to 4 gigabytes (2 to the power of 32) of memory, with each memory location
containing one byte. Each register in the JVM stores one 32-bit address. The
stack, the garbage-collected heap, and the method area reside somewhere
within the 4 gigabytes of addressable memory. The exact location of these
memory areas is a decision of the implementer of each particular JVM.

A word in the Java Virtual Machine is 32 bits. The JVM has a small number of
primitive data types: byte (8 bits), short (16 bits), int (32 bits), long (64 bits), float
(32 bits), double (64 bits), and char (16 bits). With the exception of char, which is
an unsigned Unicode character, all the numeric types are signed. These types
conveniently map to the types available to the Java programmer. One other
primitive type is the object handle, which is a 32-bit address that refers to an
object on the heap.

The method area, because it contains byte-codes, is aligned on byte boundaries.


The stack and garbage-collected heap are aligned on word (32-bit) boundaries.

The above excerpt has been taken from: -


http://www.javaworld.com/javaworld/jw-06-1996/jw-06-vm.html?

There is a lot more that we can dwell into while learning about the JVMs
you use.

You can learn more from http://java.sun.com

16

Vous aimerez peut-être aussi