27 May 2013

How Many Ways We Can Create Threads In Java

In java there are only 2 ways of creating threads. How ever since java1.5 there is one another way to invoke a Thread. The following shows how we can create threads in java.

First Method:-

A class can extend Thread class and overrides the run method of the Thread class.

Example:- 

 public class Murali extends Thread{
     public void run(){
     ==do something here==
    }
  }//class ends here.
Murali a=new Murali();
a.start();

Second Method:-

Writing a custom class which implements Runnable interface and pass this class to the Thread constructor.

Example:-      

 public class Car implements Runnable{
   public void run(){
    ==do something here==
   }
  }

Thread a=new Thread(new Car());
a.start();

Second method is good than first method because only one class can be extended and if you have extended Thread class no other class can be extended.
Since java1.5:-

How ever since java1.5 there is another way to invoke a thread. That is by “ExecutorService”. All these classes are from the “java.util.concurrent” package. There are various ways to create a “ExecutorService” using “Executors” factory class. The following is one of the way to create “ExecutorService”..

ExecutorService es= Executors.newSingleThreadExecutor();
RunnableImpl r = new RunnableImpl();
Future fu=es.submit(r);

using “ExecutorService” methods we can submit eighter Runnable or Callable to the service for execution.

How ever this cannot be said as the new way to create a Thread. It is because ExecutorService internally uses “ThreadFactory” class to create a new thread which internally uses eighter first or second method. So we have to say that there are only two ways to create threads but there is a new way in java1.5 to invoke a thread but not to create a Thread.

How “Thread.join()” works in Java

The join is the instance method in the Thread class. So many people get confused of the function of join. So thought to document the functionality of it. The join functionality awaits the thread to die. Here is how it works with example.

Example:-

public class ThreadJoin {

 public static void main(String[] args)throws Exception {
  Thread a=new Thread(new Mur(),"1");
  Thread b=new Thread(new Mur(),"2");
 
  a.start();
  a.join();
  b.start();
 
  System.out.println("End Of Main Thread");

 }

 private static class Mur implements Runnable{
  public void run() {
              for (int x = 1; x <= 10; x++) {
                       System.out.println("this is thread "
                                       + Thread.currentThread().getName());
                      }
  }
 }//end of the static inner class.
}//end of the main class.

Normally the thread that runs the main method is called main thread. So when main thread starts the other threads it does not stop executing. It starts the other threads and still continues it’s execution. Main thread finishes it’s execution and at the end it waits for the other threads that it created to die. Once the other threads it created dies then the main thread also dies.


Now How Does Join Makes Difference:-

The thread that executes the join on another thread waits (without moving to next instruction) until the thread on which the join is called dies.

In the example the main thread started a new thread by executing start method on Thread object “a” (a.start();). So now the thread “a” (Thread a=new Thread(new Mur(),"1")) starts executing as an individual light weight process. The main thread moves on and executes the next statement that is “a.join();”. The moment that it executes join on thread “a” it goes into a waiting mode, This means it stops executing the next instructions. The main thread invoked “join” (a.join();)on another thread (that is on thread object “a”) so it stops executing and waits until the other thread on which the join is called dies. Once the other thread dies the main thread resumes and starts executing the next instructions.

So the thing that has to be understood is, any thread that invokes join on another thread waits until the thread on which join is called finishes it’s execution.

The Output of the above stated example when “a.join()” is commented:-

this is thread 2
this is thread 1
this is thread 1
End Of Main Thread
this is thread 1
this is thread 2
this is thread 2
this is thread 1
this is thread 1
this is thread 1
this is thread 1
this is thread 2
this is thread 1
this is thread 1
this is thread 1
this is thread 2
this is thread 2
this is thread 2
this is thread 2
this is thread 2
this is thread 2


The Output of the above stated example with “a.join()”:-

this is thread 1
this is thread 1
this is thread 1
this is thread 1
this is thread 1
this is thread 1
this is thread 1
this is thread 1
this is thread 1
this is thread 1
End Of Main Thread
this is thread 2
this is thread 2
this is thread 2
this is thread 2
this is thread 2
this is thread 2
this is thread 2
this is thread 2
this is thread 2
this is thread 2

Thread Safety In Java

Thread safety is avoiding thread interference.Thread interference is two or more threads executing a set of operations on the same data concurrently.This causes problem. To avoid this we should make sure that one thread runs at a time and not to allow another thread to run on the same data until it is finish.

This can be achieved in java by synchronization and from java1.5 there is a new way of doing this, that is Atomic actions also called as non blocking algorithms. 

synchronization can be achieved in 2 ways. one is synchronizing the methods and the other is using synchronized blocks.

synchronizing methods:-
synchronized keyword can only be used in front of the methods. The following is the example.

Example:-

public class SynchMethEx {

            private int counter;

           public synchronized void increase(){
                // do some operations and increse the counter
               //to the desired value
           }

