2 Marching Towards Java and Java Bytecodes

2.1 INTRODUCTION: WHAT IS JAVA?

Java is an easy to learn, object-oriented programming (OOP) language developed by Sun Microsystems. There are different types of programming languages, but Java is unique among them. For example, a Visual Basic program executes correctly on Microsoft Windows, but it does not run on Apple Mac OS. With Java, a developer can write an application and run that on different operating systems (including Windows, Mac OS, Unix and Mainframes) without any modification in the code.

Typically, when developing an application in a programming language, the source code is passed through a compiler (another application) that transforms the code into a set of native instructions (for target operating system). For example, when developing applications that run on Windows operating systems, they usually run on Intel processors (like Pentium chipset). The compiler converts the source code into instructions which the processor can understand and execute.

When writing Java applications, the developer does not need to directly call Windows (or other operating systems) library functions. The Java compiler does not write native instructions; instead it generates bytecodes for a virtual machine called Java Virtual Machine (JVM) .

2.2 EVOLUTION OF JAVA

1.   In 1990, James Gosling was given a task of creating programs to control consumer electronics. Gosling and his team at Sun Microsystems started designing their software using C++ because of its object-oriented nature. Gosling, however, quickly found that C++ was not suitable for the projects they had in mind. They faced problems due to program bugs like memory leak, dangling pointer and multiple inheritance.

2.   Gosling soon decided that he would develop his own, simplified computer language to avoid all the problems faced in C++.

3.   In designing a new language, Gosling kept the basic syntax and object-oriented features of the C++ language.

4.   When Gosling completed his language design project, he had a new programming language that he named 'Oak'.

5.   Oak was first used in the Green project, wherein the development team attempted to design a control system for use in the home. This control system would enable the user to manipulate a list of devices, including TVs, VCRs, lights and telephones, all from a hand-held computer called *7 (star seven).

6.   By the time Sun discovered that the name 'Oak' was already claimed, they changed the name to Java.

7.   In 1993, after the world wide web (www) had transformed the text-based internet into a graphics-rich environment, the Java team realized that the language they had developed would be perfect for web programming. The team came up with the concept of web applets, small programs that could be included in web pages, and even went so far as to create a complete web browser (now called Hot Java) that demonstrated the language's power.

8.   In the second quarter of 1995, Sun Microsystems officially announced Java. The 'new' language was quickly embraced as a powerful tool for developing internet applications. Support for Java was added in the Netscape Navigator (Web browser on UNIX) and in the Internet Explorer.

2.3 MAIN BENEFITS OF USING JAVA

1.   Java programming language is very simple and object oriented. It is easy to learn and taught in many colleges and universities.

2.   Java applications run inside JVM , and now all major operating systems are able to run Java including Windows, Mac and UNIX.

3.   Write once, run anywhere: a Java application runs on all Java platforms.

4.   Java technologies have been improved by community involvement. It is suitable for most types of applications, especially complex systems that are used widely in network and distributed computing.

5.   Java is very secure. Only Java applications that have permission can access the resources of the main computer. Thus, the main computer is protected from virus attackers and hackers.

2.4 KEY FEATURES OF JAVA

1.   Java is simple : Java was developed by taking the best points from other programming languages, particularly C and C++. Java, therefore, utilizes algorithms and methodologies that are already proven. Error prone tasks, such as pointers and memory management, have either been eliminated or are handled by the Java environment automatically rather than by the programmer. Since Java is primarily a derivative of C++, which most programmers are conversant with, it has a familiar feel which makes it easy to use.

2.   Java is object oriented : Even though Java has the look and feel of C++, it is a wholly independent language which has been designed to be object oriented from the ground up. In OOP, the data is treated as objects to which methods are applied. Java's basic execution unit is the class. Java is considered as a pure OOP language as no coding outside of the class definitions, including main(), is allowed. Java contains an extensive class library available in the core programming packages. The advantages of OOP include reusability of code, extensibility and dynamic applications.

3.   Java is distributed : Commonly used Internet protocols such as HTTP and FTP as well as calls for network access are built into Java. Internet programming can call on the functions through the supplied libraries and access files on the Internet, as easily as writing to a local file system. Applets can be created and distributed over the communication links, which can be run on any machine supporting JVM.

4.   Java is compiled and interpreted : When Java code is compiled, the compiler outputs the Java bytecode which is executable for the JVM. The JVM does not exist physically, but it is the specification for a hypothetical processor that can run Java code. The bytecode is then run through a Java interpreter on any given platform that has the interpreter ported to it. The interpreter converts the code to the target hardware and executes it. This provides portability to any machine for which a virtual machine has been written. The two steps of compilation and interpretation allow for extensive code checking and improved security.

5.   Java is robust : Java compels the programmer to be thorough. It carries out type checking at both compile and run time and makes sure that every data structure has been clearly defined and typed. Java manages memory automatically by using an automatic garbage collector. The garbage collector runs as a low priority thread in the background by keeping track of all objects and references to those objects in a Java program. When an object has no more references, the garbage collector tags it for removal and removes the object when there is an immediate need for more memory. Exception handling built-in, strong type checking (i.e. all data must be declared as explicit type), initializing local variables are the key points which make Java robust.

6.   Java is secure : The Java language has built-in capabilities to ensure that violations of security do not occur. First and foremost, at compile time, pointers and memory allocation are removed thereby eliminating the tools that a system breaker could use to gain access to system resources. Memory allocation is deferred until run time. Even though the Java compiler produces only correct Java code, there is still the possibility of the code being tampered with between compilation and run time. Java guards against this by using the bytecode verifier to check the bytecode for language compliance when the code first enters the interpreter, before it even gets the chance to run.

The bytecode verifier ensures that the code does not do any of the following:

a. False pointers

b. Violate access restrictions

c. Incorrectly access classes

d. Use illegal data conversions

At run time, the security manger determines what resources a class can access such as reading and writing to the local disk. Sun Microsystems are currently working on a public-key encryption system to allow Java applications to be stored and transmitted over the Internet in a secure encrypted form.

7.   Java is architecturally neutral : The term 'architectural neutral' means that Java program does not depend upon the specific architecture of the machine on which they run. The Java compiler source code to a stage which is intermediate between source and native machine code. This intermediate stage is known as the bytecode or ".class" file which is neutral. The bytecode conforms to the specification of a hypothetical machine called JVM and can be efficiently converted into native code for a particular processor. Therefore, Java does not support the concept of executable files as they are machine dependent.

8.   Java is portable : The Java language follows the principle of 'write once, run anywhere' which means Java application/applet once written can be run on many platforms. By porting an interpreter for the JVM to any computer/operating system, one is assured that all code compiled for it will run on that system. This forms the basis for Java's portability. Another feature, which Java employs in order to guarantee portability, is by creating single standard for data sizes irrespective of processor or operating system platforms, i.e., all primitive types in Java are machine independent. For example, the size of the integer is 2 bytes under DOS and 4 bytes in Windows, but for Java the size of integer will remain fixed irrespective of OS, whether it is DOS, Windows, Linux or UNIX.

9.   Java is high performance : The Java language supports many high-performance features such as multithreading, just-in-time compiling, and native code usage. Multithreading is the ability of an application to execute more than one task (i.e., thread) at the same time. For example, a word processor can carry out spell check in one document and print a second document at the same time. Java has employed multithreading to help overcome the performance problems suffered by interpreted code as compared to native code. Since an executing program hardly ever uses CPU cycles all the time, Java uses the idle time to perform the necessary garbage cleanup and general system maintenance that renders traditional interpreters slow in executing applications.

Since the bytecode produced by the Java compiler from the corresponding source code is very close to machine code, it can be interpreted very efficiently on any platform. In cases where even greater performance is necessary than the interpreter can provide, just-in-time compilation can be employed whereby the code is compiled at run time to native code before execution.

10. Java is dynamic : The linker of data and methods to where they are located is done at run time. New classes can be loaded while program is running. Linking is done on the fly . Even if libraries are recompiled, there is no need to recompile code that uses classes in those libraries. This differs from C++ which uses static binding. This can result in fragile classes for the cases where linked code is changed and memory pointers then point to the wrong addresses.

2.5 JAVA CHARACTER SET

A Java program is a collection of number of instructions written in a meaningful order. Further instructions are made up of keywords, variables, functions, objects, etc., which uses the Java character set defined by Java. It is a collection of various characters, digits and symbols which can be used in a Java program (Table 2.1). It comprises the followings:

images

Table 2.1 Java character set

2.5.1 Java Tokens

The smallest individual unit in a Java program is called a Java token. Six types of tokens are defined in Java (Figure 2.1)

