24 Introduction to Virtual Machine and API Programming

24.1 INTRODUCTION

The programming API is an API that let users to write scripts and programs to manipulate virtual machines. It is a high-level interface which is easy to use and practical for both script developers and application programmers.

The Java platform has two main parts, the Java virtual machine and the Java API, as shown in Figure 24.1.

1.   Java virtual machine
The Java virtual machine is a 'soft' computer that can be implemented in software or hardware. It is an abstract machine designed to be implemented on top of existing processors. The porting interface and adapters enable it to be easily ported to new operating system without being completely rewritten.

2.   Java API
The Java API forms a standard interface to applets and applications, regardless of the underlying operating system. The Java API is the essential framework for application development. This API specifies a set of essential interfaces in a growing number of key areas that developers will use to build their Java-powered applications.

images The Java base API : It provides the very basic language, utility, I/O, network, GUI and applet services; OS companies that have licensed Java have contracted to include them in any Java platform they deploy.

images

Figure 24.1 The Java base platform is uniform across all operating systems

images The Java standard extension API : It extends the capabilities of Java beyond the Java base API. Some of these extensions will eventually migrate to the Java base API. Other non-standard extension APIs can be provided by the applet, application or underlying operating system. As each new extension API specification is published, it will be made available for industry review and feedback before it is finalized.

In Figure 24.1, the Java base platform is the part shown in black, including the blocks labelled Adapter (platform dependent). The Java API includes both the Java base API and Java standard extension API. The classes are the implementation of that API. The Java virtual machine is at the core of the platform. The porting interface lies between the Java virtual machine and the operating system (OS) or browser. This porting interface has a platform independent part as shown in black and a platform dependent part shown as adapters. The OS and JavaOS provide the window, filling and network functionality. Different machines can now be connected by a network.

The Java API framework is open and extensible. The API is organized by groups or sets. Each of the API sets can be implemented as one or more packages which are called as namespaces. Each package groups together a set of classes and interfaces that define a set of related fields constructors and methods.

24.2 VIRTUAL MACHINE

The Java virtual machine is key to the independence of the underlying operating system and hardware; it is a platform that hides the underlying operating system from Java-powered applets and applications. And it is very easy to port the virtual machine to a browser or another operating system.

In addition, the virtual machine defines a machine independent format for binary files which is called as '.class' file format. This format includes instructions for a virtual computer in the form of bytecodes. The bytecode representation of any Java language program is symbolic in that it offsets and indexes into methods that are not constants, but are instead given symbolically as string names. The first time a method is called, it is searched by name in the class file format, and its offset numeric value is determined at that time for quicker access at subsequent lookups. Therefore, any new or overriding method can be introduced late at runtime anywhere in the class structure and it will be referred to symbolically, and properly accessed without breaking the code.

/* PROG 24.1 SUM OF TWO NUMBERS (DEMO OF VIRTUAL MACHINE)*/
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
/*
   <applet code = "button4" width = 280 height = 140>
   </applet>
   */
public class JPS2 extends Applet implements ActionListener
{
      Button but1;String result=" ";
      boolean in=false;
      int num1, num2;
      TextField tf1, tf2;
      Label L1, L2;
      public void init()
      {
             setBackground(Color.blue);
             L1=new Label("Enter first number:");
             add(L1);
             tf1=new TextField(10);
             add(tf1);
             L2=new Label("Enter second number:");
             add(L2);
             tf2=new TextField(10);
             add(tf2);
             but1=new Button("Click for maximum of two no.");
             add(but1);
             but1.addActionListener(this);
      }
      public void actionPerformed(ActionEvent AE)
      {
             try
             {
                      num1=Integer.parseInt(tf1.getText());
                      num2=Integer.parseInt(tf2.getText());
                      int ans = num1 > num2 ? num1 : num2;
                      result=result.valueOf(ans);
                      result=("Sum of two number:="+result);
             }
             catch(Exception E)
             {
                      result="Error";
             }
             repaint();
      }
      public void paint(Graphics g)
      {
             g.setColor(Color.blue);
             g.drawString(result,120,120);
      }
}

Now, on the basis of the example given in the above Java application program named JPS2.java, the working of Java virtual machine will be traced. The Java virtual machine (simple virtual machine) can be categorized into five fundamental pieces as shown in figure 24.2.

images

Figure 24.2 Five fundamental pieces for Java virtual machine

Some of these pieces might be implemented by using an interpreter 'java' or native binary code compiler—Java native interface (JNI) or by a hardware chip.

The remarkable point here is that the memory areas required by the Java virtual machine are not just required at any particular place in the memory (primary or secondary), or to be in any fixed order. However, all but the method area must be able to represent align 32-bit values (Java stack is 32-bit wide).

Now, the pieces of Java virtual machine can be shown in Figure 24.2.

Java Bytecodes

To get the bytecode for any application implemented in Java, the Java application will first be compiled using 'javac'. For getting the concept of byte code compile the above file (JPS2.java) using javac.

After compiling the Java program using 'javac' the '.class' file format is obtained which contains the bytecodes which makes the program platform independent. To see the bytecodes the javap will be used with option '–c'.

javap - c filename>filename.bc

Note: Here extension .bc is used for bytecode.

images

Figure 24.3 javap used to get bytecode for JPS2.java

A Java virtual machine starts execution by invoking the method main of some specified class, passing it a single argument, which is an array of strings (public static void main(String args[])). This causes the specified class to be loaded, linked to other types that it uses and initialized. The method main must be declared public, static, and void. Below the file 'JPS2.class' is given that contains the bytescode as given below:

/*FILE:"JPS2.BC" CONTAINS BYTECODE FOR THE FILE "JPS2.CLASS" */
Compiled from "JPS2.java"
public class JPS2 extends java.applet.Applet implements
 java.awt.event.ActionListener{
java.awt.Button but1;
java.lang.String result;
boolean in;
int num1;
int num2;
java.awt.TextField tf1;
java.awt.TextField tf2;
java.awt.Label L1;
java.awt.Label L2;
public JPS2();
      Code:
       0: aload_0
       1: invokespecial    #1; //Method java/applet/
                                         Applet."<init>":()V
       4: aload_0
       5: ldc    #2; //String
       7: putfield   #3; //Field result:Ljava/lang/String;
       10:      aload_0
       11:      iconst_0
       12:      putfield    #4; //Field in:Z
       15:      return
public void init();
      Code:
       0: aload_0
       1: getstatic    #5; //Field java/awt/Color.blue:Ljava/
                                 awt/Color;
       4: invokevirtual    #6; //Method setBackground:(Ljava/
                                         awt/Color;)V
       7: aload_0
       8: new    #7; //class java/awt/Label
       11:     dup
       12:     ldc    #8; //String Enter first number:
       14:     invokespecial    #9; //Method java/
                 awt/Label."<init>":(Ljava/lang/String;)V
       17:     putfield    #10; //Field L1:Ljava/awt/Label;
       20:     aload_0
       21:     aload_0
       22:     getfield    #10; //Field L1:Ljava/awt/Label;
       25:     invokevirtual    #11; //Method add:(Ljava/
                 awt/Component;)Ljava/awt/Component;
       28:     pop
       29:     aload_0
       30:     new    #12; //class java/awt/TextField
       33:     dup
       34:     bipush 10
       36:     invokespecial    #13; //Method java/
                 awt/TextField."<init>":(I)V
       39:     putfield    #14; //Field tf1: Ljava/awt/
                                         TextField;
       42:     aload_0
       43:     aload_0
       44:     getfield    #14; //Field tf1:Ljava/awt/
                                  TextField;
       47:     invokevirtual    #11; //Method add:(Ljava/
                 awt/Component;)Ljava/awt/Component;
       50:     pop
       51:     aload_0
       52:     new    #7; //class java/awt/Label
       55:     dup
       56:     ldc    #15; //String Enter second number:
       58:     invokespecial    #9; //Method java
                 /awt/Label."<init>":(Ljava/lang/String;)V
       61:     putfield    #16; //Field L2:Ljava/awt/Label;
       64:     aload_0
       65:     aload_0
       66:     getfield    #16; //Field L2:Ljava/awt/Label;
       69:     invokevirtual    #11; //Method add:(Ljava
                   /awt/Component;)Ljava/awt/Component;
       72:     pop
       73:     aload_0
       74:     new    #12; //class java/awt/TextField
       77:     dup
       78:     bipush 10
       80:     invokespecial    #13; //Method java
                    /awt/TextField."<init>":(I)V
       83:     putfield    #17; //Field tf2:Ljava/awt/
                TextField;
       86:     aload_0
       87:     aload_0
       88:     getfield    #17; //Field tf2:Ljava/awt/
                TextField;
       91:     invokevirtual    #11; //Method add:(Ljava
                    /awt/Component;)Ljava/awt/Component;
       94:     pop
       95:     aload_0
       96:     new    #18; //class java/awt/Button
       99:     dup
       100:    ldc    #19; //String Click for maximum of two
                  no.
       102:    invokespecial    #20; //Method java
                /awt/Button."<init>":(Ljava/lang/String;)V
       105:    putfield    #21; //Field but1:Ljava/awt/
                                    Button;
       108:    aload_0
       109:    aload_0
       110:    getfield    #21; //Field but1:Ljava/awt/
                                         Button;
       113:    invokevirtual    #11; //Method add:(Ljava
                /awt/Component;)Ljava/awt/Component;
       116:    pop
       117:    aload_0
       118:    getfield    #21; //Field but1:Ljava/awt/
                                   Button;
       121:    aload_0
       122:    invokevirtual    #22; //Method java/awt
                 /Button.addActionListener:(Ljava/awt/event/
                ActionListener;)V
       125:     return