          public synchronized void decrease(){
             // do some operations and decrease the counter
             //to the desired value
         }

        public synchronized int getCounter(){
             return counter;
        }
}

in this when a thread enters into one synchronized method of the class it achieves the intrinsic lock of that object so that any other thread cannot enter any of the synchronized methods of that class until the thread comes out of the synchronized method it entered. Once the thread comes out of the synchronized method and before it enters into another synchronized the lock on that object will be released so there is a chance that another thread can attain the lock and perform a synchronized method.

synchronizing the whole method will be a bottleneck for performance. Instead only synchronize the block which needs thread safety.

synchronized blocks:-

The synchronized blocks improves the performance by only synchronizing the block of code which is necessary. The following is the example.

Example:-

public class SynchBlock {

 public static void main(String[] args)throws Exception {
 
  Thread b=new Thread(new Kir(ThreadSync.class),"2");
  Thread c=new Thread(new Kir(ThreadSync.class),"3");
  Thread d=new Thread(new Kir(ThreadSync.class),"4");
 
 
  b.start();
  c.start();
  d.start();

 }

 
 private static class Kir implements Runnable{

         private Object obj;

        public Kir(Object obj){
            this.obj=obj;
       }

        public void run(){
             synchronized(obj){
                  int i=0;
                  while(true){
                     System.out.println("Thread"+Thread.currentThread().getName()+"@"+i);
                      if(i==100)break;
                     i++;
                 }//end of the while loop.
             }//end of the synchronized block.
       }//end of run method.
 }//end of the inner class.

}//end of the main class.

Before the thread enters into the synchronized block it has to obtain intrinsic lock on the object specified in the in the parentheses of the block definition(in the above example the lock on the object it has to attain is “obj”). Once it achieves the lock it will be able to execute the synchronized block. Once the thread is out of the synchronized block the lock on that particular object will be released so that another thread can attain a lock and can execute the synchronized block.

so the above two methods achieve thread safety but there is a problem. when one thread attained intrinsic lock on the object, The other threads that try to attain lock on the same object move to the runnable state and has to be rescheduled and also need to compete for the lock with the other threads who are waiting for the lock on the same object.

So java1.5 came with a solution called Atomic actions or Non Blocking Algorithms.  

Atomic Actions or Non Blocking Algorithms(Since java1.5):-

In concurrent programming an operation (or set of operations) is atomic, linearizable, indivisible or uninterruptible if it appears to the rest of the system to occur instantaneously.Atomicity is a guarantee of isolation from concurrent process. Additionally, atomic operations commonly have a succeed or fail definition — they either successfully change the state of the system, or have no apparent effect.

In programming, an atomic action is one that effectively happens all at once. An atomic action cannot stop in the middle: it either happens completely, or it doesn't happen at all. No side effects of an atomic action are visible until the action is complete.

An atomic action has to happen all at once or none. It is not that thread which is executing the atomic operation need not be in a running state until it completes the action. The atomic action ensures that the effects of it or seen only after the complete execution and if this detects the thread interference it does nothing. It ensures thread safety. It appears like all happened at once

For example the following are the steps involved in atomic operation:-

 Take the value from the shared variable.
  increment the value by one
  set the value back again to the shared variable.
 so the operation has to look like the complete operation had happened at once or instantaneously. so it follows the following algorithm.
 Take the value of the shared variable into another local variable(int i=j).
Add one to it and assign it to another variable(int k=i+1)
Now lock the shared variable(may be at hardware level) and check whether the shared variable still holds the value that it took at the beginning of the operation.
If it is the same then set the increased value(k) to the shared variable (j)  and release the lock so that other threads can perform operation on shared variable.
If it is not the same (suppose while these operations are happening another thread got it’s turn and changed the shared variable value) then nothing happens, it does not change the shared variable value and also releases the lock making the variable available to other threads for operating on it.
So the whole operation looks like it happened at once or not happened at all.

This is how it avoids thread interference and ensures thread safety.

Atomicity is commonly enforced by mutual exclusion, whether at the hardware level building on a cache coherency protocol, or the software level using semaphores or locks. Thus, an atomic operation does not actually occur instantaneously. The benefit comes from the appearance: the system behaves as if each operation occurred instantly, separated by pauses.

In computer science, compare-and-swap (CAS) is an atomic instruction used in multithreading to achieve synchronization. It compares the contents of a memory location to a given value and, only if they are the same, modifies the contents of that memory location to a given new value. This is done as a single atomic operation. The atomicity guarantees that the new value is calculated based on up-to-date information; if the value had been updated by another thread in the meantime, the write would fail. The result of the operation must indicate whether it performed the substitution; this can be done either with a simple Boolean response (this variant is often called compare-and-set), or by returning the value read from the memory location (not the value written to it).