1.   Keywords : Keywords are those words whose meaning has already been known to the compiler. The meaning of each keyword is fixed. One can simply use the keyword for its intended meaning. The meaning of keywords cannot be changed. Also one cannot use the keywords as names for variables, function, array, etc. All keywords are written in small case letters.

images

Figure 2.1 Six types of tokens defined in Java

There are 48 keywords in Java. They are mentioned in Table 2.2.

images

Table 2.2 Keywords used in Java

2.   Identifier: Identifiers are names given to various program elements like variables, array, functions, structures, etc.

Rules for writing identifiers

Rule 1: The first letter must be an alphabet or an underscore.

Rule 2: From the second character onwards, any combination of digits, alphabets or underscore is allowed.

Rule 3: Only digits, alphabets, underscore are allowed. No other symbol is allowed.

Rule 4: Keywords cannot be used as identifiers.

Examples of valid and invalid identifiers (on the basis of above given rules):

images

3.   Constants or literal: Constants in Java refer to fixed values that do not change during the execution of a program. They are also termed as literals. A name for a constant value is called a literal. A literal is what you have to type in a program to represent a value. 'A' and '*' are literals of type char, representing the character value A and *.

There are various types of constants in Java as shown in Figure 2.2.

images

Figure 2.2 Java constants

They are classified into the following categories as given below:

(a) Integer constants : Ordinary integers, such as 17456 and - 32, are literals of type byte, short or int, depending on their size. One can make a literal of type long by adding 'L' as a suffix. For example: 17L or 728476874368L.

      They are of three types:

(i)   Decimal constants: They are sequence of digits from 0 to 9 without fractional part. It may be negative, positive or zero. For example: 12, 455, -546, 0, etc.

(ii)  Octal constant: They have sequence of numbers from 0 to 7 and first digit must be 0. For example: 034, 0, 0564, 0123, etc.

(iii) Hex constant: They have sequence of digits from 0 to 9 and A to F (represents 10 to 15). They start with 0x or 0X. For example: 0x34, 0xab3, oX3E, etc.

(b) Real constants: They are the number with fractional part. They are also known as floating point constants. Any numerical literal that contains a decimal point or exponential is a literal of type double. To make a literal of type float, one have to append an 'F' or 'f' to the end of the number. For example, '1.2F' stands for 1.2 considered as a value of type float. You need to know this because the rules of Java say that a value of type double cannot be assigned to a variable of type float. So, a error message may appear if you try to do something like "float" x=1.2;." You have to say "float x = 1.2 F".'/ So, the advice is to stick to type double for real numbers.

Real constant can also be represented in exponential or scientific notation which consists of two parts. For example, the number 212.345 can be represented as 2.12345e+2 where e+2 mean 10 to the power 2. The portion before the e, i.e. 2.12345, is known as mantissa and +2 is the exponent. Exponent is always an integer number which can be written in either lower or upper case. There may be many more representation of the above given number.

For example: 34.56, 0.67, 1.23f, 2.45F.

(c) Single character constants: They are enclosed in single quote. They consist of single character or digit. For example:'4', 'A', ' ,' etc.

(d) Boolean constants: For the type boolean, there are precisely two literals: true and false. These literals are typed without quotes. But they represent values and not variables. Boolean values occur most often as the values of conditional expressions. For example, size > 30 is a Boolean-valued expression that evaluates to true if the value of the variable size is greater than 30, and false if the value of size is not greater than 30. Boolean-valued expressions are used extensively in control structures. Of course, Boolean values can also be assigned to variables of type Boolean.

(e) String constants: They are sequence of characters, digits or any symbol enclosed in double quote. For example: "hello", "23twenty three", "&^ABC". "2.456" etc.

(f) Backslash constants: Java defines several backslash constants which are used for special purpose. They are called so because each backslash constant starts with a backslash (). They are represented with two characters whose general form is char but treated as a single character. They are also called escape sequence . Given below is the list of backslash (escape sequence) character constants (Table 2.3):

BCC Meaning ASCII
 Backspace 08
f Form feed 12
New line 10
Carriage return 13
" Double quote 34
' Single quote 39
? Question mark 63
a Alert 07
Horizontal tab 09
v Vertical tab 11
Null 00

Table 2.3 The backslash character constant

(g) Special symbols: Special symbols or separators are having special meaning in the Java program. They are [], (), { }, comma (,), semicolon (;) and dot (.).

(i)   The symbol [] is used as subscript operator and with an array.

(ii)  The symbol () is known as function operator and used with function and enclosing expressions.

(iii) The symbol {} is known as braces, where '{' is known as an opening brace and '}' is a closing brace. They are used for defining the class, interface, function or block.

(iv)  The comma is used as separators between identifiers. The separator semicolon is used as terminator or delimiter.

(v)   The dot is used for accessing members of class.

2.6 VARIABLES

A variable is a named location in memory that is used to hold a value that can be modified in the program by the instruction. A variable in Java is designed to hold only one particular type of data; it can legally hold that type of data and no other. The compiler will consider it to be a syntax error if a user tries to violate this rule. Java is called a strongly typed language because it enforces this rule. All variables must be initialized prior to their use or they must be assigned values taken from standard input stream, i.e., keyboard. Java supports variables to be initialized dynamically at any place within the program.

The general form of variable declaration is:

data type variable [list];

Here the list denotes more than one variable separated by commas:

For example:

int a;
float b,c;
char p,q;

In the above example, a is a variable of type int, b and c are variables of type float, and p, q are variables of type char. int, float and char are data types used in Java. The rule for writing the variables are the same as for writing identifiers since a variable is nothing but an identifier.

Java program allows to declare variables anywhere in the program. It is not necessary to declare all the variables in the beginning of the program. It can be declared right on the place where one wants to use it. An advantage is that sometimes lots of variables are declared in advance in the beginning of the program and many of them are unreferenced. Declaring variables at the place where they are actually required is handy. It is not necessary to declare all the variables earlier prior to their use. On the other hand, it is burdensome to look for all the variables declared in the program as they will be scattered everywhere in the whole program.

Java also allows variables to be initialized dynamically at the place of their use. It can be written anywhere in the program. For example:

int x = 23;
float sal = 2345f;
char name[] = 'Hari';

This is known as 'dynamic initialization' of the variables. The assignment of values to types must be compatible as Java is a strongly typed language.

2.7 HOW TO PUT COMMENTS IN JAVA?

Java supports three types of comments: one for single line, another one for multiline and the last one for documentation purpose.

In Java, the multiline comments must start with /* on the first line and end with */ on the last line as shown below:

/*
    This is multi
    line comment */

You must have seen this type of comment if you are familiar with C. The second form of comment comes from C++. It is the single-line comment, which starts at a // and continues until the end of the line. This type of comment is convenient and commonly used.

// this is single-line comment.

The documentation type comment starts with /** on one line and ends with */. Each line between the beginning and end of the documentation comment an * is placed. This is generally used for documenting class, interface and methods.

2.8 DATA TYPES IN JAVA

A data type is a class of data object which shares the same properties and methods for creating and manipulating them. Stating more simply, a data type is a set of values and a set of operations on those values.

There are eight so-called primitive data types built into Java. The primitive types are named byte, short, int, long, float, double, char and boolean. The first four types hold integers (whole numbers such as 17, -2345 and 0). The four integer types are distinguished by the ranges of integers they can hold. The float and double types hold real numbers (such as 3.6 and -145.99). Again, the two real types are distinguished by their range and accuracy. A variable of type char holds a single character from the unicode character set. The unicode character code is of 16 bit code which can support almost all types of characters and symbols found in different types of languages like Russian, Korean, Japanese and Chinese. Since Java is designed to allow applets (small Java program meant for Internet) to be written for world wide use, it makes sense that it would use unicode to represent characters. A variable of type boolean holds one of the two logical values true or false.

The most important difference between the data types in other languages and in Java is that all primitive types in Java are machine independent, i.e., irrespective of the machine on which you are working, all data types will be having the fix size. Size of char is 2 bytes, size of int is 4 bytes and size of float is 4 bytes (Table 2.4). All these sizes will remain fixed on all the machines. This makes it easy for the allocation and de-allocation of memory independent of the implementation of data types on that machine. This also increases portability of the Java programs.

images

Table 2.4 Range of data types

One important thing to note about Java regarding the data type is that it is a strongly typed language. Each variable, expression, literal has a strictly defined type, and during assignment and function call, the type is strictly checked for compatibility. The Java compiler checks all expressions and parameters to ensure that the types are compatible.

