Thursday, September 4, 2014

Changing behavior of object at runtime.


annonymous innerclass

Inheritance is a very strong feature in java. Among other things it enables us to change behavior of objects at runtime. Lets consider an example.

Consider a class TextFormat having a method displayText(String msg). The method prints the text message that is passed as param without any formating.


package format;
public class TextFormat {
 public void print(String msg){
  System.out.println(msg);
 }
}

package format;
public class Client {
 public static void main(String[] args) {
  TextFormat tf = new TextFormat();
  tf.print("Testing the power of LATE BINDING");
 }
}
Output : Testing the power of LATE BINDING

A client can call the display method through the interface* TextFormat and see the message displayed on the console.

Note* : Interface in the above para is used as a generic term that defines the operations that a client of an api can perform. And it can mean a class or an interface.

Now the client wants the text to be displayed in a formatted manner say in lower case. But it does not want to change the interface and the method call.
That can be achieved through inheritance and the dynamic/late binding concept.
Note that the only change in the client code is at Line 10. And that can also be moved out of code to the configuration ( generally xml ) using IOC (Inversion of control) pattern. So, effectively the Client code remains untouched and the behavior change is also achieved.


package format;
public class LowerCaseTextFormatter extends TextFormat {
 @Override
 public void print(String msg) {
           System.out.println(msg.toLowerCase());
 }
}

package format;
public class Client {
 public static void main(String[] args) {
    TextFormat tf = new LowerCaseTextFormatter(); // LINE 10
    tf.print("Testing the power of LATE BINDING");
 }
}
Output : testing the power of late binding


Can we achieve such a behavior change without writing a new concrete implementation that extends TextFormat class ?

Consider the below case. We are able to change the behavior of print() method on the fly by creating a anonymous inner class. Although it is a local class and cant be reused outside its scope.


package format;

public class Client {
 
 public static void main(String[] args) {
  /* Changing behaviour of print method 
   * using Anonymous Inner Class
   */
  new TextFormat(){  
   @Override
   public void print(String msg) {
    System.out.println(msg.toLowerCase());
   }
  }.print("Testing the power of LATE BINDING");
 }
}
Output : testing the power of late binding

The compiler version of anonymous inner class does extend the TextFormat class.


Monday, September 1, 2014

How does JVM evaluate serialVersionUID if not provided explictly ?

If the programmer does not provide the serialVersionUID explicitly, then the jvm defaults the id to the hash* for that class. The serialVersionUID is a 64-bit (long type) hash of the class name, interface class names, methods, and fields.


private static final long serialVersionUID = 3487495895819393L;

hash* - The hash mentioned here does not refer to the one calculated from hashCode() method. 

Java api provides the utilities to evaluate the serialVersionUID. It may be evaluated 
a) programatically through the api exposed by java
b) through the utility 
serialver provided in the bin folder.


a) Programatically evaluating the serialVersionUID :  Java api provides class ObjectStreamClass, that can be used as below to evaluate the serialVersionUID of a class.
Here we are evaluating the serialVersionUID of the Person class.

We can tweak the class structure by adding/removing new fields,  interfaces, methods, changing access-modifiers etc and we can verify that the serialVersionUID changes.

import java.io.ObjectStreamClass;

public class EvaluateSerialVersionUID {

 public static void main(String[] args) {
  ObjectStreamClass osc = ObjectStreamClass.lookup(Person.class);
  System.out.println(osc.getSerialVersionUID());
 }
}

b) serialver.exe utility in the JDK bin directory : 

We can also use the serialver.exe utility to evaluate the SerialVersionUID in a serializable class.



import java.io.Serializable;
public class Test implements Serializable{
 String name;
 
 public Test(){}
 
 public Test(String name){
  this.name= name;
 }
}

Compile the Test class.
Open command prompt, change the directory to the JAVA_HOME/bin directory.
Run the below command. ( D:\Java_Workspace is path containing Test.class file ).

serialver -classpath D:\Java_Workspace -show





Enter the fully qualified class name and click show.




Sunday, August 31, 2014

Significance of serialVersionUid in serialization? What happens if we dint provide one explicitly?


What happens if the class definition changes between the serialization and the deserialization process ?
It might cause compatibility issues during deserialization process.

At a broad level below changes can happen in class definition between the process of serialization and deserialization :

1. New fields added - This does not lead to any loss of information during the process of deserialization. The new fields added will hold default values of their data type.

2. Fields removed - There is a certain loss of information in this case. Because the fields that are removed from interface (class in this case), there is no way to access those fields.

Let consider each example.

New fields added in class definition : 