In java
Reads and writes are atomic for reference variables and for most primitive variables (all types except long and double).
Reads and writes are atomic for all variables declared volatile (including long and double variables).

Since java1.5 Some of the classes in the package “java.util.concurrent” provide atomic methods that do not rely on synchronization.

Atomic variables:-

The “java.util.concurrent.atomic” package defines classes that support atomic operations on single variables. All classes have get and set methods that work like reads and writes on volatile variables. That is, a set has a happens-before relationship with any subsequent get on the same variable. The atomic compareAndSet method also has these memory consistency features, as do the simple atomic arithmetic methods that apply to integer atomic variables.

Example:-

import java.util.concurrent.atomic.AtomicInteger;

class AtomicCounter {
    private AtomicInteger c = new AtomicInteger(0);

    public void increment() {
        c.incrementAndGet(); //This is atomic operation. Internally uses CAS.
    }

    public void decrement() {
        c.decrementAndGet(); // this is atomic. Internally uses CAS.
    }

    public int value() {
        return c.get();
    }

}

The Atomic variables also contain CAS methods which perform Atomic operations.

Threads In Brief(java)

 when you want to concurrent tasks threads are the way in java to do it. Thread is a lightweight process which is part of the process. The threads can share memory but they run on their own stack. Every thread has a lifecycle. It will be in different states throughout its life cycle.

Thread Life Cycle:-




New State:-

when Thread object is created (Thread as=new Thread(new RunnableImpl)) it will be in new state. In this state the thread is not alive. From new state they move to runnable state.

Runnable State:-

From new state it moves to runnable state when start() method is called on the thread. Once the start() method is called on the thread,  the thread moves to runnable state. In this state the thread is ready to run and is waiting for the thread scheduler to give him a chance to run. In this state the thread is alive. when thread scheduler gives the thread a chance to run then it moves to running state.

Running State:-

Once the thread scheduler gives a chance to a thread that is in runnable state to run then it moves to running state. This is state that does some action. In this state the thread starts executing its task, that means it starts executing the threads “run()” method. As long as it is in this state it keeps executing until it dies. From this state thread can move back to runnable state or it moves to blocked state or it moves to dead state.

Blocked state:-

If the static method yield() is invoked on the thread the thread moves from running state to runnable state. If the static method sleep() is invoked on the thread then it moves to blocking state from running state for a certain period of time. If method wait() is called in the synchronized code then also the thread moves from running state to blocked state. If Thread has to wait for some input then also it moves to blocked state from running state. The thread is alive in this state.

Once the threads are out of blocked state they move to runnable state.

Dead State:-

If the thread finishes its execution, that means if it completes the “run()” method then it moves to a dead state. Once the thread is dead that cannot be started again but it can be accessed as a normal java object.

Thread priorities are not guaranteed. we can set the priorities but it is not guaranteed that the the thread scheduler gives high priority thread a chance to run immediately. It can pick up any thread. Thread scheduler is platform dependent. It may use different algorithms like “Round Robin” or “Time Slicing” for implementation.

Important Methods In Thread Class:-

 Thread.sleep(long millis):-

when this static method is called the currently executing thread moves to blocked state, i mean it sleeps for at least the specified amount of time. If this is called inside the synchronized code the thread goes to sleep without releasing the lock. It does not release the lock until it finishes the synchronized code.

Thread.yield():-

when this static method is called the currently executing thread moves to runnable state from running state.

Thread.join():-

The thread which executes “join()” method on another thread object will stop executing until the other thread on which “join()” is called finishes its execution, i mean until it is dead.

Thread.interrupt():-

Sends signal to thread to interrupt execution.

Inter Thread Communication:-

Threads communicate with each other by using the following methods that are declared inside the class “Object”. All these methods can be called only inside the synchronized code. Before calling this methods the thread has to attain intrinsic lock on that particular object.

 wait()
notify()
notifyAll()

wait():-

This causes the thread to move to waiting state(blocked state) until another thread notifies it. The thread releases the lock before it enters to blocked state. Here the thread enters to a pool of waiting threads on that particular object.

notiy():-

When this method is called on a particular object, it wakes up a single thread from the pool of threads waiting on that particular object. Choosing the thread is arbitrary.

notifyAll():-

When this method is called on a particular object, it wakes up all the threads in the pool waiting on that particular object.

Example for Inter communication:-

class Q {
   int n;
   boolean valueSet = false;
   synchronized int get() {
      if(!valueSet)
      try {
         wait();
      } catch(InterruptedException e) {
         System.out.println("InterruptedException caught");
      }
      System.out.println("Got: " + n);
      valueSet = false;
      notify();
      return n;
   }

   synchronized void put(int n) {
      if(valueSet)
      try {
         wait();
      } catch(InterruptedException e) {
         System.out.println("InterruptedException caught");
      }
      this.n = n;
      valueSet = true;
      System.out.println("Put: " + n);
      notify();
   }
}// end of class Q