public void actionPerformed(java.awt.event.ActionEvent);
      Code:
       0: aload_0
       1: aload_0
       2: getfield    #14; //Field tf1:Ljava/awt/TextField;
       5: invokevirtual    #23; //Method java
             /awt/TextField.getText:()Ljava/lang/String;
       8: invokestatic    #24; //Method java/lang
             /Integer.parseInt:(Ljava/lang/String;)I
       11:   putfield    #25;      //Field num1: I
       14:   aload_0
       15:   aload_0
       16:   getfield    #17;      //Field tf2:Ljava/awt/
               TextField;
       19:   invokevirtual    #23; //Method java
               /awt/TextField.getText:()Ljava/lang/String;
       22:   invokestatic    #24; //Method java
               /lang/Integer.parseInt:(Ljava/lang/String;)I
       25:   putfield    #26; //Field num2:I
       28:   aload_0
       29:   getfield    #25; //Field num1:I
       32:   aload_0
       33:   getfield    #26; //Field num2:I
       36:   if_icmple 46
       39:   aload_0
       40:   getfield    #25; //Field num1:I
       43:   goto 50
       46:   aload_0
       47:   getfield    #26; //Field num2:I
       50:   istore_2
       51:   aload_0
       52:   aload_0
       53:   getfield    #3; //Field result:Ljava/lang/
                String;
       56:   pop
       57:   iload_2
       58:   invokestatic    #27; //Method java
               /lang/String.valueOf:(I)Ljava/lang/String;
       61:   putfield    #3; //Field result:Ljava/lang/
                                        String;
       64:   aload_0
       65:   new    #28; //class java/lang/StringBuilder
       68:   dup
       69:   invokespecial    #29; //Method java
               /lang/StringBuilder."<init>":()V
       72:   ldc    #30; //String Sum of two number:=
       74:   invokevirtual    #31; //Method java/lang/
             StringBuilder.append:(Ljava/lang/String;)
             Ljava/lang/StringBuilder;
       77:   aload_0
       78:   getfield    #3; //Field result:Ljava/lang/
                                String;
       81:   invokevirtual    #31; //Method java/lang/
               StringBuilder.append:(Ljava/lang/String;)
               Ljava/lang/StringBuilder;
       84:   invokevirtual    #32; //Method java/lang/
              StringBuilder.toString:()Ljava/lang/String;
       87:   putfield    #3; //Field result:Ljava/lang/
                                String;
       90:   goto 100
       93:   astore_2
       94:   aload_0
       95:   ldc    #34; //String Error
       97:   putfield    #3; //Field result:Ljava/lang/
                                String;
       100:  aload_0
       101:  invokevirtual    #35; //Method repaint:()V
       104:  return
Exception table: from to target type
       0  90  93  Class java/lang/Exception
public void paint(java.awt.Graphics);
      Code:
       0: aload_1
       1: getstatic    #5; //Field java/awt/Color.
                            blue:Ljava/awt/   Color;
       4: invokevirtual    #36; //Method java/
            awt/Graphics.setColor:(Ljava/awt/Color;)V
       7: aload_1
       8: aload_0
       9: getfield    #3; //Field result: Ljava/lang/String;
       12:   bipush      120
       14:   bipush      120
       16:   invokevirtual    #37; //Method java/
               awt/Graphics.drawString:(Ljava/lang/String;II)
V
       19:   return
}

The bytecodes are a high-level representation of the program so that optimization and machine code generation (via a just-in-time compiler ) can be performed at that level. In addition, garbage collection can occur inside the virtual machine, since it holds variables in stacks in the Java platform address space.

A bytecode instruction consists of a one-byte opcode that serves to identify the instruction involved and zero or more operands, each of which may be more than one byte long, that encodes the parameters the opcode requires.

Set of Registers

For the execution of the byte code, Java virtual machine use a set registers which is very similar to the registers given inside a real computer system. Java virtual machine use registers for performing three major tasks: keeping the machine's state, affecting the operation of virtual machine and updating after each bytes-code is executed.

There are mainly four types of registers given for Java virtual machine. These registers are basically 32-bit wide.

images

Figure 24.4 Set of register for Java virtual machine

Since Java virtual machine is completely stack based, it does not use any registers (pc, optop, frame and vars) for passing or receiving any type of arguments.

The Stack

Stack plays an important role in the working of Java virtual machine. A Java stack frame is very similar to the stack frame used for a conventional programming language-it holds the state for a single method call. The role of stack in Java virtual machine is to supply parameters to bytecodes and methods, and to receive result back from them.

To understand what has been given for the stack, the above example can be considered once again. In the program JPS2.java method public void paint(Graphics g) is given. This method accepts object of Graphics class.

public void paint(Graphics g)
{
   g.setColor(Color.blue);
   g.drawString(result,120,120);
}

The byte code for the above method is:

public void paint(java.awt.Graphics);
   Code:
     0: aload_1
     1: getstatic  #5; //Field java/awt/Color.blue:Ljava/awt/
                            Color;
     4: invokevirtual  #36; //Method java/awt/Graphics.
                                 setColor:(Ljava/awt/Color;)V
     7: aload_1
     8: aload_0
     9: getfield  #3; //Field result: Ljava/lang/String;
     12:      bipush   120
     14:      bipush   120
     16:      invokevirtual  #37; //Method java/
                awt/Graphics.drawString:(Ljava/lang/String;II)V
     19:      return
   }

Explanation: In the bytecode given above for paint method, aload_1 loads object reference from the local variable. Local variable in the current Java frame must contain a return address or reference to an object (Object g of class Graphics). Line-2 shows a getstatic field from class. The general form for getstatic is:

     getstatic ... . . , =>..., value-word1, value-word2

It is used to construct an index into the constant pool of the current class and the constant pool item will be a field reference to a static field of a class.

     1: getstatic #5; // Field java/awt/Color.blue:Ljava/awt/Color;

In the above getstatic field construct an index into the constant pool for the Color class. The constant pool item with nothing but the Color.blue will be a field reference to a static field of a class Color. The value of that field (Color.blue) is placed on the top of the stack. The first stack picture is for 32-bit wide and the second will be for 64-bit. The noticeable point here is if the specified field is not a static field, an IncompatibleClassChangeError is thrown by the system.

Now, the next line of the bytecode is for invokevirtual, which is used to invoke an instance method based on runtime type. The general code for invokevirtual is:

    invokevirtual ......, handle, [arg1][arg2... .]......=>......

In the program JPS2.java, invokevirtual has been used to invoke the instance method for paint method.

    4:     invokevirtual     #36; //Method     java/awt/Graphics.setColor:(Ljava/
                                  awt/Color;)V

The operand stack must maintain a reference/handle to an object (object g for Graphics class) and some number of arguments. It use an index into the constant pool of the current class. Item at some particular index in the constant pool contains the complete method signature. The reason why the constant pool contains the method signature is that, ivokevirtual manages a pointer to the object which has been used to invoke the method table is to be retrieved from the object reference. The method signature is then verified from the method table. Method signature is guaranteed to get an exact match for one of the method signatures in the table. If value of handle is null, it throws a NullPointerException . And if during method invocation a stack overflow is found, a StackOverflowError is thrown. The role of getfield is to fetch field from object. There is a handle which must be a reference to an object. bipush pushes one byte signed integer, as shown in the above bytecode at line-12 and line-14.

    12:  bipush    120
    14:  bipush    120

