MyArrayList Implementation II
MyArray.java
package scit.edu.trial;
import java.util.*;
public class MyArray extends ArrayList
{
private Object a[];
MyArray(Object element) {
a = new Object[1];
a[0]=element;
}
public Object get(int index) {
if (index < a.length){
return a[index];
}
else{
System.out.println("Index out of bounds");
return null;
}
}
public Object set(int index, Object element) {
if (index < a.length){
Object oldValue = a[index];
a[index] = element;
return oldValue;
}
else {
System.out.println("Index out of bounds");
return null;
}
}
public int size() {
return a.length;
}
public boolean add(Object element){
int lenArray;
int iterCopy;
Object copyArray[];
lenArray=a.length;
copyArray=a;
a= new Object[lenArray+1];
for(iterCopy=0;iterCopy<lenArray;iterCopy++){
a[iterCopy]=copyArray[iterCopy];
}
a[lenArray]=element;
return true;
}
public void show(){
int temp;
int iterArray;
temp=a.length;
for(iterArray=0;iterArray<temp;iterArray++){
System.out.println(a[iterArray]);
}
}
public boolean remove(Object element){
int index;
int arrayLen;
int iterArray;
int cnt=0;
arrayLen=a.length;
Object copyArray[]=new Object[arrayLen-1];
index=search(element);
if (index < 0){
System.out.println("Element Not Found");
return false;
}
for(iterArray=0;iterArray < arrayLen;iterArray++){
if(iterArray!=index){
copyArray[cnt]=a[iterArray];
cnt++;
}
}
a=copyArray;
return true;
}
private int search(Object element){
int index;
int arrayLen;
arrayLen=a.length;
for(index=0; index<arrayLen;index++){
if (a[index].equals(element) ) {
return index;
}
}
return -1;
}
public int indexof(Object element){
int index;
index=search(element);
if(index<0){
System.out.println("Element Not Found");
return -1;
}
return index;
}
public boolean contains(Object element){
int index;
index=search(element);
if(index<0){
System.out.println("Element Not Found");
return false;
}
return true;
}
}
MyTest.Java
package scit.edu.trial;
import scit.edu.trial.MyArray;
public class MyTest{
public static void main(String args[])
{
MyArray aArray = new MyArray(new Integer(2000));
aArray.add(new Integer(100));
aArray.add(new Integer(200));
aArray.add(new Integer(300));
aArray.add(new Integer(400));
aArray.add(new Integer(1000));
aArray.add(new Integer(500));
aArray.add(new Integer(600));
aArray.add(new Integer(700));
aArray.remove(new Integer(1000));
if(aArray.contains(new Integer(600))){
System.out.println("Element 600 is in list");
}
else{
System.out.println("Element 600 isnt in list");
}
aArray.remove(new Integer(700));
aArray.show();
System.out.println("Element 300 present at location\t" + aArray.indexof(new Integer(300)));
aArray.set(0,new Integer(900));
aArray.show();
}
}
OUTPUTE:\try\build>java scit.edu.trial.MyTest
Element 600 is in list
2000
100
200
300
400
500
600
Element 300 present at location 3
900
100
200
300
400
500
600
MyArrayList Implementation
In this blog, the assignment was to show implementation of the set and get method for ArrayList. I tried to make but I arrived at this following code in which MyArrayList extends directly AbstractList. In MyArrayList, I used get and set method. This is not a dynamic actual custom implementation of ArrayList.
CODE:import java.util.*;
public class TestArrayList{
private static class MyArrayList extends AbstractList
{
private Object a[];
MyArrayList(Object array[]) {
a = array;
}
public Object get(int index) {
return a[index];
}
public Object set(int index, Object element) {
Object oldValue = a[index];
a[index] = element;
return oldValue;
}
public int size() {
return a.length;
}
}
public static void main(String args[])
{
Object[] bArray= new Object[4];
bArray[0] =new Integer(12);
bArray[1] =new Integer(10);
bArray[2] =new Integer(14);
bArray[3] =new Integer(16);
MyArrayList aArray = new MyArrayList(bArray);
System.out.println("Previous to change \t" + aArray.get(1));
aArray.set(1,new Integer(40));
System.out.println("After changing value \t" +aArray.get(1));
System.out.println("Size of the array \t" +aArray.size());
}
}
OUTPUT:
Previous to change 10
After changing value 40
Size of the array 4
Garbage Collection in JVM
The memory space which had been allocated to an object from the heap, can be reused when it is not being referenced by the original object. This means that once object finished its work, the memory space that had been used by the object can be reclaimed. This whole process of reclaiming memory is known as garbage collection.
Now more technically, the heap is where the objects of a Java program live. Any time you allocate memory with the new, newarray, anewarray, and multianewarray instructions, the memory comes from the heap. The Java language doesn't allow you to free allocated memory directly. Instead, the runtime 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 called garbage collection.
Two type of garbage can be collected one is the pointer which is pointing to non existing memory address other one is memory space which doesn’t have any pointer to reference it. Also the problem with reclamation of memory arises due to restriction on physical memory size.
It can be called as memory recycling because the memory once freed can be used to allocate to new object. For this GC should have some mechanism to check out which are the object memory space not being referenced. The garbage collector must somehow determine which objects are no longer referenced by the program and make available the heap space occupied by such unreferenced objects. In the process of freeing unreferenced objects, the garbage collector must run any finalizers of objects being freed. Finalizer is activity that will check for dirty object. If it is dirty then it will be written back else will simply freed.
GC has to cope with heap i.e. memory compaction or defragmentation of memory. Suppose memory already allocated in some random order from available heap. Now if memory freed which was lying in between some other object’s memory space, then it will be some what similar to OS memory management scenario. Where having enough memory space to allocate it to process doesn’t satisfy whole requirement. But due to no single memory segment available which is big enough to accommodate process, process waits in queue. This same thing can happen in dynamic memory allocation if proper memory compaction methods are not being used.
So it is clear that any garbage collector must do three basic things. First, it must detect garbage objects i.e. unreferenced objects. Second, it must reclaim the heap space used by the garbage objects and make the space available again to the program. Third, it must take care of possible memory fragmentation.
Memory Management in JVM
There are three type usually associated with VM.
1) Static memory management: - Here everything is allocated statically. All memory areas are allocated statically before execution begins. In this method the memory space for function parameter is also allocated before execution. This is not a good strategy for a VM implementation since it restricts use of recursive calls, it doesn’t allow multithreading. This strategy generally doesn’t allow any change to data structure at runtime.
2) Linear memory management: - Memory is allocated and freed in LIFO (Last In First Out) order. New object can be allocated space very easily. But for deleting old object’s memory space all new object’s memory space has to be deleted. This is used in very simple VMs. Since many data object in VM are managed in stack like structure.
3) Dynamic memory allocation: - Memory can be allocated in any order. Allocation takes place from special area which is known as heap. Memory once allocated is not fixed; size of the object can grow or shrink on the fly. Most of the modern VM use some form of the dynamic memory management. It can be either automatic or manual. Whenever programmer has responsibility of freeing the unused memory space explicitly like in c free (), this called as manual dynamic memory management. But if all allocation and de-allocation of memory done by VM without programmers intervention, this is called as automatic dynamic memory allocation.
3a) Automatic Dynamic Memory Management: - Programmers are free from all worry of allocation and de-allocation of object’s memory space. Garbage collector comes into picture in this method which reclaims unused (unreferenced) memory space. Memory system automatically expands and shrinks data in the heap as necessary. Benefits of this system include making programming easier, no dangling pointer and improve program reliability and safety. Implementation challenges for automatic memory management are keeping tracks of pointer to memory space, deleting memory space allocated to an object i.e. garbage collection, whether to compact heap whenever object memory space is deleted
JVM-I
All computation in the JVM centers on the stack. Because the JVM has no registers for storing arbitrary values, everything must be pushed onto the stack before it can be used in a calculation.
A static Java compiler converts Java source code into a verifiably secure and compact architecture-neutral intermediate format, called Java byte codes. At runtime, the Java Virtual Machine (JVM) can either interpret the Java byte codes or translated into native code by Java Just-In-Time (JIT) compiler to improve the runtime performance.
JIT
The JIT compiler is contained within the JVM. The JIT compiler uses method-by-method translation; that is, it translates each method as it is loaded, rather than translating an entire class. When the JVM runs in interpreter mode (without the JIT compiler), it works directly with the Java bytecode, interpreting each instruction at run time.
When the JVM runs in JIT compiler mode (with the JIT compiler), the JIT compiler translates Java bytecode to native instructions and then the JVM then executes those instructions. During a single run of the Java interpreter, the JVM can use the same method multiple times, but the JIT compiler translates that method only once. After the JIT compiler translates a method, the JVM uses the method's native code instead of Java bytecode.
Bytecodes
Bytecodes are the machine language of the Java virtual machine. When a JVM loads a class file, it gets one stream of bytecodes for each method in the class. The bytecodes streams are stored in the method area of the JVM. The bytecodes for a method are executed when that method is invoked during the course of running the program. Intepretation, just-in-time compiling, or any other technique that was chosen by the designer of a particular JVM could execute it. A method's bytecode stream is a sequence of instructions for the Java virtual machine. Each instruction consists of a one-byte opcode followed by zero or more operands. The opcode indicates the action to take. If more information is required before the JVM can take the action, that information is encoded into one or more operands that immediately follow the opcode.
Platform Independence
Platform Independence
Java is created to develop network application. OO concept taken from C++ as a reduced subset of what was available in C++ and some restriction are being placed on some of OO concept like multiple inheritance. Since Java was created for networking application it have to be supported on many different platform, that’s where Java stand different than other programming languages.
Compiler being used to interpret the language semantic and syntax, and then converting it to executable form of that specified machine (here machine is used in context of hardware and OS running on it). But the problem lies here only that compiler can generate OS specific executables and compilers working on different machine has different specification (not major differences such as in MSWindows C you can use clrscr() to clear screen but in Linux C this function is not available etc) to follow, that make impossible to run one code developed on one machine to work on different machine without some modification.
Sun developed a Virtual Machine known as Java VM. This resides between java code and underlying machine. Whenever user want to compile and run a java code, the code passed to JVM which then compiles the code and convert it into byte code which can be used on any other machine. JVM create virtual OS for running executable code.
JVM also developed for many available machines, if it is available on the machine user can run any java code on that machine without any hesitation. JVM pretend java code that it running with the same machine without any modification. That is truly platform independence but needs JVM. So it is true ‘Write once run anywhere’.
DotNet come up with concept CLR ie. Common Language Runtime which specifically state that ‘Write in any language and run on one platform’, that gives us language independence (here language means that follows CLS ie. Common Language Specification).
This is one of the reason for people to use Java than any other language in the world.