class Producer implements Runnable {
   Q q;
   Producer(Q q) {
      this.q = q;
      new Thread(this, "Producer").start();
   }

   public void run() {
      int i = 0;
      while(true) {
         q.put(i++);
      }
   }
}

class Consumer implements Runnable {
    Q q;
    Consumer(Q q) {
       this.q = q;
       new Thread(this, "Consumer").start();
    }
    public void run() {
       while(true) {
       q.get();
    }
  }
}
public class PCFixed {

   public static void main(String args[]) {
      Q q = new Q();
      new Producer(q);
      new Consumer(q);
      System.out.println("Press Control-C to stop.");
   }
}

Guarded Blocks:-
 a block begins by polling a condition that must be true before the block can proceed.
For Example:-
public void guardedJoy() {
    // Simple loop guard. Wastes
    // processor time. Don't do this!
    while(!joy) {}
    System.out.println("Joy has been achieved!");
    // some more instructions goes here.
}

In the above the complete method is guarded by a polling condition. It makes sure the method does not get executed until the condition is met. Until some other thread sets the “joy” value to “false” the loop keeps polling. This also can be improved by Inter Thread Communication(wait, notify).

Thread Liveness:-

The notion that your program will not lock up and eventually do something useful is called the liveness property.

There are a number of reasons why a multi-threaded program will fail liveness:

      Deadlock
      Starvation and Live Lock

Deadlock:-

Both the threads wait for each other to release the resource for further processing is called deadlock.
Example:-

public class Deadlock {
    static class Friend {
        private final String name;
        public Friend(String name) {
            this.name = name;
        }
        public String getName() {
            return this.name;
        }
        public synchronized void bow(Friend bower) {
            System.out.format("%s: %s" + "  has bowed to me!%n",
            this.name, bower.getName());
            bower.bowBack(this);
        }
        public synchronized void bowBack(Friend bower) {
            System.out.format("%s: %s" + " has bowed back to me!%n",
                this.name, bower.getName());
        }
    }

    public static void main(String[] args) {
        final Friend alphonse = new Friend("Alphonse");
        final Friend gaston =  new Friend("Gaston");
        new Thread(new Runnable() {
            public void run() { alphonse.bow(gaston); }
        }).start();
        new Thread(new Runnable() {
            public void run() { gaston.bow(alphonse); }
        }).start();
    }
}

Deadlocks can be avoided by using Explicit locks which are introduced as part of the “java.util.concurrent.locks” package from java1.5.

Explicit Locks:-

Lock objects work very much like the implicit locks used by synchronized code. As with implicit locks, only one thread can own a Lock object at a time. Lock objects also support a wait/notify mechanism, through their associated Condition objects.

The biggest advantage of Lock objects over implicit locks is their ability to back out of an attempt to acquire a lock. The tryLock method backs out if the lock is not available immediately or before a timeout expires (if specified). The lockInterruptibly method backs out if another thread sends an interrupt before the lock is acquired.

solving deadlock using explicit locks:-

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.Random;

public class Safelock {
    static class Friend {
        private final String name;
        private final Lock lock = new ReentrantLock();

        public Friend(String name) {
            this.name = name;
        }

        public String getName() {
            return this.name;
        }

        public boolean impendingBow(Friend bower) {
            Boolean myLock = false;
            Boolean yourLock = false;
            try {
                myLock = lock.tryLock();
                yourLock = bower.lock.tryLock();
            } finally {
                if (! (myLock && yourLock)) {
                    if (myLock) {
                        lock.unlock();
                    }
                    if (yourLock) {
                        bower.lock.unlock();
                    }
                }
            }
            return myLock && yourLock;
        }
           
        public void bow(Friend bower) {
            if (impendingBow(bower)) {
                try {
                    System.out.format("%s: %s has" + " bowed to me!%n", this.name, bower.getName());
                    bower.bowBack(this);
                } finally {
                    lock.unlock();
                    bower.lock.unlock();
                }
            } else {
                System.out.format("%s: %s started"
                    + " to bow to me, but saw that"
                    + " I was already bowing to"
                    + " him.%n",
                    this.name, bower.getName());
            }
        }

        public void bowBack(Friend bower) {
            System.out.format("%s: %s has" +
                " bowed back to me!%n",
                this.name, bower.getName());
        }
    }

    static class BowLoop implements Runnable {
        private Friend bower;
        private Friend bowee;

        public BowLoop(Friend bower, Friend bowee) {
            this.bower = bower;
            this.bowee = bowee;
        }
   
        public void run() {
            Random random = new Random();
            for (;;) {
                try {
                    Thread.sleep(random.nextInt(10));
                } catch (InterruptedException e) {}
                bowee.bow(bower);
            }
        }
    }
           