The value then expanded to an int and pushed onto the operand stack. The method return has used to return from the method. That is after getting return Java interpreter returns control to its caller. The value is pushed onto the operand stack of the previous execution environment.

The Garbage Collected Heap

The technique through which a program can obtain space in the RAM during the execution of the program and not during compilation is called dynamic memory allocation. In this method, space for the variables (array, strings, etc.) is allocated from a free memory region which is known as heap. This area is not fixed in nature and keeps changing as the memory is allocated and de-allocated from this region. The entire runtime view of memory for a program is shown in Figure 24.5.

The heap is often assigned a large, fixed sized when the Java runtime system is started, but on systems that support virtual memory, it can grow according to the requirement, in an unbounded manner. Since it is well known that Java supports the concepts of garbage collection to collect the object automatically there is no need de-allocate the memory manually from programmers side.

images

Figure 24.5 Runtime memory area of a Java application program

Area for Storing Methods

Java virtual machine supports basically two different areas for storing purposes. The first one is called as Method area and second Constant pool.

images

Figure 24.6 Area used for storing by Java Virtual Machine

images Method area: It is very similar to the compiled code area of conventional programming language environment. It keeps the bytecodes used to implement almost all the methods used for Java application development by Java system.

images Constant pool: Constant pool is basically given for classes used in the Java system. Since, it is well known that heap is a part of memory from which newly created instance are allocated, each class in the heap has a constant pool attached to it. Constant pool is usually created by javac at the compile time. These constants encode all the names like variables and methods used by any method in a class.

24.3 VIRTUAL MACHINE ERRORS

When any Java program is compiled and interpreted, most of the time problem is faced in loading, linking and initialization of the program ('.bc' or '.class') with virtual machine. A Java virtual machine throws an object that is an instance of a subclass of the class VirtualMachineError when an internal error or resource limitation prevents it from implementing the semantics of the Java language. The Java virtual machine specification cannot predict where resource limitations or internal errors may be encountered and does not mandate precisely when they can be reported. Thus, any of the virtual machine errors listed as subclasses of VirtualMachineError may be thrown at any time during the operation of the Java virtual machine.

24.4 INSTRUCTION SET FOR VIRTUAL MACHINE

Java virtual machine instructions are represented in this chapter by entries of the form shown in Table 24.1.

Operation Description
Format images
Forms mnemonic = opcode
Stack ......., value1, value2 =>
......., vlaue3
Description A longer description detailing constraints on operand stack contents or constant pool entries, the operation performed, the type of the result, and so on.
Linking Exceptions If any linking exception is thrown by the execution of this instruction, they are set off one to a line in a way that they must be thrown.
Runtime Exceptions If any runtime exceptions can be thrown by the execution of an instruction, they are set off one to a line in a way that they must be thrown. Other than the linking and runtime exceptions, if any, listed for an instruction, the instruction must not throw any runtime exceptions except for instances of VirtualMachineError or its subclasses.
Notes Comments not strictly part of the specification of an instruction are set aside as note at the end of the description.

Table 24.1 An example of instruction page

24.5 INVOKING METHODS USING VIRTUAL MACHINE

The normal method invocation for a Java instance method dispatches on the runtime type of the object (they are virtual, in C++ terms). Such an invocation is implemented using the invokevirtual instruction, which takes as its argument an index to a constant pool entry giving the fully qualified name of the class type of the object, the name of the method to invoke, and that method's descriptor. To invoke the area_rectangle method, defined as an instance method, the code can be written as shown below:

/*PROG 24.2 INVOKING METHODS DEFINED AS AN INSTANCE METHOD USING VIRTUAL MACHINE */
import java.io.*;
import java.util.*;
class JPS3
{
      public static void main(String[] args)
      {
             Scanner sc = new Scanner(System.in);
             int area_rect;
             System.out.println("
Enter a number");
             //num = sc.nextDouble();
             area_rect = area15n10();
             System.out.println("
Square of "+area_rect);
      }
      static int area150n100()
      {
             return area_rectangle(150, 100);
      }
      static int area_rectangle(int l, int w)
      {
             return (l * w);
      }
}

Now, the complete bytecode is given for the program JPS3.java.

/*FILE:"JPS3.BC" CONTAINS BYTECODE FOR THE FILE "JPS3.CLASS" */
Compiled from "JPS3.java"
class JPS3 extends java.lang.Object{
JPS3();
      Code:
       0: aload_0
       1: invokespecial   #1; //Method java/lang/
           Object."<init>":()V
       4: return
public static void main(java.lang.String[]);
      Code:
       0: new   #2; //class java/util/Scanner
       3: dup
       4: getstatic   #3; //Field java/lang/System.in:Ljava/
                                 io/InputStream;
       7: invokespecial   #4;//Method java/util/
            Scanner."<init>":(Ljava/io/InputStream;)V
       10:   astore_1
       11:   getstatic   #5; //Field
                java/lang/System.out:Ljava/io/PrintStream;
       14:   ldc      #6; //String 
Enter a number
       16:   invokevirtual   #7; //Method
              java/io/PrintStream.println:(Ljava/lang/String;)V
       19:   invokestatic    #8; //Method area15n10:()I
       22:   istore_2
       23:   getstatic   #5; //Field
                 java/lang/System.out:Ljava/io/PrintStream;
       26:   new        #9; //class java/lang/StringBuilder
       29:   dup
       30:   invokespecial       #10; //Method
              java/lang/StringBuilder."<init>":() V
       33:   ldc      #11; //String 
Square of
       35:   invokevirtual     #12; //Method java/lang/
               StringBuilder  .append:(Ljava/lang/String;)Ljava/
               lang/StringBuilder;
       38:   iload_2
       39:   invokevirtual     #13; //Method java/lang/
                StringBuilder  .append:(I)Ljava/lang/
                StringBuilder;
       42:   invokevirtual     #14; //Method java/lang/
                StringBuilder               .toString:()Ljava/lang/String;
       45:   invokevirtual     #7; //Method java/io/
                PrintStream  .println:(Ljava/lang/String;)V
       48:   return
static int area15n10();
   Code:
       0: sipush 150
       3: bipush 100
       5: invokestatic   #15; //Method area_rectangle:(II)I
       8: ireturn
static int area_rectangle(int, int);
      Code:
       0: iload_0
       1: iload_1
       2: imul
       3: ireturn
}

Explanation: To know the method invocation, the detail of bytecode is first looked into for the method which is shown below:

   static int area150n100();
      Code:
           0: sipush 150
           3: bipush 100
           5: invokestatic   #15; //Method area_rectangle:(II)I
           8: ireturn

sipush is given as sipush 100 pushes two byte signed integer where byte1 and byte 2 are combined into a signed 16-bit value. Later on, this value is expanded to a certain extent and pushed onto the stack. bipush is also given to push the data element but it pushes one byte signed integer. This value is expanded to an int and pushed onto the operand stack. The general signature for sipush and bipush is:

sipush        ............ ==>  ............, value
bipush        ............ ==>  ............, value

The next statement of the bytecode for the area15n10() is:

5: invokestatic #15; //Method area_rectangle:(II)I

The byte1 and byte2 are available in the operand stack. These numbers work as arguments. Both the byte1 and byte2 are used to construct and index into the constant pool of the current class. The item which is in the constant pool at a certain index keeps the signature for the method and class. The general form for the invokestatic is:

invokestatic ….. ,[a1, [a2,… .]],...... .=> ...... .

First method invocation starts by pushing the reference of the current instance onto the stack. Then the values are pushed into the stack using sipush and bipush statement. When the frame for the area_rectangle method is created the arguments passed to the method area_rectangle (150, 100) becomes the initial values of the new frame's local variables. Finally, area_rectangle is invoked using invokestatic. When area_rectangle returns the value, its int value is then pushed onto the stack. The return value is thus put in place to be immediately returned to the invoker of int area150n100().

The last statement of the bytecode for the method int area150n100() is ireturn instruction. The ireturn is used for the value to be pushed onto the stack of the previous execution environment. The general form for ireturn is given here:

ireturn ........., value => [empty]

The Java virtual machine provides distinct return instructions for many of its numeric and reference data types, as well as a return instruction for methods with no return value. The same set of return instructions is used for all varieties of method invocations. The various types of return instruction with their general form used in bytecode to return from method are listed below:

(a) ireturn (General form: ireturn …………, value => [empty])

(b) lreturn (General form: lreturn …………, value-word1, value-word2 =>[empty])

(c) freturn (General form: freturn …………, value => [empty])

(d) dreturn (General form: dreturn …………, value-word1, value-word2 => [empty])

(e) areturn (General form: areturn …………, value => [empty])

24.6 CLASS INSTANCE AND VIRTUAL MACHINE

Java virtual machine class instances are created using the Java virtual machine's new instruction. Once the class instance and its instance variables have been created, and those of the class and all of its superclasses have been initialized to their default values, an instance initialization method of the new class instance (<init>) is invoked. (Recall that at the level of the Java virtual machine, a constructor appears as a method with the special compiler-supplied name <init>. This special method is known as the instance initialization method. Multiple instance initialization methods, corresponding to multiple constructors, may exist for a given class.) For example:

/*PROG 24.3 DEMO OF CLASS INSTANCE AND VIRTUAL MACHINE VER 1*/
class demo_class_vm
{
    private int cx, cy;
    void input(int x, int y)
    {
           cx = x;
           cy = y;
    }
    void show()
    {
           System.out.println("
cx=" + cx);
           System.out.println("
cy="+ cy);
    }
}
class JPS5
{
    public static void main(String args[])
    {
           demo_class_vm d = new demo_class_vm();
           d.input(100, 200);
           d.show();
    }
}
OUTPUT:
C:JPSch24>javac JPS5.java
C:JPSch24>java JPS5
cx=100
cy=200
C:JPSch24>
/* FILE: JPS5.bc */
Compiled from "JPS5.java"
class JPS5 extends java.lang.Object{
JPS5();
   Code:
     0: aload_0
     1: invokespecial   #1; //Method java/lang/
          Object."<init>":()V
4: return
public static void main(java.lang.String[]);
   Code:
     0: new   #2; //class demo_class_vm
     3: dup
     4: invokespecial   #3; //Method demo_class_
          vm."<init>":()V
     7: astore_1
     8: aload_1
     9: bipush   100
     11:   sipush   200
     14:   invokevirtual   #4; //                  Method demo_class_
             vm.input:(II)V
     17:   aload_1
     18:   invokevirtual   #5; //                  Method demo_class_
              vm.show:()V
     21:   return
}

From the byte code given above, it can be seen that the Java class demo_class_vm starts with the new instruction which is basically created by Java virtual machine.

0: new   #2; //class demo_class_vm
3: dup
4: invokespecial   #3; // Method demo_class_vm."<init>":()V
7: astore_1
8: aload_1
9: bipush 100
11:     sipush 200
14:     invokevirtual   #4; //Method demo_class_
        vm.input:(II)V
17:     aload_1
18:     invokevirtual   #5; // Method demo_class_vm.show:()
V
21:     return
}

Class instances are passed and returned (as reference types) very much like numeric values, although type reference has its own complement of instructions:

 /* PROG 24.4 CLASS INSTANCE AND VIRTUAL MACHINE VER 2 */
class JPS7       //Class declaration JPS7
{
    int i;    // An instance variable
    JPS7 example()
    {
           JPS7 o = new JPS7();
           return silly(o);
    }
    JPS7 silly(JPS7 o)
    {
           if (o != null)
           {
                    return o;
           }
             else
           {
                    return o;
           }
     }
}

Becomes like the below given code:

 JPS7 example();
        Code:
          0:   new  #2; //class JPS7
          3:   dup
          4:   invokespecial  #3; //Method "<init>":()V
          7:   astore_1
          8:   aload_0
          9:   aload_1
          10:  invokevirtual   #4; //Method silly:(LJPS7;)
                 LJPS7;
          13:  areturn

The method given in the above program JPS7.java: silly(JPS7 o)

Method: JPS7 silly(JPS7);
     Code:
       0:   aload_1
       1:   ifnull 6
       4:   aload_1
       5:   areturn
       6:   aload_1
       7:   areturn

The fields of a class instance (instance variables) are accessed using the getfield and putfield instructions. If i is an instance variable of type int, the methods setIt and getIt are defined as:

    void setIt(int value)
      {
          i = value;
    }
    int getIt()
    {
          return i;
    }

    Method void setIt(int)

    0 aload_0
1 iload_1
2 putfield    #4 // Field Example.i I
5 return

Method int getIt()

0 aload_0
1 getfield    #4 // Field Example.i I
4 ireturn

As with the operands of method invocation instructions, the operands of the putfield and getfield instructions (the constant pool index #4) are not the offsets of the fields in the class instance. The Java compiler generates symbolic references to the fields of an instance, which are stored in the constant pool. Those constant pool items are resolved at runtime to determine the actual field offset.

Basically getfield and putfield are used for manipulating object fields. The getfield fetches field object. The constant pool item will be a field reference to a class name and a field name. The general form for getfield is given as:

     getfield ............,handle => ............, value
     getfield ............,handle => ............,value-word1, value-word2

Here, handle must be reference to an object. The value at offset into the object referenced by handle replaces handle on the top of the stack. If the specified field is a static field, an IncompatibleClassChangeError is thrown.

The putfield is also used for manipulating object fields. This instruction sets field in object. The constant pool item is a field reference to a class name and a field name. The general form for putfield is:

     putfield ............, handle, value => ............
     Putfield ............, handle, value-word1, value-word2 => ............

If handle is null, a NullPointerException is thrown and if the specified field is a static field, an IncompatibleClassChangeError is thrown.

24.7 ARRAY AND VIRTUAL MACHINE

Arrays are also served as an object for Java virtual machine. To create an array of a numeric type the newarray instruction is used in the bytecode.

 /*PROG 24.5 DEMO ARRAYS AND VIRTUAL MACHINE USING NEWARRAY */
class JPS5
{
      public static void main(String args[])
      {
             int[] arr ={ 0, 1, 2, 3, 4 };
             for (int i = 0; i < arr.length; i++)
             System.out.print(arr[i] + " ");
      }
}

The above code might be compiled to

/* FILE: JPS5.BC FOR DEMO ARRAYS AND VIRTUAL MACHINE USING NEW ARRAY */
Compiled from "JPS5.java"
class JPS5 extends java.lang.Object
{
JPS5();
      Code:
       0: aload_0
       1: invokespecial    #1; //Method java/lang/
         Object."<init>":()V
       4: return
public static void main(java.lang.String[]);
      Code:
       0: iconst_5
       1: newarray int
       3: dup
       4: iconst_0
       5: iconst_0
       6: iastore
       7: dup
       8: iconst_1
       9: iconst_1
       10:        iastore
       11:        dup
       12:        iconst_2
       13:        iconst_2
   14:    iastore
   15:    dup
   16:    iconst_3
   17:    iconst_3
   18:    iastore
   19:    dup
   20:    iconst_4
   21:    iconst_4
   22:    iastore
   23:    astore_1
   24:    iconst_0
   25:    istore_2
   26:    iload_2
   27:    aload_1
   28:    arraylength
   29:    if_icmpge  65
   32:    getstatic       #2; //Field java/lang/System.out:
                                          Ljava/io/PrintStream;
   35:    new   #3; //class java/lang/StringBuilder

   38:   dup
   39:   invokespecial    #4; //Method java/lang/
          StringBuilder."  <init>":()V
   42:   aload_1
   43:   iload_2
   44:   iaload
   45:   invokevirtual     #5; //Method java/lang/
          StringBuilder. append:(I)Ljava/lang/StringBuilder;
   48:   ldc   #6; //String
   50:   invokevirtual     #7; //Method java/lang/
          StringBuilder.append:(Ljava/lang/String;)Ljava/
          lang/StringBuilder;
   53:   invokevirtual     #8; //Method java/lang/
          StringBuilder.  toString:()Ljava/lang/String;
   56:   invokevirtual     #9; //Method java/io/PrintStream
          .print:(Ljava/lang/String;)V
   59:   iinc 2, 1
   62:   goto 26
   65:   return
}

Explanation: The above bytecode is given for the Java application program where array has been used. At line 0 of public static void main(java.lang.String[]); iconst_5 is given which is a pushing instruction, used to push the five integer values onto the stack. There are six of these bytecodes one for each of the integers 0-5 (icont_0, iconst_1, iconst_2, inconst_2, iconst_3, iconst_4 and iconst_5) given by line 5, 12, 13, 16, 17, 20 and 21. The general form iconst is given below:

iconst_  ........, => ........,

The next instruction given in the above bytecode is nothing but the instruction used for creating an array of numeric type. The general form of this instruction is:

newarray  ........, size => result

The newarray instruction is given to manage the array. It is used to allocate new array. Its size must be an int. It represents the number of elements in the new array. The newarray instruction is an attempt to allocate a new array of the indicated type, which is capable of holding size elements. If size is less than zero, a NegativeArraySizeException is thrown and if there is not enough memory to allocate the array, an OutOfMemoryError is thrown. The instruction dup is give at line-3 used for stack operation. The dup is used to duplicate the top word on the stack. The general form for dup instruction is:

dup  ....., any => ........., any, any

Now the next instruction given in the above bytecode for JPS5 will be discussed, which is iastore given at line-6. The general form of iastore is given below:

iastore  ...... ., array, index, value => ......

The iastore stores the value into the array. Array must be an array of int, index must be an integer. If array is null, a NullPointerException is thrown and if index is not within the bounds of array, an ArrayIndexOutOfBoundsException is thrown.

The next instruction discussed here is astore, given at line-23 in the bytecode shown above.

23: astore_1

The astore stores the object reference into the local variable. It uses a handle. Handle must be a return address or a reference to an object. The general form for the astore instruction is given as:

astore_<A> ......., handle => ......

There are four types of these bytecodes, one for each of the integers starting from 0 to 3 as:

astore_0, astore_1, astore_2 and astore_3 .

Now, the working of istore given at line-25 will be discussed. The istore is used to store stack values into local variables.

25: istore_2

In the instruction istore 'i' is given for integer. That is the reason istore instruction is used to store int into the local variable. The general signature for the instruction is given as:

istore ........., value => .........

The next new instruction given in the bytecode is iload given at line-26

26: iload_2

The iload instruction is nothing but the instruction given for the Java virtual machine to load the local variables onto the stack. The signature for iload instruction is:

iload_ ...... . . => ......, value

The role of iload is to load int from local variable onto the operand stack. The local variable (<i>load_2 shown in the byte code) in the current Java frame must contain an int. There are four different flavours of iload instruction, one for each of the integer starting from 0 to 3: iload_0, iload_1, iload_2 and iload_3.

Now a bit about the aload instruction will be discussed. The aload instruction is shown in the above bytecode at line-27 as:

27: aload_1

There are mainly two types of aload instructions. The signature of both the aload instructions is given below:

aload ...... => ......, value

It is used to load object reference from local variable.

aload_<A> ...... . => ..... . , value

It is used to load object reference from local variable. Here local variable <A> in the current Java frame must contain a return address or reference to an object. There are four different bytecodes for aload_<A> , one for each of the integer 0-3: aload_0, aload_1, aload_2 and aload_3 .

The next instruction given in the bytecode file JPS5.bc is if_icmpge which is nothing but used for transferring control. The instruction if_icmpge is given at line-29 as shown below:

29: if_icmpge 65

For the description of if_icmpge instruction, the signature of the instruction is looked into which is given as:

if_icmpge ..... . . , value1, value2 => ......

Here for the instruction if_icmpge execution proceeds at that offset where value<rel>0 is true in the first set of bytecodes Table 24.2, value1<rel>value2 is true in the second set, or value is null or not null in the third; byte1 and byte2 are used to construct a signed 16-bit offset from the pc (register). Here <rel> is nothing but one of eq, ne, lt, gt, le, and ge which represents the following:

Bytecode for if_icmpge Meaning
eq Equal
ne Not equal
lt Less than
gt Greater than
le Less than or equal
ge Greater than or equal

Table 24.2 Option used for if_icmpge instruction

Now getstatic instruction can be discussed which is used for manipulating object fields. The getstatic field is shown in the above code at line-32

32: getstatic   #2; //Field java/lang/System.out: Ljava/io/PrintStream;

The instruction getstatic is given to get static field from class. There are two flavours of getstatic instruction. The general form of both the getstatic type is given below:

getstatic ........ . , => ............, value
getstatic ........ . , => ............, value-word1, value-word2

For getstatic instruction byte1 and byte2 are used to construct an index into the constant pool of the current class. The constant pool item will be field reference to a static field of a class. The value of that field is placed on the top of the operand stack. Here it is important to note that the first stack picture is for 32-bit and the second for 64-bit-wide fields.

The next instruction to be focussed is new instruction. In the above bytecode new is used at line-35 as shown below:

  35: new   #3; //class java/lang/StringBuilder

The new instruction is mainly used to create new object. The general form for new instruction is given below:

  new ........ . => …..,handle

Byte1 and byte2 are used to construct an index into the constant pool of the current class. The item at that index must be a class name that can be resolved to a class pointer, class.

The iaload instruction is the next instruction which will be discussed now. It is given in the above bytecode at line-44.

 44: iaload

The signature for the iaload instruction is given below:

  iaload ........, array, index => …., value

The iaload instruction is used to load <type> from array. For the array, index must be integer type. The <type> value at position number index in array is retrieved and pushed onto the top of the stack.

The ldc instruction is used to push the item from the constant pool. In the byte code ldc instruction has been given at line-48

  48: ldc   #6; //String

The iinc instruction is given to increment local variable by constant. The iinc instruction is given at line-59 in the above bytecode given for JPS5.bc

  59: iinc 2, 1

Value of iinc instruction is incremented by the value byte2, where byte2 is treated as a signed 8-bit quantity.

The last instruction of the above bytecode is goto instruction, which is given at line-62 as given below:

  62: goto 26

There are two versions of goto statement: goto -no change and goto -no change.

The goto instruction is also used for transferring control. Byte1 and byte2 are used to construct a signed 16-bit/32-bit offset. For goto statement, execution starts at that particular offset from the register pc.

24.8 SWITCH STATEMENTS AND VIRTUAL MACHINE

There are two different types of instruction to compile switch statement in Java: tableswitch instruction and lookupswitch instruction.

To see the working of both the instructions given for handling switch statement in Java an example is given below.

/*PROG 24.6 DEMO (TABLESWITCH INSTRUCTION) OF SWITCH-CASE AND VIRTUAL MACHINE */
import java.io.*;
import java.util.*;
class JPS6
{
     public static void main(String args[])
     {
            Scanner sc=new Scanner(System.in);
            System.out.print("
 Enter 0, 1, or 2 :=");
            int num = sc.nextInt();
            switch (num)
            {
                     case 0:
                             System.out.println("
 U entered
                                                       zero
");
                             break;
                     case 1:
                             System.out.println("
 U entered
                                                       one
");
                             break;
                     case 2:
                             System.out.println("
 U enterd
                                                       two
");
                             break;
                     default:
                             System.out.println("
 U entered other
                                                       than 0,1,or 2
");
            }
     }
}

The bytecode for the above program can be generated:

/*FILE: JPS6.BC CONTAINS BYTECODE */
Compiled from "JPS6.java"
class JPS6 extends java.lang.Object{
JPS6();
      Code:
       0: aload_0
       1: invokespecial   #1; //Method java/lang/Object.
                                "<init>":()V
       4: return
public static void main(java.lang.String[]);
      Code:
       0: new   #2; //class java/util/Scanner
       3: dup
       4: getstatic   #3; //Field java/lang/System.in:
                            Ljava/io/InputStream;
       7: invokespecial   #4; //Method java/util/Scanner.
             "<init>":(Ljava/io/InputStream;)V
       10:          astore_1
       11:          getstatic   #5; //Field java/lang/System.out:
                                             Ljava/io/PrintStream;
       14:          ldc   #6; //String 
 Enter 0, 1, or 2 :=
       16:          invokevirtual   #7; //Method java/io/
                       PrintStream. print:(Ljava/lang/String;)V
       19:          aload_1
       20:          invokevirtual   #8; //Method java/util/
                       Scanner.  nextInt:()I
       23:          istore_2
       24:          iload_2
       25:          tableswitch{ //0 to 2
                    0: 52;
                    1: 63;
                    2: 74;
                    default: 85}
       52:          getstatic   #5; //Field java/lang/System.out:
                                                Ljava/io/PrintStream;
       55:          ldc   #9; //String 
 U entered zero

       57:          invokevirtual   #10; //Method java/io/
                       PrintStream. println:(Ljava/lang/String;)V
       60:          goto 93
       63:          getstatic   #5; //Field java/lang/System.out:
                                                Ljava/io/PrintStream;
       66:          ldc   #11; //String 
 U entered one

       68:          invokevirtual   #10; //Method java/io/
                       PrintStream. println:(Ljava/lang/String;)V
       71:          goto 93
       74:          getstatic   #5; //Field java/lang/System.out:
                      Ljava/io/PrintStream;  77:   ldc   #12; //
                         String 
 U enterd two

       79:          invokevirtual   #10; //Method java/io/
                       PrintStream. println:(Ljava/lang/String;)V
       82:          goto 93
       85:          getstatic   #5; //Field java/lang/System.out:
                     Ljava/io/PrintStream;
       88:   ldc   #13; //String 
 U entered other than
0,
                    1,or 2

       90:          invokevirtual   #10; //Method java/io/
                    PrintStream.
                    println:(Ljava/lang/String;)V
       93:          return
}

Explanation: The tableswitch instruction is used when the cases of the switch can be efficiently represented as indices into a table of target offsets. The important point for tableswitch instruction is that it operates only on integer data. The tableswitch instruction is efficient in terms of space complexity. In the above bytecode tableswitch instruction is given at line-25 as shown below:

25: tableswitch{ //0 to 2
   0: 52;
   1: 63;
   2: 74;
   default: 85}

To understand the working of tableswitch instruction, the general form given for the instruction can be considered:

 tableswitch ....... . .index => …..

Only three cases are given under switch statement in the program. And the cases given in switch statement are case 0, case 1 and case 2; therefore the index value will start from 0 to 2 as shown in the bytecode. The tableswitch is a variable-length bytecode. Immediately after the tableswitch opcode, zero to three 0 bytes are inserted as a padding so that the next byte starts at an address that is a multiple of 4. After the padding, a series of signed 4-byte quantities will come into picture which is nothing but default-offset, low, high, and then high-low+1. These offsets are treated as a 0-based jump table. The important thing behind the index is, if the index is less than low or if it is greater than high, default-offset is added to the pc (register).

In the above section, a lot has been discussed for tableswitch instruction. Now, lookupswitch instruction will be discussed which is also used for switch statement. It is a variable-length bytecode. To understand the working of lookupswitch the example JPS7.java is given below:

/*PROG 24.7 DEMO (LOOKUPSWITCH) OF SWITCH-CASE AND VIRTUAL MACHINE */
import java.io.*;
import java.util.*;
class JPS7
{
    public static void main(String args[])
    {
             Scanner sc = new Scanner(System.in);
System.out.print("
 Enter 0, 1, or 2 :=");
int num = sc.nextInt();
switch (num)
{
        case -5:
               System.out.println("
 U entered minus
                                    five
");
               break;
        case 0:
               System.out.println("
 U entered
                                    zero
");
               break;
        case 5:
               System.out.println("
 U enterd
                                    five
");
               break;
        default:
               System.out.println("
 U entered other
                             than -5,0,or 5
");
}

Now, the program will be compiled to get the .class file (JPS7.class) which contains the byte code. Also javap will be used to get the bytecode for the same file.

The bytecode file for JPS7.java is shown below:

/*FILE: JPS7.BC CONTAINS BYTECODE */
Compiled from "JPS7.java"
class JPS7 extends java.lang.Object{
JPS7();
      Code:
       0: aload_0
       1: invokespecial    #1; //Method java/lang/Object.
                                "<init>":()V
       4: return
public static void main(java.lang.String[]);
      Code:
       0: new   #2; //class java/util/Scanner
       3: dup
       4: getstatic   #3; //Field java/lang/System.in:
                                     Ljava/io/InputStream;
       7: invokespecial   #4; //Method java/util/Scanner.
           "<init>":(Ljava/io/InputStream;)V
       10:   astore_1
       11:   getstatic    #5; //Field java/lang/System.out
                                                :Ljava/io/PrintStream;
       14:   ldc    #6; //String 
 Enter 0, 1, or 2 :=
       16:   invokevirtual    #7; //Method java/io/
                PrintStream. print:(Ljava/lang/String;)V
       19:   aload_1
       20:   invokevirtual    #8; //Method java/util/
                Scanner. nextInt:()I
       23:   istore_2
       24:   iload_2
       25:   lookupswitch{ //3
             -5: 60;
             0: 71;
             5: 82;
             default: 93 }
       60:   getstatic    #5; //Field java/lang/System.out
                                                :Ljava/io/PrintStream;
       63:   ldc   #9; //String 
 U entered minus five

       65:   invokevirtual    #10; //Method java/io/
                PrintStream. println:(Ljava/lang/String;)V
       68:   goto 101
       71:   getstatic    #5; //Field java/lang/System.
              out:Ljava/io/PrintStream;
       74:   ldc   #11; //String 
 U entered zero

       76:   invokevirtual   #10; //Method java/io/
               PrintStream. println:(Ljava/lang/String;)V
       79:   goto 101
       82:   getstatic    #5; //Field java/lang/System.out
               :Ljava/io/PrintStream;
       85:   ldc    #12; //String 
 U enterd five

       87:   invokevirtual    #10; //Method java/io/
                PrintStream. println:(Ljava/lang/String;)V
       90:   goto 101
       93:   getstatic    #5; //Field java/lang/System.out
              :Ljava/io/PrintStream;
       96:   ldc   #13; //String 
 U entered other than -
             5,0,or 5

       98:   invokevirtual    #10; //Method java/io/
               PrintStream .println:(Ljava/lang/String;)V
       101:   return
}

Explanation: The lookupswitch instruction is used when the cases of the switch statement is not efficiently represented as indices into a table of target offsets. The important point for lookupswitch instruction is that it also operates only on integer data like tableswitch opcode. The bytecode for lookupswitch opcode is given in the above bytecode at line-25.

 25:  lookupswitch{ //3
     -5: 60;
     0: 71;
     5: 82;
     default: 93 }

The general form given for lookupswitch opcode is shown as:

lookupswitch ........, key => …..

If the general signature is compared with the lookupswitch instruction given in the bytecode, it can be said that the value of key is 3. Immediately after the lookupswitch opcode, zero to three 0-bytes is inserted as padding so that the next byte starts that is a multiple of 4. And immediately, after the padding is a series of pairs of signed 4-byte quantities. The first pair is special, because it contains the default offset and the number of pairs that follow. The special thing for lookupswitch is that the key on the operand stack must be an int. This key is basically compared with each of the matches. If it is equal to one of them, the corresponding offset is added to the pc register. And if the key does not match any of the matches, the default offset is added to the pc. Even though, the lookupswitch instruction must search its keys for a match rather than simply perform a bounds check and index into a table like tableswitch. Thus, a tableswitch instruction is probably more efficient than a lookupswitch where space considerations permit a choice.

24.9 THROWING AND HANDLING EXCEPTIONS, AND VIRTUAL MACHINE

This section reveals the inner working of exception handling mechanism that Java supports. Several exception handling mechanisms like try, catch and throw are discussed. Therefore to understand the working of exception handling mechanism, an example can be given here.

/*PROG 24.8 DEMO OF EXCEPTION HANDLING AND VIRTUAL MACHINE */
class demo1 extends Exception
{
}
class demo2 extends Exception
{
}
class demo3 extends Exception
{
}
class JPS11
{
      public static void main(String[] args)
      {
             int num = 10;
             for (num = 10; num <= 30; num += 10)
             {
                      try
                      {
                              if (num == 20)
                                       throw new demo1();
                              else if (num < 20)
                                       throw new demo2();
                              else if (num > 20)
                                       throw new demo3();
                      }
                      catch (Exception E)
                      {
                              System.out.println("Caught an
                                                        exception");
                      }
             }
      }
}

Exceptions are thrown from Java programs using the throw keyword. Its compilation is simple:

The bytecode for the above Java application program is given below:

/*FILE: JPS11.BC CONTAINS BYTECODE */
Compiled from "JPS11.java"
class JPS11 extends java.lang.Object{
JPS11();
      Code:
       0: aload_0
       1: invokespecial    #1; //Method java/lang/
                               Object."<init>":()V
       4: return
public static void main(java.lang.String[]);
      Code:
       0: bipush    10
       2: istore_1
       3: bipush    10
       5: istore_1
       6: iload_1
       7: bipush    30
       9: if_icmpgt 72
       12:   iload_1
       13:   bipush    20
       15:   if_icmpne    26
       18:   new    #2; //class demo1
       21:   dup
       22:   invokespecial    #3; //Method demo1."<init>":()V
       25:   athrow
       26:   iload_1
       27:   bipush    20
       29:   if_icmpge    40
       32:   new    #4; //class demo2
       35:   dup
       36:   invokespecial    #5; //Method demo2."<init>":()V
       39:   athrow
       40:   iload_1
       41:   bipush    20
       43:   if_icmple    54
       46:   new    #6; //class demo3
       49:   dup
       50:   invokespecial    #7; //Method demo3."<init>":()V
       53:   athrow
       54:   goto 66
       57:   astore_2
       58:   getstatic    #9; //Field java/lang/System.
                                         out:Ljava  /io/PrintStream;
       61:   ldc    #10; //String Caught an exception
       63:   invokevirtual    #11; //Method java/io/
               PrintStream.println:(Ljava/lang/String;)V
       66:   iinc 1,   10
       69:   goto 6
       72:   return
Exception table:
      from   to   target  type
       12   54   57   Class java/lang/Exception
}

Explanation: For digging the matter deep about the working of exception handling mechanism, there has to have the detailed ideas about the opcode given in the above bytecode file JPS11.bc. Hence, discussion will begin with if_icmpgt instruction given at line-9 for public static void main(java.lang. String[]);

 9: if_icmpgt 72

The opcode if_icmpgt is nothing but the instruction for transfer control. The general signature for if_icmpgt is given as:

if_icmpgt ........, value1, value2 => ........ .

It is used to jump if one integer is greater than another. In the above shown bytecode first 10 is pushed onto the stack by bipush opcode at line-0 and stored by using istore_1 as shown at line-1. The value 10 has been assigned in the variable num which is of integer type. Then again in for loop the value 10 in num is once again assigned ; for this purpose once again bipush and istore instruction has been used at line-3 and line-5, respectively. After that the instruction iload_1 is given to load the value 10 in the operand stack. Again bipush is given to push the value 30 onto the stack as boundary condition for the for loop; that is if the value will be less than or equal to 30, for loop will work otherwise control will move out from the loop. To achieve this condition (if value of num is more than 30) in the next line if_icmpgt is given. The role of if_icmpgt is just to jump if one integer is greater than another. Form the bytecode we can see that at line-9, if_icmgt opcode is given, which has the value 72 and at line-72 return statement is given. The next instruction discussed here is if_icmpne given at line-15.

15: if_icmpne 26

This instruction is also a transfer control instruction used to transfer the control if two integers are not equal. The working of if_icmpne is that it first pops the top two values of integer type from the operand stack and then compares the values. If the two integers are not equal, execution branches to the address (pc: program counter). But if the integers are equal, execution continues at the next instruction. The general signature for if_icmpne opcode is:

if_icmpne ........, value1, value2 => ............

The first condition (if-statement) given in the try block of JPS11.java is:

if (num == 20)
   throw new demo1();

Since, initially value of num is 10 and in the if-statement the condition has been given for checking the equality of num with 20 which is not correct, therefore it will throw an exception. Diagrammatically it can be represented as:

images

value1 = 10 (num)
value2 = 20

Since num is not equal to 20 exception is obtained. But if the exception is not obtained, the bytecode given below will execute:

18:   new   #2; //class demo1
21:   dup
22:   invokespecial   #3; //Method demo1."<init>":()V
25:   athrow

The new opcode is given to create new object for the class demo1. The role of dup opcode is to duplicate the top word given on the stack. Invokespecial is a method invocation opcode which is used to invoke method (demo1 for the program JPS11.java) belonging to a specific class. The athrow opcode is an exception handling opcode. The signature of athrow opcode is:

athrow ........handle => [undefined]

Rest of the portion is self-explanatory.

24.10 JAVA BASE API

Currently the Java base API is defined to be the Java applet API, described in the next sections. Over time, as the platform develops, this base will grow, as some of the standard extension API migrate into the Java base API. The Java base API is also known as the Java core API.

24.10.1 Java Applet API

The Java applet API, also known as the Java base API, defines the basic building blocks for creating fully functional Java-powered applets and applications. It includes all the classes in the Java package: java.lang, java.util, java.io, java.net, java.awt and java.applet.

24.11 JAVA STANDARD EXTENSION API

In this section, the Java standard extension API is described. These extensions are 'standard' in that they form a published, uniform, open API that anyone can implement. Once defined, they can be added to maintain backward compatibility, not changed in a way that calls to them would fail. Over time, new extensions will be added. In addition, some of these extensions will migrate into the Java base API. The current plan for this migration is shown in the Table 24.3.

Java API
Migrate to Java Base API Remain as Java Standard Extension
Java 2D Java 3D
Audio Video, MIDI
Jaav Medai Framework Java Share
Java Animation Java Telephony
Java Enterprise Java Server
Java Commerce Java Management
Java Security

Table 24.3 Migration from standard extension API to Java base API

An implementation should do whatever is appropriate for the platform it runs on, within its hardware constraints. For example, desktop operating systems that have access to speaker will produce audio; however, a mainframe or network operating system that has no speaker is permitted to do the equivalent of a no-op or some other well-defined behaviour, such as throwing an exception.

24.11.1 Java Security API

The Java security API is a new Java core API, built around the java.security package (and its subpackages). This first release includes primarily cryptography functionality, which can be incorporated into Java-based applications. Future releases of this API will include more primitives supporting system security and secure distributed computing.

The Java security API is a framework for developers to easily and securely include security functionality in their applets and applications. This functionality includes cryptography, with digital signatures, encryption and authentication.

The cryptography framework in the Java security API is designed so that a new algorithm can be added later on without much difficulty and can be utilized in the same fashion as existing algorithms. For example, although DSA is the only built-in digital signature algorithm in this release, the framework can easily accommodate another algorithm such as RSA.

APIs for data encryption and other functionalities, together with their implementations, will be released separately in a 'Java Cryptography Extension' (JCE) as an add-on package to JDK. These APIs include block and stream cipher, symmetric and asymmetric encryption, and support for multiple modes of operation and multiple encryption.

Java security includes an abstract layer that applications can call. This layer, in turn, makes calls to Java security packages that implement the actual cryptography. This allows third-party developers specializing in providing cryptographic functionality to write packages for Java security. Java security also includes system support for key management, including a secure database, certificate facility, and so on.

This architecture provides for replaceable, upgradeable security. Whenever a strong algorithm or a faster implementation becomes available, modules can be replaced in the platform, in a manner completely transparent to applications.

24.11.2 Java Media API

To support various interactive media on and off the Web Java supports the Java media API. The Java media API mainly defines the multimedia classes given in Java. It is highly extensible, which is composed of various different components. The component of Java media APIs includes audio, video, 2D and 3D animation, telephony, Java speech and Java collaboration. The main focus of Java media API is to provide interfaces to Java programmers to use a wide range of media types within their applications and applets.

The components of the Java media APIs are as follow:

1.   Java 2D API : It mainly includes line art, images, color, transforms and compositing. It provides an abstract imaging model which extends the functionality of 1.02 AWT package. Java 2D API also provides an extension mechanism to support various arrays of different presentation devices, image formats, color spaces and encoding mechanism.

2.   Java Media Framework (JMF) API: It specifies a unified architecture, messaging protocol and programming interface for media players, capturing and conferencing. It mainly handles time critical media, such as audio, video and MIDI where synchronization is required. Java media framework will be published as three APIs.

images

Figure 24.7 Java Media Frame APIs

images Java media player: The Java media player will be published first. It is the API used for synchronization, controlling, processing and presenting of compressed streaming and stored timed media, which includes video and audio.

images Java media capture: It is used to capture the Web pages.

images Java media conference: Especially for conference Web pages and API specification are not yet published.

images Java collaboration API: Provides interactive two-way, multiparty communication over a variety of dedicated networks. There will be two versions of Java collaboration.

Ver1: Given for sharing of collaboration-aware applications.

Ver2: Given for sharing of collaboration-unaware applications.

images Java telephony API: It mainly works to integrates telephones with computers. Java telephony gives the idea of 'how to control the phone calls' . It provides basic functionality for first-party and third-party call control.

images Java speech: It provides Java based speech recognition and speech synthesis system.

images Java animation API : It provides Java based system for motion and transformation of 2D objects.
It uses Java media framework for synchronization, composition and timing.

images Java 3D API: It has been used specially for 3D objects. To handle 3D object, Java 3D provides an abstract, interactive imaging model. The 3D API is closely integrated with audio, video, MIDI and animation area.

24.11.3 Java Enterprise API

Java enterprise APIs are mainly given to support connectivity to enterprise databases. There are various types of database architecture like centralized, client-server, multiprocessor and distributed. With the help of Java enterprise APIs, corporate developers are building distributed client/server applets and applications in Java that run on any operating system or hardware platform in the enterprise. There are currently three groups for connectivity: JDBC (Java database connectivity), interface definition language and remote method invocation.

JDBC: JDBC is Java database connectivity, a standard SQL database access interface, which is used for providing access to a wide range of relational databases. JDBC is also used to provide a common base on which higher level tools and interfaces can be developed.

Interface Definition Language (IDL): It is developed to the OMG interface definition language specification. It is a language-neutral way to specify and interface between an object and its client on different platform. Java interface definition language (IDL) is implemented completely in Java. Mainly Java IDL components are used to provide mapping of its method, packages, etc., to IDL operations and features.

Remote Method Invocation: It is given for invocation between peers, or between client and server. RMI performed, serves its purpose when applications at both the ends of the invocation are written in Java.

24.11.4 Java Commerce API

It will bring a methodology for secure purchasing and financial management on Web. The initial component of the Java commerce API is the Java wallet, which defines and implements a client-side framework for credit card, and electronic cash transactions. For secure purchasing and financial management, Java wallet keeps the information about the shopper, payment instruction and details of transactions. It also uses strong cryptographic services that makes the complement process secure.

24.11.5 Java Server API

Java server API provides a uniform and consistent access to the server and administrative system resources. It is an extensible framework that enables and ease the development of a whole spectrum of Java-powered Internet and Intranet servers. Java serves API its own Java 'servlets' executable program that users upload to run on networks or servers. Servlets are platform-independent, server-side programming. They can reside on the server.

24.11.6 Java Management API

It provides a wide range of extensible Java objects and methods for building applets that can manage an enterprise network over Internets. It is composed of several different components, each associated with an aspect of the total management space. Since Java management API is a collection of Java classes it provides the building blocks for integrated management. The components of Java management APIs are shown in the diagram below:

images

Figure 24.8 Components of Java management APIs

24.12 THE JAVA API PACKAGE

All the core API packages defined by Java and their functionality are summarized in the Table 24.4.

Package Description
java.applet Provides support for applets construction.
java.awt Provides capability of graphical user interfaces.
java.awt.color Provides support for color spaces and profiles.
java.awt.datatransfer Transfers data to and from the system clipboard.
java.awt.font Represent various types of font.
java.awt.geom Facilitate working with geometric shapes.
java.awt.im Allow input of Chinese, Japanese and Korean characters to text editing components.
java.awt.dnd Support for drag-and-drop operations.
java.awt.event Handle events.
java.awt.im.spi Support for alternative input devices.
java.awt.image Process images.
java.awt.image.rederable Support rendering-independent images.
java.awt.print Provide general print capabilities.
java.beans Allows programmer to build software component.
java.beans.beanscontext Creates an execution environment for Beans.
java.io Provides input and output files.
java.lang Provides core functionality.
java.lang.annotation Provides support for annotations.
java.lang.instrument Gives support for program instrumentation.
java.lang.management Provides support for management of the execution environment.
java.lang.ref Enables some interaction with the garbage collector.
java.lang.reflect Analyzes code at runtime.
java.math Handles large integers and decimal numbers.
java.net Supports networking.
java.nio Top-level package for the NIO classes and encapsulates buffers.
java.nio.channels Encapsulates channels, used by the NIO system.
java.nio.channels.spi Supports service providers for channels.
java.nio.charset Encapsulates character sets.
java.nio.charset.spi Supports service providers' character set.
java.rmi Provides remote method invocation.
java.rmi.activation Activates persistent objects.
java.rmi.dgc Manages distributed garbage collection.
java.rmi.registry Maps names to remote object references.
java.rmi.server Supports remote method invocation.
java.security Handles certificates, keys, digests, signatures and other security functions.
java.security.acl Manages access control lists.
java.security.cert Parses and manages certificates.
java.security.interfaces Defines interfaces for DSA (Digital Signature Algorithm) keys.
java.security.spec Specifies keys and algorithm parameters.
java.sql Communicates with a SQL (Structured Query Language) database.
java.util Contains the common utilities.
java.util.concurrent Supports the concurrent utilities.
java.util.jar Creates and reads JAR files.
java.util.logging Supports logging of information relating to user preference.
java.util.prefs Encapsulates information relating to user and system preferences.
java.util.regx Supports regular expression processing.
java.util.spi Supports service providers for the utility classes in java.util.
java.util.zip Reads and writes compressed and uncompressed ZIP files.

Table 24.4 The core Java API packages

24.13 PONDERABLE POINTS

1.   The Java platform has two main parts: the Java virtual machine and the Java API.

2.   The Java API specifies a set of essential interfaces in a growing number of key areas that developers will use to build their Java-powered applications.

3.   Java API basically has two parts: Java base API and Java standard extension API.

4.   The Java virtual machine is key to the independence of the underlying operating system and hardware.

5.   The Java base API is defined to be the Java applet API.

6.   The Java applet API, also known as the Java base API, defines the basic building blocks for creating Java-powered applets.

7.   Java applet API includes all the classes in the Java package: java.lang, java.util, java.io, java.net, java.awt and java.applet.

8.   The Java security API is a framework for developers to easily and securely include security functionality in their applets.

9.   Java security includes an abstract layer that applications can call.

10. The Java media API defines the multimedia classes that support a wide range of rich, interactive media on and off the Web.

11. The Java media API includes audio, video, 2D and 3D animation, telephony and collaboration.

12. Java 2D API provides graphics and imaging capabilities beyond those available with the Java applet API.

13. Java media framework API handles traditional time critical media such as audio, video and MIDI.

14. Java animation API supports 2D animations.

15. Java share API provides the basic abstraction for live, two-way, multi-party communication between objects over a variety of networks and transport protocols.

16. Java 3D API provides high-performance, interactive, 3D graphics support.

17. Java enterprise API supports three groups for connectivity: JDBC (Java database connectivity), interface definition language and remote method invocation.

18. Java server API is an extensible framework that enables and eases the development of a whole spectrum of Java-powered Internet and intranet server.

19. Java management API is a collection of Java classes that provides the building blocks for integrated management.

REVIEW QUESTIONS

1.   What is the Java platform?

2.   Explain the term Java base platform and embedded Java platform.

3.   Explain the term Java API. Also explain Java base API and the Java standard extension API.

4.   Explain the functionality of Java security API with example.

5.   Why do we use Java media API? Also explain the components of the Java APIs.

6.   Explain the term Java enterprise API.

7.   What do you understand by Java commerce API? Also explain the functionality of the Java wallet.

8.   Explain the working of Java server API.

9.   Give the functionality of the components of Java management APIs.

10. Describe the virtual machine in detail.

11. What do you understand by instruction set for virtual machine.

12. Give the procedure for invoking method using virtual machine.

13. What is class instance?

14. What is cryptographic package provider used for API?

15. Give the detailed procedure for debugging in API environment.

16. Explain the term 'remote debugging' for API.

17. Explain Java debugger for API environment.

18. Explain the Java classes used for debugging APIs. Also explain the data types associated with Java debugging API.

Multiple Choice Questions

1.   Java platform has the part

(a) Java virtual machine

(b) Java API

(c) (a) and (b)

(d) Noneofthe above

2.   The virtual machine defines a machine independent format for binary files which is called as:

(a) .exe file

(b) .class file

(c) .javafile

(d) .datfile

3.   To see the bytecode of Java's program we will use

(a) javac -c filename>filename.bc

(b) javah -c filename>filename.bc

(c) javap -c filename>filename.bc

(d) java -c filename>filename.bc

4.   Any of the virtual machine errors listed as sub classes of ___________, may be thrown at any time during the operation of the Java virtual machine.

(a) VirtualMachineError

(b) MachineError

(c) MachineExecutionError

(d) None of the above

5.   In Java, method invocation is done by

(a) invokevirtual instruction

(b) bipushvirtual instruction

(c) bipush instruction

(d) None of the above

6.   For the method

int sum10and20()
{
   return addTwovalue(10, 20);
}

This compiles

0 aload_0
1 bipush 10
3 bipush 20
8 ireturn

Here ireturn is used to

(a) just to return the value by default

(b) take int value by addTwovalue

(c) return value to sum

(d) none of the above

7.   The invokespecial instruction must be used to

(a) invoke variables

(b) invoke stack storage area

(c) invoke instance initialization <init> method

(d) none of the above

8.   Java virtual machine class instances are created using the Java virtual machine by

(a) Using invokespecial instruction

(b) Using <init> instruction

(c) Using aload_0 instruction

(d) Using new instruction

9.   Which of the following is the method of DebuggerCallBack class?

(a) threadDeathEvent()

(b) void threadDeathEvent(int a)

(c) public void threadDeathEvent (int a)

(d) public threadDeathEvent()

10. For getting the code position when we are using RemoteStackFrame we will use

(a) getRemoteClass()

(b) getLocalVariable()

(c) getpc()

(d) None of the above

KEY FOR MULTIPLE CHOICE QUESTIONS

1.   c

2.   b

3.   c

4.   a

5.   a

6.   b

7.   c

8.   d

9.   a

10. c

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.96.105