A strongly typed language is one in which each name in a program in the language has a single type associated with it, and that type is known as compile time. Strong typing is a good thing because it improves security by preventing many form of accidental misuse of the data. Empirically, it has been observed that strong typing is a very effective aid to achieve program reliability.

The difference between boolean type in Java and other languages is that in other languages any non-zero value is considered as true and 0 is considered as false value. In Java with boolean types, one can use expressions which return either true or false values. Integers or other data types cannot be used to act as true or false value.

2.9 STRUCTURE OF A JAVA PROGRAM

The general structure of any Java program is as given below. It states that a standard Java program may look like according to various sections present in the structure (Figure 2.3).

images

Figure 2.3 Structure of a simple Java program

1.   The first section documentation is optional, and it is used to put comments for the program, usually the program heading as given.

2.   In the second section, the package is defined if we want to include the file being written to be the part of the package. After the package statement, the package name is specified. A package is any collection of classes and interfaces. It is an optional section.

3.   If the program needs to use standard Java classes, then we must use import statement for importing the packages containing the Java classes. This is also an optional section.

4.   Next we can create various classes depending upon our requirements. This is also an optional section if you are not dealing with classes and objects and making elementary programs without using the class. In Java, all the functions, variables and constants must be defined inside the class.

5.   The last section contains the class in which the main() function is defined. A class containing the main function must be present in every Java program. It contains all statements which are to be executed. Inside the main function, we may create objects of classes created earlier. All statements are put inside the braces and terminated with semicolon (;).

A full-fledged Java program is given below. If you do not understand extra stuff at this point, do not worry. This is just to give you an idea of the structure of a Java program.

/**Documentation
   * Demo program for java program structure,
   * does not serve any purpose except demonstration
*/
package demopackage; //package name is demopackage
import java.io.*;    //importing package
import java.util.*;  //importing package
/*definition of class starts here */

class demo
{
    private int x, y;
    void input(int a, int b)
    {
       x=a;
       y=b;
    }
    void show()
    {
       System.out.println("X="+x);
       System.out.println("Y="+y);
    }
} //class definition of demo ends here
class Main
{
   public static void main(String[]args) /* main fucntion
                                            definition*/
       {
          demo d1; //declaring objects
          d1=new demo(); //actually creating objects
          d1.input (10,20); //calling fucntion input
          d1.show(); //calling fucntion show
       } //main fucntion ends here
} //Main class ends here

2.10 YOUR FIRST PROGRAM IN JAVA

/*PROG 2.1 DISPLAYING "Welcome in Java Programming" on to the screen */
class Hello
{
    public static void main(String[] args)
    {
        System.out.println("WELCOME IN JAVA PROGRAMMING");
    }
}

Explanation: The class name is 'hello.' In Java, everything has to be in a class; even the main function must be defined inside the class. In order to define a program, a class must include a method called main, with a definition that takes the form (Figure 2.4)

public static void main(String[] args)
{
    //statements
}

images

Figure 2.4 Output screen of Program 2.1

The word 'public' in the first line of main() means all that this routine can be called from outside of the program. This is essential because the main() routine is called by the Java interpreter. The use of static for method is to allow you to call that method creating an object. The void means functions do not return any value. The arguments within main are called command line arguments. String is a built-in class in Java and all the arguments are passed to program and are collected in array args. The name of the String array may be anything.

When Java interpreter runs the program, the interpreter calls the main() subroutine and the statements that it contains are executed. These statements make up the script that tells the computer exactly what to do when the program is executed. The main() routine can call subroutines that are defined in the same class or even in other classes, but it is the main() routine that determines how and in what order the other subroutines are used.

To print anything onto the screen, we write as

System.out.println("WELCOME IN JAVA PROGRAMMING");

In the above example, 'System' is a built-in class defined in a package java. Lang. (A package is a collection of classes.) The package is by default imported for all Java programs. '.out' is the 'static' object of the class 'PrintStream.' An static object can be used with a class name using dot (.) operator. The println is a method defined for the PrintStream class which can be used without object using dot operator. The function prints whatever is written in quotes onto the screen and moves to the next line. Each statement in Java must end with a semicolon.

Assume the file name is hello.java. The program can be typed in any text editor or Java editor.

2.10.1 Compiling and Running the Program (DOS Based)

To compile and run the program and all the other programs in this book, you must first have a Java programming environment. You must install the Java Development Kit (JDK) onto your machine. The current version of the JDK is 1.6. The various components of the JDK are discussed in details later in the chapter.

Setting-up Java : The procedures to install the JDK version for Microsoft Windows Operating System are described below (Figure 2.5):

1.   Run the executable file of the downloaded installation package. The name of this file under format is JDK-version-windows-chipset_type.exe.

2.   Select all the features as below:

images

Figure 2.5 J2SE development kit

3.   Set the PATH environment variable browsing to the BIN folder of the JDK installation folder.

(a) Right click on the My Computer icon, select Properties and open the Advance tab as the following:

images

(b) Click the Environment button to open the dialog Environment Variables.

images

(c) Click the Edit button and append the path of the BIN folder to the end. The BIN folder is sub of the SDK installed folder, the example of its path such as: C:Programfiles Javajdk1.5.0_06bin

images

This will install Java on the computer.

Compiling Java Program : After installing and setting path if not, set up as:

Set a path for java and javac as follows:

Step 1: Open the c:edit autoexec.bat file in the Notepad Editor (or any kind of editor).

images

Step 2: Add this line - PATH=C: jdkin

images

Step 3: After switching from editor to command prompt, type c:autoexec javac and press Enter key.

images

After pressing Enter key, you will get your path PATH=C: jdkin on the command prompt as shown below.

images

Step 4: Then write javac as c:javac as shown below and press Enter key to execute all the class files.

If you do not want to set up the path, you may directly go to the bin directory and create your Java source file there; but setting the path is the preferred choice as you can work in any directory you like. We assume that the path has been set up.

Now develop you source code on any editor (here notepad is selected). We are in the directory JPS (Figure 2.6).

images

Figure 2.6 Showing the Java program on notepad

C:JPSch2>javac hello.java

The javac is the java compiler which takes input as the name of java source file. If there is no error in the .java file and path was set up correctly, there will be no output and you will get your prompt back. It means that the file hello.java has been compiled successfully. The compiled file is known as bytecode file or .class file. At the prompt type dir/p *.class and you will see a file name hello.class as shown in Figure 2.7.

images

Figure 2.7 Showing the hello.class file

Running Java Program : To run the program, the following command is used:

The java is the Java interpreter which takes .class file as argument (note: do not write the extension .class). This class file, hello.class, contains the Java bytecode that is executed by a Java interpreter. Hello.java is called the source code for the program. To execute the program, only the compiled class file is required not the source code. Note that during interpretation no file is produced. The interpreter reads the bytecode file line by line and displays output onto the screen. The interpreter is the part of JVM purely in software form.

In the program, the name of file was hello.java and name of the class was also hello. It was necessary as the Java interpreter interprets the .class file and the name of the file is same as name of the class. In case the file name and class name is different, we must compile the program by the file name and execute the program using the class name. For example, in the above case, assume the file name is file1.java. You will compile the file as

C:JPSjavac file1.java

The output file produced will be hello.java and not file1.java. Now the program runs as follows:

C:JPS java hello

The figure below shows compilation and interpretation process for a java program that is stored in file MyProgram.java (Figure 2.8).

images

Figure 2.8 Compilation and interpretation for a Java program

2.11 JAVA IS FREE FORM

Java is a free form language. The Java program can be written in any manner, i.e., no botheration of line change, spaces, tabs, etc., as long as there is at least a white space character between any token. The white space characters in Java are space, tab and new line character. For example:

The above program will compile smoothly and on interpretation, output will be produced 'Java is Free Form.' But it is usually advised not to write programs in the above manner as it makes it difficult to read and comprehend the program.

2.12 PROGRAMMING EXAMPLES

/*PROG 2.2 DISPLAYING OUTPUT ON SEPERATE LINES VER 1 */
class JPS1
{
    public static void main(String args[])
    {
        System.out.println("NMIMS UNIVERSITY");
        System.out.println("MPSTME SHIRPUR");
    }
}
OUTPUT:
C:JPSch2>javac JPS1.java
C:JPSch2>java JPS1
NMIMS UNIVERSITY
MPSTME SHIRPUR
C:JPSch2>

Explanation: The program is simple. We have two statements that print NMIMS UNIVERSITY and MPSTME SHIRPUR on each line, respectively.