    public static void main(String[] args) {
        final Friend alphonse =
            new Friend("Alphonse");
        final Friend gaston =
            new Friend("Gaston");
        new Thread(new BowLoop(alphonse, gaston)).start();
        new Thread(new BowLoop(gaston, alphonse)).start();
    }
}

Starvation:-

If the currently executing thread keeps on executing synchronized methods on the object and if it does block the other threads waiting for monitor lock on the same object for longer time is called starvation.

 Immutable Objects:-

 An object is considered immutable if its state cannot change after it is constructed. Maximum reliance on immutable objects is widely accepted as a sound strategy for creating simple, reliable code.
 Immutable objects are particularly useful in concurrent applications. Since they cannot change state, they cannot be corrupted by thread interference or observed in an inconsistent state.

Thread Safety:-

This can be achieved by avoiding thread interference. This can be done by synchronizing methods, synchronizing blocks and Atomic actions.

The java.util.concurrent package includes a number of additions to the Java Collections Framework which can be safely used in concurrent applications.

Annotations(java)


 Annotations are first introduced in java1.5. Annotation mean “a crucial explanatory note” added to anything. These are more powerful than java comments, javadoc comments.

Annotations have a number of uses, among them:

 Information for the compiler — Annotations can be used by the compiler to detect errors or suppress warnings.

Compiler-time and deployment-time processing — Software tools can process annotation information to generate code, XML files, and so forth.

Runtime processing — Some annotations are available to be examined at runtime.

Using annotations, we are able to add metadata information to our source code – build or deployment information, configuration properties, compilation behavior or quality checks.

Annotations can be retained at source code level, class level and runtime level. If the retention policy is specified as “source code” then the annotations will only be used by the compiler and they will not present in the class files. If the retention policy is “class” then the annotations will be present in class files but will not be used by VM. If the retention policy is “runtime” then they are also available at runtime which means the VM loads them.

Annotation is a kind of interface. 

Annotation Types have some differences compared to regular interfaces:
 Only primitives, strings, enums and arrays of them are allowed. Note that as Objects in general are not allowed, arrays of arrays are not allowed in Annotation Types (every array is an object).
The annotation elements are defined with a syntax very similar to that of methods, but keep in mind that modifiers and parameters are not allowed.
Default values are defined using the default keyword followed by the value that will be a literal, an array initializer or an enum value.

 All the annotations by default extends “java.lang.annotation.Annotation”. we are not manually allowed to extend an interface in annotations. This happens automatically like all classes extends “java.lang.Object” class by default.

Here while declaring annotation the Interface keyword is preceded by “@”. The declaration of Annotation is as follows.


public @interface Complexity {

    Level value(); // The return type Level is an Enum.
    String date();
    int currentRevision() default 1;
    String lastModified() default "N/A";
    String lastModifiedBy() default "N/A";
    // Note use of array
    String[] reviewers();

}

Single Value Annotations:-

There is a chance that an annotation can have only one element. In such a case that element should be named value.

To make the information in @Complexity appear in Javadoc-generated documentation, you must annotate the @Complexity definition itself with the@Documented annotation:

@Documented
@interface Complexity {

   // Annotation element definitions
 
}

Annotations can be applied to a program's declarations of classes, fields, methods, and other program elements.

@Author(
   name = "Benjamin Franklin",
   date = "3/27/2003"
)
class MyClass() { }
or
@SuppressWarnings(value = "unchecked")
void myMethod() { }

If there is just one element named "value," then the name may be omitted, as in:
@SuppressWarnings("unchecked")
void myMethod() { }

Also, if an annotation has no elements, the parentheses may be omitted, as in:
@Override
void mySuperMethod() { }

Annotations Used by the Compiler

There are three annotation types that are predefined by the language specification itself: 

@Deprecated, @Override, and @SuppressWarnings.

@Deprecated—the @Deprecated annotation indicates that the marked element is deprecated and should no longer be used. The compiler generates a warning whenever a program uses a method, class, or field with the @Deprecated annotation. When an element is deprecated, it should also be documented using the Javadoc @deprecated tag, as shown in the following example. The use of the "@" symbol in both Javadoc comments and in annotations is not coincidental — they are related conceptually. Also, note that the Javadoc tag starts with a lowercase "d" and the annotation starts with an uppercase "D".

  // Javadoc comment follows
    /**
     * @deprecated
     * explanation of why it
     * was deprecated
     */
    @Deprecated
    static void deprecatedMethod() { }
}

@Override—the @Override annotation informs the compiler that the element is meant to override an element declared in a superclass (overriding methods will be discussed in the the lesson titled "Interfaces and Inheritance").
  // mark method as a superclass method
   // that has been overridden
   @Override
   int overriddenMethod() { }

While it's not required to use this annotation when overriding a method, it helps to prevent errors. If a method marked with @Override fails to correctly override a method in one of its superclasses, the compiler generates an error.