In the class Person below, there are two fields name and age. The class implements Serializable interface. Also notice that there is no serialVersionUid defined explicitly which means the jvm will evaluate it using class definition and implicitly add it.

Lets create an object of Person and serialize it to person.ser file.

But before deserializing it, lets change the class definition by adding a new field say 'gender' of type String.

Now deserialize the person.ser file by uncommenting LINE 20 in below code (comment LINE 10). Notice that we get the incompatible serialVersionUid exception. This indicates that the jvm changes the default serialVersionUID with changes in the class definition. ( How JVM evaluates serialVersionUID? )

java.io.InvalidClassException: serialize.Person; local class incompatible: stream classdesc serialVersionUID = -2497583579111876693, local class serialVersionUID = 5759024017125419027

Can we avoid this exception and successfully deserialize the object ? Lets see in the next section.


public class Person implements Serializable{
 String name;
 int age;
  
 Person(String name, int age){
  this.name = name;
  this.age = age;
 }
 
 public static void main(String[] args) {
  Person p = new Person("Abhi", 28);
  SerializerHelper serHelper = p.new SerializerHelper();
  
  serHelper.serialPerson(p);     // LINE 10 - serialize
  //serHelper.deserialPerson();  // LINE 20 - deserialize
 }
 
 private class SerializerHelper{
  public void serialPerson(Person p){
   try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("person.ser")));){
    oos.writeObject(p);
   } catch (IOException e) {
    e.printStackTrace();
   }
  }

  public Person deserialPerson(){
   Person p = null; 
   try(ObjectInputStream oos = new ObjectInputStream(new FileInputStream(new File("person.ser")));){
    p = (Person)oos.readObject();
   } catch (IOException | ClassNotFoundException e) {
    e.printStackTrace();
   }
   return p;
  }
 }
}



The exception occurred because the jvm realized that the class for which object was serialized has changed. It was able to judge that from the mismatch in serialVersionUid.

Lets add the serialVersionUid explicitly in the Person class this time.

public class Person implements Serializable{
 // serialVersionUID added explictly
 private static final long serialVersionUID = 1L;
 String name;
 int age;

Follow the same steps :
Create a person Object, serialize it.
Add a new field to the class definition.
Now, without changing the serialVersionUid, deserialize the person.ser file.

Added new field in Person Class without changing the serialVersionUID
public class Person implements Serializable{
 // serialVersionUID added explictly
 private static final long serialVersionUID = 1L;
 String name;
 int age;
 String gender;

        ...
        
        public static void main(String[] args) {
  Person p = new Person("Abhi", 28);
  SerializerHelper serHelper = p.new SerializerHelper();
  
  //serHelper.serialPerson(p);
  Person p1 = (Person)serHelper.deserialPerson();
  System.out.printf("Deserialized person name=%s, age=%d, gender=%s ",p1.name, p1.age, p1.gender);
 }

Output : Deserialized person name=Abhi, age=28, gender=null 

The person.ser gets deserialized fine now.
Note that the newly added field 'gender' is having a default value null.


Fields removed from class definition :  ....  To be contd.

Monday, August 25, 2014

WeakReference, WeakHashMap


Understanding of references in java cannot really be accomplished without the understanding of Garbage Collector in java.

All the references created in java are by default Strong references. Lets try to understand with the help of an example what is so strong about a strong reference.

Strong reference :


 MyClass myObj = new MyClass();  


What above piece of code essentially does is creates a new object, allocates it on the heap. The strong reference myObj points to the object on the heap. The reference is strong in a sense that garbage collector can't reclaim the memory unless the reference is made null.




Weak Reference : 


WeakReference is an indirect way of referencing an object on heap.
When the referent referred by weakReference becomes null, the get() call on weakReference returns null.

A weakRef reference wraps the employee object and if the employee is made nullthe get() call on weakRef returns null and the employee object can be garbage collected.

Let try to find out the reasons as to why we need weak references in the first place. Lets consider below example.

We are creating instances of a class Employee and putting it in a HashMap.
Even though reference 'e' becomes null outside the for loop but the Employee objects are still reachable through employeeMap and will not be garbage collected. It can be verified that the size of map is 10,000 and contains the Employee objects.

 package heap;

import java.util.HashMap;
import java.util.Map;

public class OrdinaryHM{
 public static Map <Employee, Integer> employeeMap = new HashMap<Employee, Integer>();
 