/*PROG 2.3 DISPLAYING OUTPUT ON SEPERATE LINES VER 2 */
class JPS2
{
   public static void main(String args[])
   {
       System.out.print("NMIMS UNIVERSITY MUMBAI 
");
       System.out.println("MPSTME SHIRPUR CAMPUS");
   }
}
OUTPUT:
NMIMS UNIVERSITY MUMBAI
MPSTME SHIRPUR CAMPUS

Explanation: The print method does not move to the next line after printing. So we have to use to make the text appear onto the next line.

/* PROG 2.4 DISPLAYING OUTPUT ON SEPERATE LINES USING TAB */
class JPS3
{
    public static void main(String args[])
    {
        System.out.print("
COMPUTER SCIENCE	");
        System.out.println("INFORMATION TECHNOLOGY 
");
    }
}
OUTPUT:
COMPUTER SCIENCE INFORMATION TECHNOLOGY

Explanation: ' ' is the tab which leaves as tab and prints on the same line.

/*PROG 2.5 USING VARIABLES VER 1 */
class JPS4
{
   public static void main(String args[])
   {
       int num;
       System.out.println("num="+num);
   }
}
OUTPUT:
Compilation Error
Variable num might not have been initialized

Explanation: In Java, all variables must be declared and defined prior to their use. They do not contain any garbage value if not defined; instead compilation error is flashed as shown above.

/*PROG 2.6 USING VARIABLES VER 2*/
class JPS5
{
    public static void main(String args[])
    {
        String str;
        str = "WELCOME IN NMIMS UNIVERSITY FOR JAVA";
        System.out.println(str);
    }
}
OUTPUT:
WELCOME IN NMIMS UNIVERSITY FOR JAVA

Explanation: String is a class in Java defined in the file java.lang package. A package is a collection of classes and interfaces. The java.lang package is the default package imported in all Java programs. The statement String str; declares an object str of String class which is initialized to "WELCOME IN NMIMS UNIVERSITY FOR JAVA" and displayed using println method.

/*PROG 2.7 DEMO OF ALL TYPES OF VARIABLES */
class JPS6
{
   public static void main(String args[])
   {
       String str;
       str = "NMIMS UNIVERSITY";
       int num = 25;
       byte b = 20;
       float f = 35.46f;
       double d = 234.567;
       char ch = 'N';
       boolean bo = true;
       System.out.println("String str:=" + str);
       System.out.println("byte b :=" + b);
       System.out.println("float f :=" + f);
       System.out.println("Double d :=" + d);
       System.out.println("Boolean bo:=" + bo);
   }
}
OUTPUT:
String str       :=NMIMS UNIVERSITY
byte b           :=20
float f          :=35.46
Double d         :=234.567
Boolean bo       :=true

Explanation: To display any type of variables including objects of classes (only built-in and not user defined), we can concatenate it with string using + operator followed by the name of the variable to be printed. For example, "byte b: ="+b with b (i.e., value of b which is 20), so string becomes "byte b: = 20" and displayed. The same analogy applies to all other println methods used in the program.

/*PROG 2.8 READING STRING DATA */
import java.io.*;
class JPS7
{
    public static void main(String args[])
    {
       String sname;
       try
       {
          DataInputStream input;
          input = new DataInputStream(System.in);
          System.out.println("Enter your name");
          sname = input.readLine();
          System.out.println("Hello" + sname);
        }
        catch (Exception eobj)
        {
          System.out.println("Error");
        }
   }
}
OUTPUT:
Enter your name
Hari
Hello Hari

Explanation: In the first line of the program, import is the keyword, followed by java.io which is the package name and.* means all the classes from the package java.io will be imported to our program. The class DataInputStream is defined in the package java.io. This class has methods for reading the data from the console. The methods of this class might throw an exception (run time errors), therefore, we have placed the code for taking input into try block. A try block is a block created with try and {}. In the try block, any Java code which might throw an exception during the execution of the program is placed. The exception thrown, if not caught, may terminate or crash the program abnormally. The catch block following the try block is responsible for catching and handling the exception thrown. In the try block, we create a reference (not object) input type DataInputStream type as:

In the text line, we create an object of the DataInputStream class type and assign reference of it to input as:

The 'new' is the operator for creating objects dynamically. In Java, all objects are created dynamically. Objects are instances of classes. Here, input is an instance of the class DataInputStream. The parameter System.in represents that we want to read from the standard input stream, i.e., from the keyboard. It is an object of the InputStream class type.

The readLine method of the class DataInputStream allows us to read a string from the keyboard delimited by ' .' Assume the entered string is 'Hari.' This entered string is read from the console using input.readLine() and assigned to sname. Next, we display the string by concatenating with 'hari' using + operator.

Assume that the readLine method is used for reading some data from a file and not from the keyboard. It is possible that some error might occur from the file, such as the file not found or end of file has been reached. In such cases, the method may throw an exception. The thrown exception object is caught by the catch block in object E. The object E is of the class Exception type, which can handle all types of exception. So, any run-time error will be handled by the catch block and your program will not terminate abnormally. Even try block must have a corresponding catch block. On compiling the above program, you will get message like:

C:JPSch2>javac JPS7.java
Note: JPS7.java uses or overrides a deprecated API.
Note: Recompile with -Xlint: deprecation for details.

This simply means that the DataInputStream class has been replaced by some new classes in the new version of Java and that Application Programming Interface (API) is deprecated. The other new class for taking input where this message does not appear will be discussed later on. The above message does not affect execution of the program.

/*PROG 2.9 READING INTEGER DATA */
import java.io.*;
class JPS8
{
    public static void main(String args[])
    {
       String snum;
       int num;
       try
       {
          DataInputStream input;
          input = new DataInputStream(System.in);
          System.out.println("Enter a number");
          snum = input.readLine();
          num = Integer.parseInt(snum);
          System.out.println("You have entered:="
                              + num);
       }
       catch (Exception eobj)
       {
          System.out.println("ERROR!!!!");
       }
    }
}
OUTPUT:
Enter a number
30
You have entered: =30

images

Figure 2.9 Output screen of Program 2.9

Explanation: The program is almost same as the previous one, but here we are reading into data from the console. Whatever you read from console using the readLine method is treated as string even if integer, float is input, etc. Assume that you entered 30, but 30 is a string not an integer. This 30 in string form is stored in the string snum. To convert the string into the integer, we have a static method parseInt of the Integer class which converts a string into an integer and returns the integer. The returned integer 30 is stored in variable num. If you do not enter an integer as input and enter something else, say string or float, then an exception is thrown as parseInt cannot convert the sent argument to the integer as shown in the above Figure 2.9.

The entered value can directly be converted to an integer without storing it into the string variable as

The similar method for taking a long value as input is:

/*PROG 2.10 READING LONG DATA TYPES */
import java.io.*;
class JPS9
{
   public static void main(String args[])
   {
       long num1, num2;
       try
       {
          DataInputStream input;
          input = new DataInputStream(System.in);
          System.out.println("Enter the first long
                              value");
          num1 = Long.parseLong(input.readLine());
          System.out.println("Enter the second long
                              value");
          num2 = Long.parseLong(input.readLine());
          System.out.println("The two values you have
                              entered are");
          System.out.println("num1:=" + num1);
          System.out.println("num2:=+" + num2);
       }
       catch (Exception eobj)
       {
          System.out.println("ERROR!!!!");
       }
    }
}
OUTPUT:
Eneter the first long value
213456789876
Enter the second long value
123456732453
The two values you have entered are
num1:=213456789876
num2:=123456732453

Explanation: The program is similar to the previous program, but here we have accepted a long value from the user instead of an integer value.

/*PROG 2.11 READING FLOAT DATA TYPE VER 1 */
import java.io.*;
class JPS10
{
      public static void main(String args[])
      {
            String snum;
            Float obj;
            float num;
            try
            {
                 DataInputStream input;
                 input = new DataInputStream(System.in);
                 System.out.println("
Enter a float
                                           number");
                 snum = input.readLine();
                 obj = Float.valueOf(snum);
                 num = obj.floatValue();
                 System.out.println("You have eneterd"
                                           + num);
                 System.out.println("
");
            }
            catch (Exception eobj)
            {
                 System.out.println("ERROR!!!");
            }
      }
}
OUTPUT:
Enter a float number
57.78
You have eneterd 57.78

Explanation: The float is a class and it is a primitive data type. Reading a float variable from console is a two-step process:

1.   Convert the string object into the float object.

2.   Get float value from the float object using floatValue method.

Assume that the number entered is 57.78 which is assigned to snum in string from. The String object is converted to an object of the Float class using the static method valueOf of Float class as:

From this float object obj we can get the float value as,

The three-line coding can be reduced to just one-line coding as shown in the next program.

/*PROG 2.12 READING FLOAT DATA TYPE VER 2 */
import java.io.*;
class JPS11
{
      public static void main(String args[])
      {
            float num;
            try
            {
                 DataInputStream input;
                 input = new DataInputStream(System.in);
                 System.out.println("Enter a float number");
                 num =  Float.valueOf(input.readLine()).float
                       Value();
                 System.out.println("You have entered"
                                           + num);
            }
            catch (Exception eobj)
            {
                 System.out.println("ERROR!!!!!");
            }
      }
}
OUTPUT:
Enter a float number
45.67894523
You have entered 45.678944

Explanation: The program is similar to the previous one, but here we have combined the three lines in just one line.

/*PROG 2.13 READING CHARACTER FROM CONSOLE */
import java.io.*;
class JPS12
{
      public static void main(String args[])
      {
            char ch;
            try
            {
                 DataInputStream input;
                 input = new DataInputStream(System.in);
                 System.out.println("

 Enter a
                                           character");
                 ch = (char)(input.read());
                 System.out.println("You have entered"
                                           + ch);
                 System.out.println("ASCII value"
                                           + (int)ch);
            }
            catch (Exception eobj)
            {
                 System.out.println("ERROR!!!");
            }
      }
}
OUTPUT:
(FIRST RUN)
Enter a character
a
You have entered a
ASCII value 97
(SECOND RUN)
Enter a character
A
You have entered A
ASCII value 65

Explanation: To read a character, we have the read method of DataInputStream class. The method returns an integer, so we have to typecast it to a character. While displaying, we have also printed the ASCII value of the character taken by typecasting it with int.

2.13 READING USING SCANNER

One of the most remarkable inclusions in the JDK 1.5 is the scanner class defined in java.util package. This feature was not available in the previous version of Java. Therefore, in the earlier section, the older method of taking output from the user was used. But after reading this section, you will not look back and use only the scanner class for the input. Scanner is a simple text scanner which can parse primitive types and strings using regular expression.

A scanner breaks its input into token using a delimiter pattern, which by default matches white space. The resulting tokens may be converted into values of different types using the various next methods.

For example, this code allows a user to read a number from System.in, i.e., from the keyboard.

Though not necessary to use try and catch block while taking input using the scanner class, it is recommended to do so for the reasons they are in the language. Similar to nextInt(), there are methods for reading long, byte, float and other data types. They are given in the table 2.5.

Methods Purpose
nextInt() Reading an integer
nextByte() Reading a byte
nextLong() Reading a long
nextFloat() Reading float
nextBoolean() Reading a boolean
nextShort() Reading short
next() Reading a string, but included white space characters.

Table 2.5 Methods defined by the Scanner class

The programs are showing the usage:

/*PROG 2.14 READING AN INT AND DOUBLE USING SCANNER CLASS */
import java.io.*;
import java.util.*;
class JPS13
{
      public static void main(String[] args)
      {
            Scanner sc = new Scanner(System.in);
            System.out.println("
Enter an integer");
            int x = sc.nextInt();
            System.out.println("Integer is:= " + x);
            System.out.println("
Enter a double");
            double d = sc.nextDouble();
            System.out.println("Double is:=" + d);
      }
}
OUTPUT:
Enter an integer
35
Integer is: = 35
Enter a double
345.678
Double is: =345.678

Explanation: The program is simple to understand.

/*PROG 2.15 READING STRING USING SCANNER CLASS */
import java.io.*;
import java.util.*;
class JPS14
{
      public static void main(String args[])
      {
            String str;
            Scanner sc=new Scanner(System.in);
            System.out.println("
Enter you name here");
            str =sc.next();
            System.out.println("Welcome" + str);
      }
}
OUTPUT:
(First Run)
Enter you name here
Vijay
Welcome Vijay

(Second Run)
Enter you name here
Vijay Nath Pandey
Welcome Vijay

Explanation: In the program, we are reading a string from the console using the next method of the Scanner class. Note that as compared to readLine method of the DataInputStream class, the next method of Scanner class does not read the complete line of string. It breaks at the very first white space character like tab, space, etc. So if we enter the name as 'Vijay Nath Pandey,' only 'Vijay' will be returned by the next method as shown by second run.

2.14 COMMAND LINE ARGUMENTS

Command line arguments are the arguments that are supplied at command line when running your Java program. In Java, all command line arguments are objects of the String class. Few examples are given on following pages.

/*PROG 2.16 DEMO OF COMMAND LINE ARGUMENT */
class JPS15
{
      public static void main(String[] args)
      {
            System.out.println("
Command line arguments
                                  are");
            for(int i=0; i<args.length; i++)
                 System.out.println("Args" +(i+1)+"="
                                  +args[i]);
      }
}
OUTPUT:

C:JPSch2>javac command1.java
C:JPSch2>java JPS15 one two three four five
Command line arguments are
Args 1=one
Args 2=two
Args 3=three
Args 4=four
Args 5=five

Explanation: Type the above program in a file called command1.java. After compilation, run the program as given in the figure above. Bytecode file is not a command line argument. The first argument one is stored in args [0], second command line argument two is stored in args[1] and so on. In the program using for loop, we have displayed all command line arguments.

/*PROG 2.17 FINDING MAXIMUM USING COMMAND LINE ARGUMENTS */
class JPS16
{
      public static void main(String[] args)
      {
            int max = 0, t;
            try
            {
                 max = Integer.parseInt(args[0]);
                 for (int i = 0; i < args.length; i++)
                 {
                        t = Integer.parseInt(args[i]);
                        if (max < t)
                                  max = t;
                 }
            }
            catch (Exception e)
            {
                 System.out.println("PARSING ERROR!!!!");
            }
            System.out.println("Max is" + max);
      }
}
OUTPUT:
C:JPSch2>javac command2.java
C:JPSch2>java JPS16 30 56 23 45 67
Max is 67

Explanation: In the program above, we supply integers at command line. But all command line arguments are string objects, so we need to parse them into integers. The first argument is converted to an integer and assumed to be maximum and stored in max. The rest of the arguments are converted to integers and are compared to the max. If any of the argument is greater than maximum, then it becomes name command2.java.

2.15 USING CONSTANTS

In Java, constants can be created by using the final keyword. For example:

Each of the above line declares a constant of type int and float type. You cannot change the value of a constant. You can only use it. The final keyword can also be used for creating a final method and a final class. This will be discussed later in the book.

2.16 BYTECODE AND JVM

2.16.1 What is the Java Virtual Machine? Why is it Here?

The JVM is an abstract computer that runs compiled Java programs. The JVM is 'virtual' because it is generally implemented in software on top of a 'real' hardware platform and operating system. All Java programs are compiled for the JVM. Therefore, the JVM must be implemented on a particular platform before compiled Java programs will run on that platform (Figure 2.10).

images

Figure 2.10 Location of JVM

The JVM plays a central role in making Java portable. It provides a layer of abstraction between the compiled Java program and the underlying hardware platform and operating system. The JVM is central to Java's portability because compiled Java programs run on the JVM, independent of whatever may be underneath a particular JVM implementation.

What makes the JVM lean and mean? The JVM is lean because it is small when implemented in software. It was designed to be small so that it can fit in as many places as possible like TV sets, cell phones and personal computers. The JVM is mean because of its ambition. 'Ubiquity!' is its battle cry. It wants to be everywhere, and its success is indicated by the extent to which programs written in Java will run everywhere.

2.16.2 What are Java Bytecodes?

Java programs are compiled into a form called Java bytecodes (Figure 2.11). The JVM executes Java bytecodes. So, Java bytecodes can be thought of as the machine language of the JVM. The Java compiler reads Java language source (.java) files, translates the source into Java bytecodes and places the bytecodes into class (.class) files. The compiler generates one class file per class in the source.

images

Figure 2.11 How Java compiler converts Java source into Java bytecodes

To the JVM, a stream of bytecodes is a sequence of instructions. Each instruction consists of a one-byte opcode and zero or more operands. The opcode tells the JVM what action to take. If the JVM requires more information to perform the action than just the opcode, the required information immediately follows the opcode as operands.

A mnemonic is defined for each bytecode instruction. The mnemonics can be thought of as an assembly language for the JVM. For example, there is an instruction that will cause the JVM to push a zero onto the stack. The mnemonic for this instruction is iconst_0, and its bytecode value is 60 hex. This instruction takes no operands. Another instruction causes program execution to unconditionally jump forwards or backwards in memory. This instruction requires one operand, a 16-bit signed offset from the current memory location. By adding the offset to the current memory location, the JVM can determine the memory location to jump to. The mnemonic for this instruction is goto, and its bytecode value is a7 hex (Figure 2.12).

images

Figure 2.12 Mnemonic instructions representation

2.16.3 Virtual Parts

The 'virtual hardware' of the JVM 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 minimum size of a word in the JVM is 32 bits. Each register in the JVM stores one word. The stack, the garbage-collected heap and the method area reside somewhere within the JVM's addressable memory. The exact location of these memory areas is a decision of the implementor of each particular JVM.

A word in the JVM 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 bytecodes, is aligned on byte boundaries. The stack and garbage-collected heap are aligned on word (32-bit) boundaries.

2.16.4 The Proud, the Few, the Registers

The JVM has a program counter and three registers that manage the stack. It has few registers because the bytecode instructions of the JVM operate primarily on the stack. This stack-oriented design helps keep the JVM's instruction set and implementation small.

The JVM uses the program counter, or pc register, to keep track of where in memory it should be executing instructions. The other three registers—optop register, frame register and vars registers—point to various parts of the stack frame of the currently executing method. The stack frame of an executing method holds the state (local variables, intermediate results of calculations, etc.) for a particular invocation of the method.

2.16.5 The Method Area and the Program Counter

The method area is where the bytecodes reside. The program counter always points to (contains the address of) some byte in the method area. The program counter is used to keep track of the thread of execution. After a bytecode instruction has been executed, the program counter will contain the address of the next instruction to execute. After execution of an instruction, the JVM sets the program counter to the address of the instruction that immediately follows the previous one, unless the previous one specifically demanded a jump.

2.16.6 The Java Stacks and Related Registers

The Java stack is used to store parameters for and results of bytecode instructions to pass parameters to and return values from methods and to keep the state of each method invocation. The state of a method invocation is called its stack frame. The vars, frame and optop registers point to different parts of the current stack frame.

There are three sections in a Java stack frame: the local variables, the execution environment and the operand stack. The local variables section contains all the local variables being used by the current method invocation. It is pointed to by the vars register. The execution environment section is used to maintain the operations of the stack itself. It is pointed to by the frame register. The operand stack is used as a work space by bytecode instructions. It is here that the parameters for bytecode instructions are placed and results of bytecode instructions are found. The top of the operand stack is pointed to by the optop register.

The execution environment is usually sandwiched between the local variables and the operand stack. The operand stack of the currently executing method is always the topmost stack section, and the optop register, therefore, always points to the top of the entire Java stack.

2.16.7 The Garbage-collected Heap

The heap is where the objects of a Java program live. Any time you allocate memory with the new operator, that memory comes from the heap. The Java language does not allow you to free allocated memory directly. Instead, the run time environment keeps track of the references to each object on the heap and automatically frees the memory occupied by objects that are no longer referenced. This process is called garbage collection.

2.16.8 What is in a Class File?

The Java class file contains everything a JVM needs to know about one Java class or interface. In their order of appearance in the class file, the major components are: magic, version, constant pool, access flags, this class, super class, interfaces, fields, methods and attributes.

Information stored in the class file often varies in length, that is, the actual length of the information cannot be predicted before loading the class file. For instance, the number of methods listed in the methods component can differ among the class files, because it depends on the number of methods defined in the source code. Such information is organized in the class file by prefacing the actual information by its size or length. This way, when the class is being loaded by the JVM, the size of variable-length information is read first. Once the JVM knows the size, it can correctly read in the actual information.

Information is generally written to the class file with no space or padding between consecutive pieces of information; everything is aligned on byte boundaries. This helps keep the class files petite so that they will be aerodynamic as they fly across networks.

The order of class file components is strictly defined so that JVMs can know what to expect, and where to expect it, when loading a class file. For example, every JVM knows that the first eight bytes of a class file contain the magic and version numbers, the constant pool starts on the ninth byte and the access flags follow the constant pool. But because the constant pool is variable length, it does not know the exact whereabouts of the access flags until it has finished reading in the constant pool. Once it has finished reading in the constant pool, it knows the next two bytes will be the access flags.

2.17 WHY UNDERSTAND BYTECODE?

Bytecode is the intermediate representation of Java programs just as assembler is the intermediate representation of C or C++ programs. The most knowledgeable C and C++ programmers know the assembler instruction set of the processor for which they are compiling. This knowledge is crucial when debugging and doing performance and memory usage tuning. Knowing the assembler instructions that are generated by the compiler for the source code you write helps you know how you might code differently to achieve memory or performance goals. In addition, when tracking down a problem, it is often useful to use a debugger to disassemble the source code and step through the assembler code that is executing.

An often overlooked aspect of Java is the bytecode that is generated by the javac compiler. Understanding the bytecode and what bytecode is likely to be generated by a Java compiler helps the Java programmer in the same way that knowledge of assembler helps the C or C++ programmer.

The bytecode is your program. Regardless of a JIT or Hotspot run time, the bytecode is an important part of the size and execution speed of your code. Consider that the more bytecode you have, the bigger the .class file is and the more code that has to be compiled by a JIT or Hotspot run time.

2.17.1 How to Get Bytecode ?

For generating bytecode, the following steps need to be followed:

Step 1: Develop a Java program and save the program by using .java extension.

/*PROG 2.18 READING INTEGER DATA */
import java.io.*;
class JPS8
{
      public static void main(String args[])
      {
            String snum;
            int num;
            try
            {
                 DataInputStream input;
                 input = new DataInputStream(System.in);
                 System.out.println("Enter a number");
                 snum = input.readLine();
                 num = Integer.parseInt(snum);
                 System.out.println("You have enetered:="
                                           + num);
            }
            catch (Exception eobj)
            {
                 System.out.println("ERROR!!!!");
            }
      }
}

We have saved this program as JPS8.java.

Step 2: Now compile the above program by using javac compiler

javac JPS8.java

Step 3: After the successful compilation, apply the following statement: javap - c JPS8 > JPS8.bc (Figure 2.13).

Step 4: Show the bytecode (Figure 2.14).

images

Figure 2.13 Showing the successful compilation process

images

Figure 2.14 Execution of javap for getting bytecode

Compiled from "JPS8.java"
class JPS8 extends java.lang.Object{
JPS8();
      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/io/DataInputStream
      3:dup
      4:getstatic #3; //Field java/lang/System.in:Ljava/io/InputStream;
      7:invokespecial     #4; //Method
java/io/DataInputStream."<init>":(Ljava/io/InputStream;)V
      10:astore_3
      11:getstatic        #5; //Field java/lang/System.out:Ljava/io/PrintStream;
      14:ldc              #6; //String 

      16:invokevirtual    #7; //Method
java/io/PrintStream.println:(Ljava/lang/String;)V
      19:getstatic        #5;       //Field       java/lang/System.out:Ljava/io/
PrintStream;
      22:ldc              #8; //String Enter a number
      24:invokevirtual    #7; //Method
java/io/PrintStream.println:(Ljava/lang/String;)V
      27:aload_3
      28:invokevirtual    #9; //Method
java/io/DataInputStream.readLine:()Ljava/lang/String;
      31:astore_1
      32:aload_1
      33:invokestatic     #10; //Method
java/lang/Integer.parseInt:(Ljava/lang/String;)I
      36:istore_2
      37:getstatic        #5;       //Field       java/lang/System.out:Ljava/io/
PrintStream;
      40:new              #11; //class java/lang/StringBuilder
      43:dup
      44:invokespecial    #12; //Method java/lang/StringBuilder."<init>":()V
      47:ldc              #13; //String You have enetered: =
      49:invokevirtual    #14; //Method
java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/
StringBuilder;
      52:iload_2
      53:invokevirtual    #15; //Method
java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      56:invokevirtual    #16; //Method
java/lang/StringBuilder.toString:()Ljava/lang/String;
      59:invokevirtual    #7; //Method
java/io/PrintStream.println:(Ljava/lang/String;)V
      62:goto             74
      65:astore_3
      66:getstatic        #5; //Field java/lang/System.out:Ljava/io/PrintStream;
      69:ldc              #18; //String ERROR!!!!
      71:invokevirtual    #7; //Method
java/io/PrintStream.println:(Ljava/lang/String;)V
      74:return
      Exception table:
      from to target type
      0 62 65 Class java/lang/Exception
}

2.17.2 Implementation of Bytecode Works

javac Employee.java
javap -c Employee > Employee.bc

Compiled from Employee.java
class Employee extends java.lang.Object {
public Employee(java.lang.String,int);
public java.lang.String employeeName();
public int employeeNumber();
}
Method Employee(java.lang.String,int)
0 aload_0
1 invokespecial #3 <Method java.lang.Object()>
4 aload_0
5 aload_1
6 putfield #5 <Field java.lang.String name>
9 aload_0
10 iload_2
11 putfield #4 <Field int idNumber>
14 aload_0
15 aload_1
16 iload_2
17 invokespecial #6 <Method void
storeData(java.lang.String, int)>
20 return
Method java.lang.String employeeName()
0 aload_0
1 getfield #5 <Field java.lang.String name>
4 areturn
Method int employeeNumber()
0 aload_0
1 getfield #4 <Field int idNumber>
4 ireturn
Method void storeData(java.lang.String, int)
0 return

This class is very simple. It contains two instance variables, a constructor and three methods. The first five lines of the bytecode file list the file name that is used to generate this code, the class definition, its inheritance (by default, all classes inherit from java.lang.Object) and its constructors and methods. Next, the bytecode for each of the constructors is listed. Then, each method is listed in alphabetical order with its associated bytecode.

You might notice on closer inspection of the bytecode that certain opcodes are prefixed with an 'a' or an 'i.' For example, in the Employee class constructor, you see aload_0 and iload_2. The prefix is representative of the type that the opcode is working with. The prefix 'a' means that the opcode is manipulating an object reference. The prefix 'i' means the opcode is manipulating an integer. Other opcodes use 'b' for byte, 'c' for char, 'd' for double, etc. This prefix gives you immediate knowledge about what type of data is being manipulated.

Details: To understand the details of the bytecode, we need to discuss how a JVM works regarding the execution of the bytecode. A JVM is a stack-based machine. Each thread has a JVM stack which stores frames. A frame is created each time a method is invoked, and it consists of an operand stack, an array of local variables and a reference to the run time constant pool of the class of the current method. Conceptually, it might look like this (Figure 2.15):

images

Figure 2.15 A simple design of frame

The array of local variables, also called the local variable table, contains the parameters of the method and also used to hold the values of the local variables. The parameters are stored first, beginning at index 0. If the frame is for a constructor or an instance method, the reference is stored at location 0. Then location 1 contains the first formal parameter, location 2 contains the second and so on. For a static method, the first formal method parameter is stored in location 0, the second in location 1 and so on.

The size of the array of local variables is determined at compile time and is dependent on the number and size of the local variables and formal method parameters. The operand stack is a LIFO stack used to push and pop values. Its size is also determined at compile time. Certain opcode instructions push values onto the operand stack; others take operands from the stack, manipulate them and push the result. The operand stack is also used to receive return values from methods.

public String employeeName()
{
return name;
}
Method java.lang.String employeeName()
0 aload_0
1 getfield #5 <Field java.lang.String name>
4 areturn

The bytecode for this method consists of three opcode instructions. The first opcode, aload_0, pushes the value from index 0 of the local variable table onto the operand stack. Earlier, it was mentioned that the local variable table is used to pass parameters to methods. The this reference is always stored at location 0 of the local variable table for constructors and instance methods. The this reference must be pushed because the method is accessing the instance data, name of the class.

The next opcode instruction, getfield, is used to fetch a field from an object. When this opcode is executed, the top value from the stack, this, is popped. Then the #5 is used to build an index into the run time constant pool of the class where the reference to name is stored. When this reference is fetched, it is pushed onto the operand stack.

The last instruction, areturn, returns a reference from a method. More specifically, the execution of areturn causes the top value on the operand stack, the reference to name, to be popped and pushed onto the operand stack of the calling method.

The employeeName method is fairly simple. Before looking at a more complex example, we need to examine the values to the left of each opcode. In the employeeName method's bytecode, these values are 0, 1 and 4. Each method has a corresponding bytecode array. These values correspond to the index into the array where each opcode and its arguments are stored. You might wonder why the values are not sequential. Since bytecode got its name, each instruction occupies one byte, why are the indexes not 0, 1 and 2? The reason is some of the opcodes have parameters that take up space in the bytecode array. For example, the aload_0 instruction has no parameters and naturally occupies one byte in the bytecode array. Therefore, the next opcode, getfield, is in location 1. However, areturn is in location 4. This is because the getfield opcode and its parameters occupy location 1, 2 and 3. Location 1 is used for the getfield opcode; location 2 and 3 are used to hold its parameters. These parameters are used to construct an index into the run time constant pool for the class to where the value is stored. The following diagram shows what the bytecode array looks like for the employeeName method (Figure 2.16):

images

Figure 2.16 Bytecode array for employeeName method

Actually, the bytecode array contains bytes that represent the instructions. Looking at a .class file with a hex editor, the following values can be seen in the bytecode array:

images

Figure 2.17 Values in the bytecode array

2A, B4 and B0 correspond to aload_0, getfield and areturn, respectively (Figure 2.17).

public Employee(String strName, int num)
{
name = strName;
idNumber = num;
storeData(strName, num);
}
Method Employee(java.lang.String,int)
0 aload_0
1 invokespecial #3 <Method java.lang.Object()>,
4 aload_0
5 aload_1
6 putfield #5 <Field java.lang.String name>
9 aload_0
10 iload_2
11 putfield #4 <Field int idNumber>
14 aload_0
15 aload_1
16 iload_2
17 invokespecial #6 <Method void
storeData(java.lang.String, int)>
20 return

The first opcode instruction at location 0, aload_0, pushes the this reference onto the operand stack. (Remember, the first entry of the local variable table for instance methods and constructors is the this reference.)

The next opcode instruction at location 1, invokespecial, calls the constructor of this class's superclass. Because all classes that do not explicitly extend any other class implicitly inherit from java.lang.Object, the compiler provides the necessary bytecode to invoke this base class constructor. During this opcode, the top value from the operand stack, this, is popped.

The next two opcodes, at locations 4 and 5, push the first two entries from the local variable table onto the operand stack. The first value to be pushed is the this reference. The second value is the first formal parameter to the constructor, strName. These values are pushed in preparation for the putfield opcode instruction at location 6.

The putfield opcode pops the two top values off the stack and stores a reference to strName into the instance data name of the object referenced by this.

The next three opcode instructions at locations 9, 10 and 11 perform the same operation with the second formal parameter to the constructor, num, and the instance variable, idNumber.

The next three opcode instructions at locations 14, 15 and 16 prepare the stack for the storeData method call. These instructions push the this reference, strName and num, respectively. The this reference must be pushed because an instance method is being called. If the method was declared static, the this reference would not need to be pushed. The strName and num values are pushed since they are the parameters to the storeData method. When the storeData method executes, the this reference, strName and num will occupy indexes 0, 1 and 2, respectively, of the local variable table contained in the frame for that method.

2.18 THE JAVA PLATFORM

A platform is the hardware or software environment in which a program runs. We have already mentioned some of the most popular platforms like Microsoft Windows, Linux, Solaris OS and Mac OS. Most platforms can be described as a combination of the operating system and underlying hardware. The Java platform differs from most other platforms in that it is a software-only platform that runs on top of other hardware-based platforms.

The Java platform has two components: the JVM and the API.

The JVM has been earlier mentioned; it is the base for the Java platform and is ported onto various hardware-based platforms.

images

Figure 2.18 The API and JVM insulate the program from the underlying hardware

The API is a large collection of ready-made software components that provide many useful capabilities. It is grouped into libraries of related classes and interfaces; these libraries are known as packages (Figure 2.18).

As a platform-independent environment, the Java platform can be a bit slower than native code. However, advances in the compiler and virtual machine technologies are bringing performance close to that of native code without threatening portability.

2.19 JAVA, INTERNET AND WWW

Computers can be connected together on networks. A computer on a network can communicate with other computers on the same network by exchanging the data and files or by sending and receiving the messages. Computers on a network can even work together on a large computation. Today, millions of computer throughout the world are connected to a single huge network called Internet. Internet is the network of networks. New computers are being connected to the Internet every day. In fact, a computer can join the Internet temporarily by using a modem to establish a connection through telephone lines leased lines, through VSAT, etc.

The www is based on pages which can contain information of many different kinds as well as links to other pages. These pages are viewed with a web browser program such as Netscape or Internet Explorer. Many people seem to think that the WWW is the Internet, but it is really just a graphical user interface to the Internet. The pages that you view with a web browser are just files that are stored on computers connected to the Internet. When you tell your web browser to load a page, it contacts the computer on which the page is stored and transfers it to your computer using a protocol known as Hyper Text Transfer Protocol (HTTP). Any computer on the Internet can publish pages on the www. When you use a web browser, you have access to a huge sea of interlinked information that can be navigated with no special computer expertise. The web is the most exciting part of the Internet and is driving the Internet to a truly phenomenal rate of growth. Nowadays, the web has become a universal and fundamental part of every day life.

Java is intimately associated with the Internet and the www. Special Java programs called applets are meant to be transmitted over the Internet and displayed on web pages. A web server transmits a Java applet just as it would transmit any other type of information. A web browser understands Java, that is, that includes an interpreter for the JVM and can then run the applet right on the web page. Since applets are programs, they can do almost anything, including complex interaction with the user. With Java, a web page becomes more than just a passive display of information. It becomes anything that programmers can imagine and implement. For the Internet and networking Java has special support.

2.20 JDK TOOLS

There are a number of tools shipped with the JDK which are discussed below:

1.   javac: The javac stands for Java compiler. It is provided as an executable file in the bin directory of JDK. The javac tools read and interface definitions, written in the Java programming language, and compiles them into the bytecode class files. The most common usage is to compile single Java source file (Figure 2.19) as:

javac filename.java

images

Figure 2.19 Compilation of JPS8.java without using nowarn option; two warning messages are displayed

This, on compilation, creates the filename.class file provided the program is error free. You can compile multiple files together by separating the file names using a space or tab as:

javac file1.java file2.java file3.java

(a) If you want to put .class file in another directory, after the compilation you can set the -d option. The syntax is given as:

javac -d dirname file1.java

On compilation, the file1.class file will be placed in the directory dirname. This comes handy when you want to compile a number of files together and put the files in a directory.

(b) Another option is you can use is -classpath. Later we will discuss this option in depth.

(c) The nowarn option hides warning message (Figure 2.20). One such example of warning message is when you use readLine method with an object of the DataInputStream class. To suppress the message, you can compile the program as (assume that the file name is file1.java which used the readLine method):

javac -nowarn file1.java

images

Figure 2.20 JPS8.java with nowarn option; no warning message is displayed

(d) The -deprecation option tells which methods or classes have been deprecated. This can be used as (Figure 2.21):

javac -deprecation file1.java

images

Figure 2.21 JPS8.java with deprecation option

The run-time view is shown in the image given below which uses nowarn and deprecation option for a file JPS8.java

2.   java: The java is the Java interpreter. Similar to the javac, it is provided as executable file within the JDKin directory. The Java tool is used to run the Java application. It does this by starting a Java run-time environment, loading a specified class and invoking that class's main method. No specific option will be covered in this book.

3.   jdb: The Java Debugger, jdb, is a simple command line debugger for the Java classes. The jdb helps you find and fix bugs in Java language programs.

4.   javadoc: The javadoc tool parses the declarations and documentation comments in a set of Java source files and produces a corresponding set of HTML pages describing (by default) the public and protected classes, nested classes, interfaces, constructors, methods and fields. You can use it to generate the API documentation or the implementation documentation for a set of source files.

5.   javap: The javap command disassembles a class file.

6.   javah: The javah produces C header files and C source files from a Java class. These files provide the connective links that allows your Java and C code to interact.

2.21 PONDERABLE POINTS

1.   Java was developed by James Gosling at Sun Microsystems around 1991. Its original name was 'Oak.' The official name 'Java' was announced in 1995.

2.   The first complete application developed in Java was a web browser named 'Hot Java.'

3.   Java was mainly written for the Internet, but it can be used for writing console applications.

4.   Java is both compiled and interpreted. All Java programs have the extension .java. The Java source file is compiled by the Java compiler which produces bytecode file with .class extension. This file is platform-independent and can be run by a Java interpreter anywhere on any machine.

5.   Java supports unicode character set which is of 16 bits. This character code supports almost all different types of symbols present in all types of language of the world.

6.   All primitive data types in Java are platform-independent, i.e., their size remains same on every operating system.

7.   Java is a pure object-oriented programming language, i.e., even a single line of code cannot go outside from the class.

8.   Bytecode is a machine independent code which is produced for the JVM.

9.   The JVM is a virtual machine purely implemented in the form of a software program and not in hardware.

10. JDK stands for Java Development Kit which can be freely downloaded from the Internet. For running Java programs, JDK must be installed.

11. javac is the Java compiler and java is the Java interpreter.

12. In Java, no .exe file is generated; this is to support platform-independent and make it architectural neutral.

REVIEW QUESTIONS

1.   What are the key features of Java?

2.   Explain the concept of bytecode in Java. Also explain why Java does not support the concept of '.exe' file.

3.   What is JVM? Why Java has both compiler and interpreter? Justify.

4.   What is JDK? Explain the various tools of JsDK in short.

5.   'Java is free form,' justify the statement.

6.   Translate this ADT into a Java interface:

ADT: Point
Amplitude(): Real
distanceTo(Point): Real
equals(Point): Boolean
magnitude(): Real
toString(): String
xCoordinate(): Real
yCoordinate(): Real

7.   Explain the purpose of nextBoolean() method.

8.   What is command line argument? Explain the benefits of using command line arguments.

9.   Explain the working of Java stacks. How it is useful for the bytecodes?

10. How the JVM works? Also explain the working of Hypervisor used in X86 architecture.

11. Why we use Java Application Programming Interface (API)? Explain with the help of an example.

12. Explain the execution of the bytecode in Java.

13. How garbage collection heap works? How it is useful?

14. What is virtualization? How JVM performed virtualization for Java code?

15. What are comments? Describe the various comments used in Java.

16. What are the tags supported by javadoc?

17. What is the use of following JDK tools?

(a) javap

(b) javadoc

(c) jdb

(d) javah

18. Explain the major uses of jar tools available in Java.

19. Write a program to print 'Happy New Year XYZ.' The XYZ is a year; it should be given interactively through the keyboard.

20. Write a program to print

'Failure is the pillar of success.'

21. What is token? State the Java character set.

22. Write a short note on keyword.

23. What is an identifier? What are the rules to code it?

24. Which of the following are valid variable name?

(a) id2

(b) 2cons

(c) _5har

(d) #var1

(e) $HARI

(f) MPSTME NMIMS

(g) 567

(h) switch

25. What is a constant? How it is classified?

26. What is the difference between character constant and string constant?

27. Distinguish between the bytecode and Unicode character set.

28. Which of the following will compile without warning or error?

(a) float f = 2.7

(b) char c = 'x'

(c) byte B = 257

(d) boolean bo = null;

(e) int count = 0

(f) boolean flag = true

29. What will be the result for this code if it is run with the following command line argument?

class test1
{
   public static void main(String args[])
   {
      System.out.println(arg[3]);
   }
}

Multiple Choice Questions

1.   Java variables cannot start with

(a) a number

(b) an alphabet

(c) a character

(d) none of the above

2.   Identifiers are

(a) user defined names

(b) reserved key words

(c) Java statements

(d) none of the above

3.   The variable name can be started with

(a) underscore symbol ( _ )

(b) dollar symbol ($)

(c) ampersand symbol (and)

(d) none of the above

4.   How many variables can be initialized at a time?

(a) One

(b) Two

(c) Five

(d) Any number of variables

5.   In Java every variable has

(a) a type

(b) a name

(c) a value

(d) a size

(e) all of the above

6.   Which escape sequence does not have any specific meaning?

(a) ' '

(b) 'a'

(c) ''

(d) 'c'

7.   Which of these is an invalid identifier?

(a) wd-count

(b) wd_count

(c) wdcountbce

(d) w4count

8.   Who developed Java language?

(a) Ken Thomson

(b) Bjarne Stroutrup

(c) Dennis Ritchie

(d) James Gosling

9.   Java is a pure object-oriented programming language because

(a) Java is platform-independent

(b) Java is both compiled and interpreted

(c) a single line of code cannot go outside from the class

(d) none of the above

10. The next () method is used for

(a) reading an integer

(b) reading a byte

(c) reading a long

(d) reading a string, but included white space characters

11. Java supports Unicode character set which is

(a) 20 bits

(b) 32 bits

(c) 64 bits

(d) 16 bits

12. The Scanner class is defined in

(a) java.util package

(b) java.applet package

(c) java.awt package

(d) none of the above

13. Java is an object-oriented language which is

(a) platform independent language

(b) a pure object-oriented language.

(c) free form language

(d) all of the above

14. Which is not correct?

(a) jdb is a simple command line debugger for the Java classes.

(b) javac-nowarn option hides warning message.

(c) java is used to compile and run Java program.

(d) javap command disassembles a class file.

15. ________ command disassembles a class file.

(a) javac

(b) javap

(c) javah

(d) jdb

KEY FOR MULTIPLE CHOICE QUESTIONS

1.   a

2.   a

3.   a

4.   d

5.   e

6.   d

7.   a

8.   d

9.   c

10. d

11. d

12. a

13. d

14. c

15. b

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

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