@SuppressWarnings—the @SuppressWarnings annotation tells the compiler to suppress specific warnings that it would otherwise generate. In the example below, a deprecated method is used and the compiler would normally generate a warning. In this case, however, the annotation causes the warning to be suppressed.

  // use a deprecated method and tell
   // compiler not to generate a warning
   @SuppressWarnings("deprecation")
    void useDeprecatedMethod() {
        // deprecation warning
        // - suppressed
        objectOne.deprecatedMethod();
    }
Every compiler warning belongs to a category. The Java Language Specification lists two categories:

"deprecation" and "unchecked." The "unchecked" warning can occur when interfacing with legacy code written before the advent of generics (discussed in the lesson titled "Generics"). To suppress more than one category of warnings, use the following syntax:

@SuppressWarnings({"unchecked", "deprecation"})



The JDK comes with some annotations that are used to modify the behavior of the Annotation Types that we are defining:

@Documented: Indicates that the marked Annotation Type should be documented by Javadoc each time it is found in an annotated element.

@Inherited: Indicates that the marked Annotation Type is inherited by subclasses. This way, if the marked annotation is not present in a subclass it inherits the annotation in the superclass, if present. Only applies to class inheritance and not to interface implementations.

@Retention: Indicates how long the marked Annotation Type will be retained. Possible values are those of enum RetentionPolicy: CLASS (default – included in class files but not accessible at run-time), SOURCE (discarded by the compiler when the class file is created) and RUNTIME (available at run-time).

@Target: Indicates the element types to which the marked Annotation Type is applicable. Possible values are those of enum ElementType: ANNOTATION_TYPE, CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER and TYPE.

Processing Annotations:-

The Annotation Processor API

When Annotations were first introduced in Java 5, the Annotation Processor API was not mature or standardized. A standalone tool named apt, the Annotation Processor Tool, was needed to process annotations, and the Mirror API, used by apt to write custom processors, was distributed in com.sun.mirror packages.
Starting with Java 6, Annotation Processors were standardized through JSR 269 (2), incorporated into the standard libraries and the tool apt seamlessly integrated with the Java Compiler Tool, javac.

We can process the annotations using customs processors and can perform desired actions based on the annotations.

Anybody who writes custom annotation processor has to implement the interface “javax.annotation.processing.Processor” but java provides an abstract class which implements this interface making the developer job easy by providing implementation to most common methods. The abstract class name is “javax.annotation.processing.AbstractProcessor”. This class has an abstract method


“public abstract boolean process(Set<? extends TypeElement> annotations,    RoundEnvironment roundEnv)”

Parameters:
annotations - the annotation types requested to be processed
roundEnv - environment for information about the current and prior round

The annotation processing may happen in several rounds. RoundEnvironment provides the current round information.

All the classes, methods,variables that are annotated are treated as elements. The “RoundEnvironment.getElementsAnnotatedWith” method returns the annotated things as Elements. The Elements could be of kind annotation, class, constructor,enum, enum constant, field and so on.

The following is the example of a processor which process “Complexity” annotation to write a new source code file from the existing.

Enum class used in this example:-

public enum Level {

 SIMPLE, MEDIUM, COMPLEX;
}

Annotation used in this example:-

public @interface Complexity {
   Level value();
}

Class that will be processed in this example:-

@Complexity(Level.SIMPLE)
public class Person {

 @Complexity(Level.MEDIUM)
 public void move(){
 
 }

 @Complexity(Level.COMPLEX)
 public void drive(){
 
 }
}

The Processor which process the annotation:-

import java.io.BufferedWriter;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.tools.JavaFileObject;

/**
 * @author Muralidhar Yaragalla
 *
 */
@SupportedAnnotationTypes("annotate.Complexity")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class ComplexityProcessor extends AbstractProcessor{

 @Override
 public boolean process(Set<? extends TypeElement> annotations,
            RoundEnvironment roundEnv){
 
           for(Element elm:roundEnv.getElementsAnnotatedWith(Complexity.class)){
           //processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,elm.getSimpleName());
                   if (elm.getKind() == ElementKind.CLASS) {
                           TypeElement classElement = (TypeElement) elm;
                           PackageElement packageElement = (PackageElement) classElement.getEnclosingElement();
                           try{
                                    JavaFileObject jfo = processingEnv.getFiler().createSourceFile(classElement.getQualifiedName() + "info");

                                  BufferedWriter bw = new BufferedWriter(jfo.openWriter());
                                  bw.append("package ");
                                  bw.append(packageElement.getQualifiedName());
                                  bw.append(";");
                                  bw.newLine();
                                  bw.newLine();
                                 bw.flush();
                                bw.close();
                           }catch(Exception e){
       
                           }
                 }//end of if
        }//end of for
 
       return true;
 
     }

}

How this entire process works:-