 public static void main(String[] args) throws Exception{
  // Create multiple employee objects and store it in map
  Employee e = null;
  for (int i = 0; i < 10000; i++) {
   // Notice that e has a scope inside for loop only,
   // and will be null outside the loop
   e = new Employee();
   employeeMap.put(e, i);
  }
  /* Stop the application for 5 seconds to allow
   * garbage collector to do its work
   */
  Thread.sleep(5000);
  
  /* The size of Map is 10000 which means none of the employee object is garbage
   *  collected. Because they are still reachable through map 'employeeMap'
   */
  System.out.printf("Employee map size : %d ",employeeMap.size());
 }
}


Output : Employee map size : 10000

There might be scenarios where we might want to evict the entries from the map, when the actual references have become null.
Consider an example where many Observers have subscribed to a Observable. The Observable must maintain the references of all Observers in a collection. If some of the observers are made null, they will still be maintained in the collection because they are still reachable through the collection reference. Although there is no need to retain them in the collection. This is a memory leakage scenario which should be avoided.

This can be avoided using the WeakHashMap which is based upon WeakReference.

WeakHashMap solves the problem suggested above by making use of WeakReference internally.

  private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> 

As we can see in above snippet that the Entry class in WeakHashMap extends WeakReference. And also the key in the WeakHashMap is also a WeakReference. This means that the entries and key in the WeakHashMap are indirectly referred through referrent.

Let consider below example using WeakHashMap to store data.

  
package heap;

import java.util.Map;
import java.util.WeakHashMap;

public class WeakHMUsuage{
 public static Map<Employee, Integer> employeeMap = new WeakHashMap<Employee, Integer>();
 
 public static void main(String[] args) throws Exception{
  // Create multiple employee objects and store it in map
  Employee e = null;
  for (int i = 0; i < 10000; i++) {
   // Notice that e has a scope inside for loop only,
   // and will be null outside the loop
   e = new Employee();
   employeeMap.put(e, i);
  }
  /* Stop the application for 5 seconds to allow
   * garbage collector to do its work
   */
  Thread.sleep(5000);
  
  /* The size of Map is 5805 which means garbage collection is taking place. 
* As the elements are reachable through weak reference. */ System.out.printf("Employee map size : %d ",employeeMap.size()); } } Output : Employee map size : 5805


We can see here that the size of weakHashMap is reduced to 5805.

The size of map is not reduced to zero because GC works on its own terms and conditions and when it feels suitable.








Tuesday, August 19, 2014

Why not to store sensitive data like password in String objects.


The String class in java in immutable which means that once a String object is created, it can't be removed or modified from the Heap. It can only be removed in the next garbage collector cycle if the reference was made null.

What this means is that the object is available on the heap unless it is garbage collected. That means the sensitive information in the String object will be exposed to anyone having the access to the heap dump.

Lets create some String objects, take a heap dump and see the sensitive data.
The below code iterates the for loop 100 times and adds sensitive strings in the String array.

 
package heap;
public class WhyNotToSaveSenstiveDataInString {
 public static void main(String[] args) {
  String password = "MyConfidentialPassword";
  String passArr [] = new String [100];
  for (int i = 0; i < passArr.length; i++) {
   passArr[i] = password.concat(String.valueOf(i));
  }
  while(true){}
 }
}


Notice, that we have kept the application up by putting a infinite while loop. We will use the visualvm tool to take the heap dump.
Go to java bin directory and start jvisualvm.exe.






Once started, we can see our application in the sidebar. Right click it, and select Heap Dump. We can see heap dump as below. We can see the sensitive information highlighted in yellow. This information is exposed to anyone having the access to the heap dump and hence can be a compromise with the security.
One can also use OQL (object query language) to dig in more precise information.



The issue with String is that once a sensitive information is stored in it,it can't be changed programmatically. One becomes completely dependent on the next garbage collection cycle which can reclaim it only if the reference was made null.

The better option is to use a char [] to store sensitive data. Because as soon as we have used the data, we can reset the char[] with junk characters. This reduces the dependence of the security on garbage collector.

 
char[] charPassword = new char[]{'C','o','n','f','i','d','e', 'n','t','i','a', 'l'};
// Do some computation

//Fill the char [] with junk data so that the senstive information is erased
Arrays.fill(charPassword, '0');

for (int i = 0; i < charPassword.length; i++)
 System.out.print(charPassword[i]);

Output : 000000000000

Also, printing the char[] object to the console/log wont print the value of the sensitive data.

 
String strPassword = "Confidential";
char[] charPassword = new char[]{'C','o','n','f','e','d','e', 'n','t','i','a', 'l'};
System.out.println("String password: " + strPassword);
System.out.println("Character password: " + charPassword);

String password: Confidential
Character password: [C@15db9742

One can be even more careful and use the confidential data in encrypted form rather than using clear text.