KING FAHD UNIVERSITY OF PETROLEUM & MINERALS Information and Computer Science Department ICS-201 Introduction to Computer Science Lab 05: Java Virtual Machine, Problem Solving and Algorithms Objectives: In this lab, the following topics will be covered 1. 2. 3. 4. Java Virtual Machine Problem Solving. Algorithms. Exercises. 1. Java Virtual Machine: JVM is a component of the Java system that interprets and executes the instructions in our class files. Each instance of the JVM has one method area, one heap, and one or more stacks - one for each thread. When JVM loads a class file, it puts its information in the method area. As the program runs, all objects instantiated are stored in the heap. The stack area is used to store activation records as a program runs. Class Loading: Loading means reading the class file for a type, parsing it to get its information, and storing the information in the method area. For each type it loads, the JVM must store the following kinds of information in the method area: The fully qualified name of the type The fully qualified name of the type's direct superclass or if the type is an interface, a list of its direct super interfaces . Whether the type is a class or an interface The type's modifiers ( public, abstract, final, etc) Constant pool for the type: constants and symbolic references. Field info: name, type and modifiers of variables (not constants) Method info: name, return type, number & types of parameters, modifiers, bytecodes, size of stack frame and exception table. The end of the loading process is the creation of an instance of java.lang.Class for the loaded type. The purpose is to give access to some of the information captured in the method area for the type, to the programer. TestCircleClass.java: The following program gives information regarding the class Circle [Refer to Lab 3]. import java.lang.reflect.Method; public class TestCircleClass { public static void main(String[] args) { Circle myCircle = new Circle(15.75);// according to your constructor Class circleClassInfo = myCircle.getClass(); System.out.println("Class Name is: " + circleClassInfo.getName()); System.out.println("Parent is: " + circleClassInfo.getSuperclass()); System.out.println("Methods are: "); Method[] methods = circleClassInfo.getMethods(); for(int i = 0; i < methods.length; i++) System.out.println(methods[i]); } } Exercise: 1- Compile and execute the above program and observe its output. Now study the methods available in the class Class (from the java documentation). Some of the methods available are: Use these (and other) methods to get more information regarding the class Circle in your program TestCircleClass.java Linking: Verification, Preparation and Resolution: The next process handled by the class loader is Linking. This involves three sub-processes: Verification, Preparation and Resolution. Verification is the process of ensuring that binary representation of a class is structurally correct. Example of some of the things that are checked at verification are: Every method is provided with a structurally correct signature. Every instruction obeys the type discipline of the Java language Every branch instruction branches to the start not middle of another instruction. In the Preparation phase, the Java virtual machine allocates memory for the class (i.e static) variables and sets them to default initial values. Note that class variables are not initialized to their proper initial values until the initialization phase - no java code is executed until initialization. The default values for the various types are shown below: Resolution is the process of replacing symbolic names for types, fields and methods used by a loaded type with their actual references. Symbolic references are resolved into a direct references by searching through the method area to locate the referenced entity. Class Initialization and Instantiation Initialization of a class consists of two steps: Initializing its direct superclass (if any and if not already initialized) Executing its own initialization statements The above imply that, the first class that gets initialized is Object. Note that static final variables are not treated as class variables but as constants and are assigned their values at compilation. After a class is loaded, linked, and initialized, it is ready for use. Its static fields and static methods can be used and it can be instantiated. When a new class instance is created, memory is allocated for all its instance variables in the heap. Memory is also allocated recursively for all the instance variables declared in its super class and all classes up in inheritance hierarchy. All instance variables in the new object and those of its superclasses are then initialized to their default values. The constructor invoked in the instantiation is then processed. Finally, the reference to the newly created object is returned as the result. The following program demonstrates the order of class instantiation. class Super { int x=10; Super() { this(9); printThree(); x=20; } Super (int x) { printThree(); this.x=x; } void printThree() { System.out.println("three"); } } class Test extends Super { int three = (int)Math.PI; // That is, 3 public static void main(String[] args) { Test t = new Test(); t.printThree(); } void printThree() { System.out.println("three = "+three+" x= "+x); } } Exercise: 2- Try to give the output of the above example without compiling and executing it. Then, compile and execute the program to check your answer. Comment the constructor Super(), now compile the program and explain the compilation error. comment again the other the other constructor in Super and compile. Why is your program now compiling without errors; explain. 2. Problem Solving: Ask questions to understand the problem Look for familiar things Divide and conquer Test your solution Definitions of the Algorithm A logical sequence of steps for solving a problem, … Unambiguous (precise) set of steps for solving a problem (or subproblem) in a finite amount of time using a finite amount of data. The algorithm must be general, that is, it should solve the problem for all possible input sets to the problem. If there is a particular output for an input, we say that the algorithm can be applied to this input and process it to give the corresponding output. Properties of Algorithm An algorithm should have the following properties: 1. 2. 3. 4. No ambiguity in any instruction No ambiguity which instruction is executed next Finite number of instructions Execution must halt and produce a result No ambiguity in any instruction: The instructions in an algorithm must be precisely defined, so that any person or machine implementing the instructions must have no difficulty in implementing them. For example, an instruction: “Adjust the temperature to suitable level” is ambiguous and not precisely defined. No ambiguity which instruction is executed next: The order in which instructions in algorithm must be executed should also be well defined and not ambiguous. Again, we can say that the ordering should be such that any person or machine implementing the algorithm must have no difficulty in implementing them. Finite number of instructions: The number of instructions in an algorithm must be finite so that implementation by hand or by machine takes a finite amount of time. Execution must halt and produce a result: Finally, an algorithm must halt and produce an output. Procedures that loop on forever on their inputs are not algorithms in the strict sense of the term. Algorithm Control Flow The constructs are of three types: Sequential A series of steps or statements that are executed in the order they are written. Selection Defines one or more courses of action depending on the evaluation of a condition. Iteration Allows one or more statements to be repeated as long as a given condition is true. Representation of Algorithms Pseudo-code (Pseudo = not real; false, Code = Program fragment) is a generic way of describing an algorithm using the conventions of programming languages, without using language-specific syntax. Pseudo-code generally does not actually use the syntax of any particular language. There is no systematic standard form, although any particular writer will generally borrow the appearance of a particular language. Details not relevant to the algorithm (such as memory management code) are usually omitted. The programming language will be augmented with natural language where convenient (for example, for trivial operations such as swapping two variables). Examples 1. Develop an algorithm to find the average of a list of student scores. Solution: The problem statement doesn’t specify the number of students, so we assume that a sentinel value of -1 for score indicates the end-of-input. The algorithm is straightforward. We keep inputting the score of each student. For each valid score entered we increment the variable count indicating the number of students. For each valid score entered, we add the score to another variable called sum. If a score is entered with a value of -1, it indicates the end of input so we stop inputting further scores. The average is equal to total/count. But what happens if the user didn’t enter any valid score. For example his first entered value is -1? In that case if calculate total/count, it will lead to a division by zero error. So we say that if count is equal to zero, then the average is also zero The algorithm is straightforward: The algorithm is straightforward: 1. Initialize score, total, count and average to zero. 2. Input student score 3. If score = -1 then go to step 7. 4. Add score to total 5. Increment count by 1. 6. Go to step 2. 7. If count ≠ 0 average = total/count. 8. Output average. Code: import java.util.Scanner; public class Sentinel { public static void main(String[] args) { Scanner stdin = new Scanner(System.in); double sum = 0, avg = 0; int score = 0, count = 0; System.out.print("Enter the score (or -1 to Quit): "); score = stdin.nextInt(); while (score != -1) { sum += score; count += 1; System.out.print("Enter the next grade (or -1 to Quit): "); score = stdin.nextInt(); } if (count != 0) avg = sum/count; System.out.println("Average Grade = "+avg); } } 2. Develop an algorithm to convert a temperature from Fahrenheit to Celsius: Algorithm 1. Get temperature 2. Result = 5 / 9*(temperature – 32) 3. return Result 3. Develop an algorithm to withdraw a given amount from the balance: Algorithm 4. Get amount 5. If amount > balance 1. Print “cannot exceed balance” 6. Else 1. balance = balance – amount 4. A woman had just filled the cookie jar when the 3 children went to bed. That night one child woke up, ate half of the cookies and went back to bed. Later, the second child woke up, ate half of the remaining cookies, and went back to bed. Still later, the third child woke up, ate half of the remaining cookies, leaving 3 cookies in the jar. Develop an algorithm to find how many cookies were in the jar to begin with? Algorithm: 1. Display “Enter the number of children:” 2. Read <number of children> 3. Display “Enter the number of cookies remaining:” 4. Read <cookies remaining> 5. <original cookies> = <cookies remaining> 6. While (<number of children> > 0) 7. <original cookies> = <original cookies> * 2 8. <number of children> = <number of children> - 1 9. End_While 10. Display “Original number of cookies =” <original cookies> 5. Develop an algorithm to display all prime numbers from 2 to 100. Give both the pseudocode version. Convert your pseudo-code into a Java program. Given an integer n, for all positive integers k less than or equal to n do the following: 1. If k is prime, i.e. isPrime(k) is true, print k. Algorithm isPrime(int x) 1. 2. 3. 4. For a given integer x do the following. Assume that x is prime. For all positive integers j less than x do the following Divide x by j. If the remainder after division is equal to zero for any division, x is not prime. 5. Return the status of primality of x. import java.util.Scanner; public class FasterPrimality { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.println("Enter an integer: "); int limit = in.nextInt(); for(int count = 2; count <= limit; count++) if(isPrime(count)) System.out.print(count + "\t"); } public static boolean isPrime(int number) { boolean prime = true; if(number % 2 == 0 && number > 2) { prime = false; return prime; } int i = 3; int upper = ((int) Math.sqrt(number)); while(i <= upper && prime) { if(number % i == 0) prime = false; i += 2; } return prime; } } Exercises 1. 2. 3. 4. Write the Java code for the algorithm of example 2. Write the Java code for the algorithm of example 3. Write the Java code for the algorithm of example 4. Develop an algorithm to check if a given integer is a perfect square or not. Give both the pseudo-code version. Convert your pseudo-code into a Java program. 5. Develop an algorithm to find the maximum and minimum value from a list of integers. Give both the pseudo-code version and the flowchart version. Convert your pseudo-code into a Java program.