The class files of the custom processor and its dependencies has to be packed in a jar file and this jar file should be in the classpath before compiling the source files(declared with annotations). Then when the compiler(javac) is invoked on the source files. It starts executing the Processor whenever it finds the source files with the registered annotation to that Processor. The Processor process the source files when compilation itself.

How to package the Processor:-

The jar file should contain a “META-INF” folder. Inside “META-INF” folder there should be a folder with name “services”. Inside “services” folder a file with name “javax.annotation.processing.Processor” has to be created. Inside this file the processors(Fully qualified name of the processor) have to be specified. One Processor in one line.

                                      

Remote Method Invocation (RMI)


 RMI is all about invoking methods of an object that resides in another JVM. So from one JVM we can invoke methods of an object that is in another JVM. The another JVM might be on the same machine or it could be somewhere else on the network. This is the basis for EJB.

In this the server (which has very high configuration and speed and rich in hardware) exposes the remote objects via RMI Registry. Clients fetches the remote object reference via a proxy object and executes the methods on remote machine and gets the return type given by the remote method to the client’s JVM and uses it for further processing.

The following is in detail:-

What Server does?:-

The server creates a remote object and exports it to the RMI environment, which means it creates a stub or proxy for the remote object and the stub will be binded in the RMI Registry with a name.

What Client does?-

It locates (connects) the RMI registry on the remote machine(server) and  performs a lookup operation with the name of the object. The lookup operations will download the stub class of the remote object and its state by which it will be able to create the same object in the clients machine and returns the stub object. With the help of this stub object we will be able to execute the remote object's methods and can obtain the result of the remote method which means client obtains the  return type of the remote method and this result will be used for further processing in the client.

Here on client and server machine when an object has to be downloaded first the class and the state  of that object will be downloaded which help rebuilding the same object with the same behaviour. The remote object always resides on the server and will never be downloaded by any client. The client only downloads the proxy or stub.

                       
                                 


Creating Remote Objects:-

First we have to create a remote interface by which we expose methods to the network. The remote interface is created by extending the “java.rmi.Remote”. Now the interface which extends the “java.rmi.Remote” interface have to declare methods that have to be exposed to the network. All the methods in the remote interface should throw “java.rmi.RemoteException”.



Example:-

package rmi.common;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface TaskEngine extends Remote{

 Boolean executeTask(Task t)throws RemoteException;

}

The return type or parameters of the remote method should be of primitive data types or remote objects or serializable classes.

Once we create the remote interface we need to provide implementation for that. So a class which implements the remote interface should be created. This class may contain additional methods other than the ones declared in the remote interface but these additional methods are local and will not be exposed to network(other JVM).

Example Implementation:-

package rmi.server;

import java.rmi.RemoteException;

import rmi.common.Task;
import rmi.common.TaskEngine;

public class TaskEngineImpl implements TaskEngine{

 @Override
 public Boolean executeTask(Task t)throws RemoteException {
           return t.execute();
 }
 
}

Server program:-

The server program will bind the remote object in the RMI Registry. The server program keeps waiting to listen to clients.. As long as the remote object is not unbound or as long as the client holds the reference to the remote object the remote object will not be garbage collected.

Example:-
package rmi.server;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

import rmi.common.TaskEngine;

public class Server {

    public static void main(String[]args)throws RemoteException{
          if (System.getSecurityManager() == null) {
                   System.setSecurityManager(new SecurityManager());
           }
           String name="taskExe";
           TaskEngine te=new TaskEngineImpl();
            TaskEngine stub =(TaskEngine) UnicastRemoteObject.exportObject(te, 0);
            Registry registry = LocateRegistry.getRegistry();
            registry.rebind(name, stub);
            System.out.println("TaskEngine bound");
    }
}

There are few things to be kept in mind when writing server program.

 The first thing is to set the security manager. If security manager is not set the files from the client system will not be downloaded as they can harm the computer by accessing the resources on the server computer. So the security manager has to be set.

remote object should be created and should be assigned to a variable of type remote interface.
The remote object needs to be passed to the “UnicastRemoteObject.exportObject(te, 0)” so that this method can create a stub and returns that. The stub should be held by the variable of remote interface data type. It also exports the required classes to the RMI environment.

The second argument in the “UnicastRemoteObject.exportObject(te, 0)” , an int, specifies which TCP port to use to listen for incoming remote invocation requests for the object. It is common to use the value zero, which specifies the use of an anonymous port. The actual port will then be chosen at runtime by RMI or the underlying operating system. However, a non-zero value can also be used to specify a specific port to use for listening. Once the exportObject invocation has returned successfully, the TaskEngineImpl remote object is ready to process incoming remote invocations.

using  “LocateRegistry.getRegistry()”  when no arguments passed we can get the RMI registry running on the same machine.

The methods of RMIRegistry such as bind, rebind, unbind can perform operations only on the registry running on the same machine. when these methods are invoked from a remote machine on the servers registry they don’t have any effect. so clients cannot bind or unbind the objects on server.

Client Program:-

package rmi.client;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import rmi.common.Task;
import rmi.common.TaskEngine;

public class Client {
        public static void main(String[] args)throws Exception {
                 if (System.getSecurityManager() == null) {
                       System.setSecurityManager(new SecurityManager());
                }
                Registry registry = LocateRegistry.getRegistry("localhost");
                TaskEngine te = (TaskEngine) registry.lookup("taskExe");
                 Task t=new HugeProcess();
                 if(te.executeTask(t)){
                       System.out.println("executed the task successfully on remote machine");
                  }

       }
}

Points that need to be observed when writing Client:-

 The first thing is to set the security manager if not already there on the system.
“registry.lookup("taskExe")” downloads the stub class, state of the stub object that is bound in the registry on the remote computer and creates the stub object and returns it to the variable of data type remote interface. Stub also implements all the interfaces implemented by remote object.

when “Task t=new HugeProcess()” invoked the Task object is created and when it is passed to the stub objects method as parameter, the server downloads the “HugeProcess” class, state and creates the task object back again on the server and executes the remote method on the server and the return value is passed to the client back again. Client used the return value of the remote method in further processing.

Remote Interface , any custom classes or interfaces provided as arguments and return types  to the remote methods should be made available to both client and server. In our example “TaskEngine”, “Task” should be made available to both server and client. The “Task” implementation “HugeProcess” should be only in the client, It does not need to be on the server.

Running Server and Client:-

First we need to create security policy files for client and server which are required by the security manager.

The client security policy for example “client.policy” has to be on the classpath of the clients machine and this policy file should grant all the permissions to the local code (classes which are not downloaded).

client policy file:-

grant codeBase "file:D:/workspace/example/bin/" {
    permission java.security.AllPermission;
};

Server policy file for example “server.policy” should be on the classpath of the servers machine as the server program security manager needs it.

servers policy:-

grant codeBase "file:D:/workspace/example/bin/" {
    permission java.security.AllPermission;
};

In both the policy files the “codeBase” should refer to the root folder where your class files are residing.

Once the policy files are set we should start the RMI registry on the servers machine. just type “rmiregistry” in the command prompt and that would run the register.


Running Server:- 

java -Djava.rmi.server.codebase=file:/D:/workspace/example/bin/
        -Djava.rmi.server.hostname=localhost
        -Djava.security.policy=server.policy
         rmi.server.Server

The above java command defines the following system properties:

 The java.rmi.server.codebase property specifies the location, a codebase URL, from which the definitions for classes originating from this server can be downloaded. If the codebase specifies a directory hierarchy (as opposed to a JAR file), you must include a trailing slash at the end of the codebase URL.

The java.rmi.server.hostname property specifies the host name or address to put in the stubs for remote objects exported in this Java virtual machine. This value is the host name or address used by clients when they attempt to communicate remote method invocations. By default, the RMI implementation uses the server's IP address as indicated by the java.net.InetAddress.getLocalHost API. However, sometimes, this address is not appropriate for all clients and a fully qualified host name would be more effective. To ensure that RMI uses a host name (or IP address) for the server that is routable from all potential clients, set thejava.rmi.server.hostname property.

The java.security.policy property is used to specify the policy file that contains the permissions you intend to grant.

Running Client:-

java     -Djava.rmi.server.codebase=file:D:/workspace/example/bin
           -Djava.security.policy=client.policy
            rmi.client.Client

The above java command defines the following system properties:

The location where the client serves its classes (the “HugeProcess” class) by using the java.rmi.server.codebase property

The java.security.policy property, which is used to specify the security policy file that contains the permissions you intend to grant to various pieces of code.

Difference between Byte Code and Class file


 when we compile a java source file it will be converted to a class file. The classes or interfaces written in the source file will be converted to bytecode and will be stored in the class file. The class file does not only contain byte code. It also contains some additional information which is useful to the compiler and virtual machine to compile and interpret the byte code.

For example when generic class is compiled the generic class will be converted to bytecode and will be stored in the class file. The byte code does not contain any information about generics but the class file which is generated from the source file does contain information about generics. This information is useful to the compiler when compiling other source files.

For Example:-

The source file which contains generic class:-
public class Person<T>{
   
       public T add(T a){
               System.out.println("happy");
       }
}


Generated Byte Code for the above class when compiled which is stored in the class file:-

public class Person{

         public Object add(Object a){
                    System.out.println("happy");
         }
}

The byte code will be stored in the class file and also the class file contains some additional information which is required by the compiler and virtual machine such as information about generics which are not really the part of Byte Code.

Generally VM need some additional information, which is usually stored at the top of the file (the file "header"), to know how to load and interpret the binary data in the file. Such header information could contain the generics details.

The process of erasing generics while compilation is called type erasure which is not very important to know in this context.