Saturday, 4 May 2019

Volatile keyword, Synchronized keyword and Lock interface

Volatile

Marking a member variable as volatile, makes sure, when ever the member variable is accessed, its value is always read from the main memory rather than the cache which is associated to that specific thread.

Lets consider, if thread T1 and thread T2 are spawned from the same object, then all member variables will be shared between the threads T1 and T2. Each thread will store the values of these member variables in their cache in order to increase performance (hitting the cache is always quicker than accessing the main memory). 

So if the thread T2 changes the value of xyz (which is ideally a shared variable between T1 and T2), but the change would not be reflected in T1 cache. Thread T1 would continue reading an older value and hence have an inconsistent state of xyz.

Marking a variable as volatile, makes sure that threads will always lookup the value of the shared variable from the main memory rather their cache, hence avoiding inconsistent states.

If we are working on a member variable xyz marked as volatile, and we perform a multi-step operation like xyz++. This will result in inconsistent read. Reason being, the update being performed on xyz in the main memory will be in 2 steps, rather than a single step. So if T1 is updating xyz through xyz++, and meanwhile T2 reads the value of xyz, it might read an inconsistent copy of xyz.

If we are working on a 32 bit OS, then variables with data types Long and Double marked as volatile will not work as expected. Reason is Long and Double use 64 bit of memory (2- 32 bit memory places would be utilized). If thread T1 and T2 are accessing a volatile Long xyz, and T1 updates xyz, the update would have in two steps rather than a single step. And T2 reads xyz during this update, then T2 might get an inconsistent value. 

Based on above two examples, we should use volatile with caution depending on our use case.

Synchronization keyword

Synchronization keyword has a different use case in a concurrent environment as compared to volatile. Synchronized keyword ensure, mutual exclusion on a piece of code, which means only a single thread will have access to the piece of code wrapped under the synchronized keyword.

We can say that, synchronization keyword acts like a guarded block only allowing a single thread access to avoid race conditions from happening.

Synchronization works in acquiring a lock on the objects monitor. And threads which are accessing the guarded block are either spawned from this object or the object is shared (member variable) among all the threads.

Synchronization is re-entrant in nature, which means, if the thread has acquired access to a synchronized block through a objects monitor, then the thread can further go and access more synchronized blocks using the same object monitor.

Synchronization keyword can be used either by acquiring the class monitor or by objects monitor.

The class monitor is acquired if the synchronized keyword is used along with static methods, static blocks. Using this locking, only one thread will have access to the guarded block, irrespective from what ever object the thread was spawned from with in that JVM instance.

The object monitor is acquired if the synchronized keyword is used along with non static methods of on piece of code with in a method, referred to as synchronized blocks. Point to be kept in mind, if we don't have a guarantee, that the threads that are going to access the guarded block are spawned from the same thread, then avoid using the keyword this to acquire the monitor. Use an object which would be shared among all threads to acquire the monitor.

Its always better to only put the code of lines that can actually bring out race condition, rather than marking the whole method as synchronized. The more the synchronization, more the wait time for threads.

Note: Synchronization and volatile keywords make sure happens-before relationship is not violated, which is the crux of multi-threading

Lock Interface 

Lock implementations provide more extensive locking operations than can be obtained using synchronized methods and statements. They allow more flexible structuring, may have quite different properties, and may support multiple associated Condition objects.

Key difference between Lock and synchronized keyword
  • synchronized block is fully contained within a method – we can have Lock API’s lock() and unlock() operation in separate methods
  • A synchronized block doesn’t support the fairness, any thread can acquire the lock once released, no preference can be specified. We can achieve fairness within the Lock APIs by specifying the fairness property. It makes sure that longest waiting thread is given access to the lock
  • A thread gets blocked if it can’t get an access to the synchronized blockThe Lock API provides tryLock() method. The thread acquires lock only if it’s available and not held by any other thread. This reduces blocking time of thread waiting for the lock
  • A thread which is in “waiting” state to acquire the access to synchronized block, can’t be interrupted. The Lock API provides a method lockInterruptibly() which can be used to interrupt the thread when it’s waiting for the lock
Lock provides implementation like ReentrantLock and ReentrantReadWriteLock.

Monday, 15 April 2019

JRocket :: Java Memory Model

Java objects reside in an area called the heap. The heap is created when the JVM starts up and may increase or decrease in size while the application runs. When the heap becomes full, garbage is collected. During the garbage collection objects that are no longer used are cleared, thus making space for new objects.
Note that the JVM uses more memory than just the heap. For example Java methods, thread stacks and native handles are allocated in memory separate from the heap, as well as JVM internal data structures.
The heap is sometimes divided into two areas (or generations) called the nursery (or young space) and the old space. The nursery is a part of the heap reserved for allocation of new objects. When the nursery becomes full, garbage is collected by running a special young collection, where all objects that have lived long enough in the nursery are promoted (moved) to the old space, thus freeing up the nursery for more object allocation. When the old space becomes full garbage is collected there, a process called an old collection.
The reasoning behind a nursery is that most objects are temporary and short lived. A young collection is designed to be swift at finding newly allocated objects that are still alive and moving them away from the nursery. Typically, a young collection frees a given amount of memory much faster than an old collection or a garbage collection of a single-generational heap (a heap without a nursery).

Sunday, 14 April 2019

Memory Leaks

One of the core benefits of Java is the JVM, which is an out-of-the-box memory management. Essentially, we can create objects and the Java Garbage Collector will take care of allocating and freeing up memory for us. Nevertheless, memory leaks can still occur in Java applications.

What is a Memory Leak in Java?

A scenario that occurs when objects are no longer being used by the application, but the Garbage Collector is unable to remove them from working memory – because they’re still being referenced. 
A memory leak is bad because it blocks memory resources and degrades system performance over time. And if not dealt with, the application will eventually exhaust its resources, finally terminating with a fatal java.lang.OutOfMemoryError.
Symptoms of memory leak are as below:
  • Severe performance degradation when the application is continuously running for a long time
  • OutOfMemoryError heap error in the application
  • Spontaneous and strange application crashes
  • The application is occasionally running out of connection objects

Types of Memory Leaks in Java

Static Field Holding On to the Object Reference

In Java, static fields have a life that usually matches the entire lifetime of the running application(unless ClassLoader becomes eligible for garbage collection).

eg public static final ArrayList<Double> list = new ArrayList<Double>(1000000);

Prevention

  • Minimize the use of static variables
  • When using singletons, rely upon an implementation that lazily loads the object instead of eagerly loading

Through un-closed Resources and un-closed Connections

Prevention

  • Always use finally block to close resources
  • The code (even in the finally block) that closes the resources should not itself have any exceptions
  • When using Java 7+, we can make use of try-with-resources block

 Improper equals() and hashCode() Implementations

When defining new classes, a very common oversight is not writing proper overridden methods for equals() and hashCode() methods.
HashSet and HashMap use these methods in many operations, and if they’re not overridden correctly, then they can become a source for potential memory leak problems.

Calling String.intern() on Long String

The Java String pool had gone through a major change in Java 7 when it was transferred from PermGen to HeapSpace. But for applications operating on version 6 and below, we should be more attentive when working with large Strings.
If we read a huge massive String object, and call intern() on that object, then it goes to the string pool, which is located in PermGen (permanent memory) and will stay there as long as our application runs. This blocks the memory and creates a major memory leak in our application.

Prevention

  • The simplest way to resolve this issue is by upgrading to latest Java version as String pool is moved to HeapSpace from Java version 7 onwards
  • If working on large Strings, increase the size of the PermGen space to avoid any potential OutOfMemoryErrors

How to Find Leaking Sources in Your Application

Verbose Garbage Collection

One of the quickest ways to identify a memory leak is to enable verbose garbage collection.
By adding the -verbose:gc parameter to the JVM configuration of our application, we’re enabling a very detailed trace of GC. Summary reports are shown in default error output file, which should help you understand how your memory is being managed.

 Do Profiling

The second technique is the one we’ve been using throughout this article – and that’s profiling. The most popular profiler is Visual VM – which is a good place to start moving past command-line JDK tools and into lightweight profiling.

Review Your Code

Simply put – review your code thoroughly, practice regular code reviews and make good use of static analysis tools to help you understand your code and your system.
Finally, this is more of a general good practice than a specific technique to deal with memory leaks.

Java 8 Streams.... Are ParallelStreams always effective?

Consider the following 4 points before going for parallel streams:
  • Splitting / decomposition costs :: Sometimes splitting is more expensive than just doing the work!
  • Task dispatch / management costs :: Can do a lot of work in the time it takes to hand work to another thread
  • Result combination costs :: Sometimes combination involves copying lots of data. For example, adding numbers is cheap whereas merging sets is expensive.
  • Locality :: You should consider cache misses, if a CPU waits for data because of cache misses then you wouldn't gain anything by parallelization. That's why array-based sources parallelize the best as the next indices (near the current index) are cached and there are fewer chances that CPU would experience a cache miss.

In simpler words, go for parallelStream if and only if

  • I have a massive amount of items to process (or the processing of each item takes time and is parallelizable)
  • I have a performance problem in the first place
  • I don't already run the process in a multi-thread environment (for example: in a web container, if I already have many requests to process in parallel, adding an additional layer of parallelism inside each request could have more negative than positive effects)
Also note a relatively simple formula to determine a chance of parallel speedup.

NQ Model:
N x Q > 10000
where, N = number of data items and Q = amount of work per item

String, StringBuilder and StringBuffer


Equality

String overrides the equal method, but StringBuilder and StringBuffer don't.

So when a Str reference does an equal check with a reference of either a StringBuilder or a StringBuffer, it will always fail, irrespective, if all references are referring to a same value.

If you really want to check for equality, always use the toString() method on the StringBuilder and StringBuffer references

Demonstrated on below github link.

https://github.com/omerhashmininjago/java-programs/tree/master/src/main/java/com/demonstrate/concepts/string/example2

Concatenation

When a String reference is passed to a method, and we perform a concatenation, the reference with in the method would point to another object, but the original string reference will continue to point to the older object. This is because String is Immutable

This concept will not work for StringBuidler and StringBuffer as they are Mutable, the original reference will point to the newly created object.

Demonstrated on below github link
https://github.com/omerhashmininjago/java-programs/tree/master/src/main/java/com/demonstrate/concepts/string/example3

Thread Safe

When working in a single threaded environment


  • String to be used when we are sure that the string in question is not going to changed
  • StringBuilder to be used, when the string is going to go through lots of changes and we would be using a single thread. StringBuilder is not thread safe
  • StringBuffer to be used, when we would have multiple threads accessing the same string reference and we would need to be sure happens-before relationship is not violated



Friday, 12 April 2019

Asymptotic Notations

The analysis of algorithms is the determination of the computational complexity of algorithms, that is the amount of time, storage and/or other resources necessary to execute them

Each algorithm when laid down, can be represented by a formula to represent the amount of time needed for the execution of the lines of code contained in that algorithm.

This formula can contain details which are important with respect to computing time, or contain details which might be insignificant while computing the time. We can ignore such insignificant details from the formula. These trivial details are usually constants or a variable part which is insignificant when compared to another variable in the same equation, for eg T(n) = 4n^2 +5n + 3. The 3 being a constant can be removed. Leaving T(n) = 3n^2 + 5n. Now when we compare 5n to 4n^2, for large values of n, the 5n would not be of any significance when compared to the value of 4n^2. So for any value of n, we ignore this insignificant component of the formula, thus leaving T(n) = 4n^2. Now, here again, 4 is a constant, and thus becomes insignificant while considering the time complexity. Thus leaves us with T(n) = n^2 which in fact is the component which drives the complexity of an algorithm.

The Big-O Notation is the way we determine how fast any given algorithm is when put through its paces 
or
Big O notation is used to describe the performance or complexity of an algorithm.

The three notations used to represent the growth of any algorithm, as input increases

Big Theta (tight bounds)

When we say tight bounds, we mean that the time complexity represented by the Big-Θ notation is like the average value or range within which the actual time of execution of the algorithm will be.
For example, if for some algorithm the time complexity is represented by the expression 3n2 + 5n, and we use the Big-Θ notation to represent this, then the time complexity would be Θ(n2), ignoring the constant coefficient and removing the insignificant part, which is 5n.
Here, in the example above, complexity of Θ(n2) means, that the average time for any input n will remain in between, x1 * n^2 and x2 * n^2 where x1,x2 are two constants, thereby tightly binding the expression representing the growth of the algorithm.

Big O (Upper bound)

This notation is known as the upper bound of the algorithm, or a Worst Case of an algorithm and can be used to describe the execution time required or the space used (e.g. in memory or on disk) by an algorithm.
It tells us that a certain function will never exceed a specified time for any value of input n.
The question is why we need this representation when we already have the big-Θ notation, which represents the tightly bound running time for any algorithm. Let's take a small example to understand this.
Consider Linear Search algorithm, in which we traverse an array elements, one by one to search a given number.
In Worst case, starting from the front of the array, we find the element or number we are searching for at the end, which will lead to a time complexity of 'n', where 'n' represents the number of total elements.
But it can happen, that the element that we are searching for is the first element of the array, in which case the time complexity will be '1'.
Now in this case, saying that the big-Θ or tight bound time complexity for Linear search is Θ(n), will mean that the time required will always be related to 'n', as this is the right way to represent the average time complexity, but when we use the big-O notation, we mean to say that the time complexity is O(n), which means that the time complexity will never exceed 'n', defining the upper bound, hence saying that it can be less than or equal to 'n', which is the correct representation.
This is the reason, most of the time you will see Big-O notation being used to represent the time complexity of any algorithm, because it makes more sense.

Big Omega (Lower bound)


Big Omega notation is used to define the lower bound of any algorithm or we can say the best case of any algorithm.
This always indicates the minimum time required for any algorithm for all input values, therefore the best case of any algorithm.
In simple words, when we represent a time complexity for any algorithm in the form of big-Ω, we mean that the algorithm will take at least this much time to complete it's execution. It can definitely take more time than this too.

Monday, 8 April 2019

Integer Cache

Where does Java store Integers and other Wrapper classes? Its always the heap. But, Integer.valueOf(100) will always return the same instance but Integer.valueOf(200) will always return a new instance. Why this difference.

There is an IntegerCache in java.lang.Integer which stores instances for values -128 though 127. This means that Integer.valueOf(17) always will return the very same instance, while Integer.of(200) will not. While this clearly has the advantage of reuse of commonly used Integer values which results in better performance, thus relieving the GC from some work, it also has implications for autoboxing and identity comparisons.

The boundaries of this IntegerCache can be changed using  -XX:AutoBoxCacheMax=  <new value>.

The cache always has these 256 Integer values closest to 0 pre-filled rather than populating it on demand. So if the boundaries are tweaked, then this could impact memory consumption.

Tuesday, 19 February 2019

Iterator

Iterator is a universal iterator as we can apply it to any Collection object. By using Iterator, we can perform both read and remove operations. It is improved version of Enumeration with additional functionality of remove-ability of a element.

Iterator object can be created by calling iterator() method present in Collection interface.

Iterator has four method for traversal. hasNext(), next(), remove() and forEachRemainin()
ListIterator is only applicable for List collection implemented classes like arraylist, linkedlist etc. It provides bi-directional iteration.
ListIterator must be used when we want to enumerate elements of List. This cursor has more functionality(methods) than iterator.
ListIterator object can be created by calling listIterator() method present in List interface.
ListIterator has six additional methods for traversal. hasPrevious(). previous(), add(E e), nextIndex(), previousIndex() and set(E e)

Fail-Fast Iterators


Fail-Fast systems abort operation as-fast-as-possible exposing failures immediately and stopping the whole operation.

Fail-fast iterators in Java don’t play along when the underlying collection gets modified.
  • Collections maintain an internal counter called modCount. Each time an item is added or removed from the Collection, this counter gets incremented.
  • When iterating, on each next() call, the current value of modCount gets compared with the initial value. If there’s a mismatch, it throws ConcurrentModificationException which aborts the entire operation.
  • Default iterators for Collections from java.util package such as ArrayListHashMap, etc. are Fail-Fast.

The Fail-Fast behavior isn’t guaranteed to happen in all scenarios as it’s impossible to predict behavior in case of concurrent modifications. These iterators throw ConcurrentModificationException on a best effort basis.
If during iteration over a Collectionan item is removed using Iterator‘s remove() method, that’s entirely safe and doesn’t throw an exception.However, if the Collection‘s remove() method is used for removing an element, it throws an exception.

Please see demonstration of fail fast iterator on below github link
https://github.com/omerhashmininjago/java-programs/tree/master/src/main/java/com/demonstrate/concepts/collections/iterator/example1

Lets consider an example of using an Iterator over an ArrayList

1. The ArrayList extends a class known as a AbstractList and it also implements List
2. The AbstractList contains in itself a protected transient int variable named modCount
3. As we add and remove elements, this variable is accordingly updated
4. When we call the iterator() on the ArrayList, it internally creates an instance of a Subclass Itr (implementation of Iterator and an inner class to AbstractList) which stores the value of modCount (at that point when iterator() was called) in a local Variable named expectedModCount
5. So the iterator before performing any action, compares the expectedModCount to the ModCount and accordingly actions  

Fail-Safe Iterators

These iterators create a clone of the actual Collection and iterate over it. If any modification happens after the iterator is created, the copy still remains untouched. Hence, these Iterators continue looping over the Collection even if it’s modified.


However, it’s important to remember that there’s no such thing as a truly Fail-Safe iterator. The correct term is Weakly Consistent.
That means, if a Collection is modified while being iterated over, what the Iterator sees is weakly guaranteed. This behavior may be different for different Collections and is documented in Javadocs of each such Collection.
The Fail-Safe Iterators have a few disadvantages, though:
  1. One disadvantage is that the Iterator isn’t guaranteed to return updated data from the Collection, as it’s working on the clone instead of the actual Collection.
  2. Another disadvantage is the overhead of creating a copy of the Collection, both regarding time and memory.

Iterators on Collections from java.util.concurrent package such as ConcurrentHashMapCopyOnWriteArrayList, etc. are Fail-Safe in nature.

Please see demonstration of fail safe iterator on below github link
https://github.com/omerhashmininjago/java-programs/tree/master/src/main/java/com/demonstrate/concepts/collections/iterator/example2

Lets consider an example of CopyOnWriteArrayList

1. The CopyOnWriteArrayList does not extend the AbstractList but directly implements List
2. When the iterator() method on this collection is called, it created a new instance of an COWIterator (inner class to CopyOnWriteArrayList and implementation of ListIterator) and stores a copy (snapshot at that point of time) of the underlying array i.e. Object[] array which the ArrayList uses internally to store the elements
3. Then all operations of the iterator are performed on this snapshot and not on the actual collection 

Comparable and Comparator

Comparable

Comparable implementations provide a natural ordering for a class, which allows objects of that class to be sorted automatically. 

While sorting Collections, the Collection Framework gives us an algorithm which does the natural sorting for us.
Collections.sort(l);
Lets say if we have a Collection<Name> list = new ArrayList<>() and Name does not implement Comparable, then Collections.sort(list) will throw a ClassCastException.

The sort() method provided by the Collections class is to be only used when the elements of the collection can be compared

Writing Your Own Comparable Types

The Comparable interface consists of the following method.

public interface Comparable<T> {
    public int compareTo(T o);
}

The compareTo method compares the receiving object with the specified object and returns a negative integer, 0, or a positive integer depending on whether the receiving object is less than, equal to, or greater than the specified object. If the specified object cannot be compared to the receiving object, the method throws a ClassCastException.

Points to remember when we are implementing Comparable - this will make lives easier for a developer

1. Try and make sure the Class is Immutable
2. Make sure the Constructor is checking on NPE - throw NPE sooner the better
3. Override hashcode and equals - to make sure the contract is in place
4. Override toString so that the object is printed in human readable form

Refer to this github link for demonstration
https://github.com/omerhashmininjago/java-programs/tree/master/src/main/java/com/demonstrate/concepts/collections/comparable/example1

Using Comparable interface, we can sort the elements of:
  1. String objects
  2. Wrapper class objects, for example Integer, Long etc
  3. User defined custom objects (Preferably Immutable objects)
To reverse the order of sorting, you can the method provided by the Collections class - reverseOrder(); This utility method returns a Comparator that imposes the reverse of the natural ordering on a collection of objects that implement the Comparable interface.

What if you want to sort some objects in an order other than their natural ordering? Or what if you want to sort some objects that don't implement Comparable and you dont have access to its source code?

Comparator

To do either of the above things, you'll need to provide a Comparator — an object that encapsulates an ordering. Like the Comparable interface, the Comparator interface consists of a single method.

public interface Comparator<T> {
    int compare(T o1, T o2);
}

The compare method compares its two arguments, returning a negative integer, 0, or a positive integer depending on whether the first argument is less than, equal to, or greater than the second. If either of the arguments has an inappropriate type for the Comparator, the compare method throws a ClassCastException.

Much of what was said about Comparable applies to Comparator as well. Writing a compare method is nearly identical to writing a compareTo method, except that the former gets both objects passed in as arguments. The compare method has to obey the same four technical restrictions as Comparable's compareTo method for the same reason — a Comparator must induce a total order on the objects it compares.

Please have a look at the example demonstrated on the below github link

https://github.com/omerhashmininjago/java-programs/tree/master/src/main/java/com/demonstrate/concepts/collections/comparator/example1

 Comparator Vs Comparable

The Comparable interface is a good choice when used for defining the default ordering or, in other words, if it’s the main way of comparing objects.
Then, we must ask ourselves why use a Comparator if we already have Comparable?
There are several reasons why:
  • Sometimes, we can’t modify the source code of the class whose objects we want to sort, thus making the use of Comparable impossible
  • Using Comparators allows us to avoid adding additional code to our domain classes
  • We can define multiple different comparison strategies which isn’t possible when using Comparable

Monday, 18 February 2019

Cloneable

Cloning is a process of creating an exact copy of an existing object in the memory. 

In java,clone() method of java.lang.Object class is used for cloning process. This method creates an exact copy of an object on which it is called through field-by-field assignment and returns the reference of that object. 

Not all the objects in java are eligible for cloning process. The objects which implement Cloneable interface are only eligible for cloning process. Cloneable interface is a marker interface which is used to provide the marker to cloning process.


Shallow Copy vs Deep Copy

It’s very simple that if the object has only primitive fields or Immutable fields, then obviously you will go for shallow copy but if the object has references to other objects, then based on the requirement shallow copy or deep copy should be chosen. What I mean here is, if the references are not modified anytime, and then there is no point in going for deep copy. You can just opt shallow copy. But if the references are modified often, then you need to go for deep copy. Again there is no hard and fast rule; it all depends on the requirement.

Shallow Copy

Whenever we use default implementation of clone method we get shallow copy of object means it create new instance and copy all the field of object to that new instance and return it as object type we need to explicitly cast it back to our original object. This is shallow copy of the object. clone() method of the object class support shallow copy of the object. If the object contains primitive as well as non-primitive or reference type variable In  shallow copy, the cloned object also refers to the same object to which the original object refers as only the object references gets copied and not the referred objects themselves. That's why the name shallow copy or shallow cloning in Java. If only primitive type fields or Immutable objects are there then there is no difference between shallow and deep copy in Java.

https://github.com/omerhashmininjago/java-programs/tree/master/src/main/java/com/demonstrate/concepts/cloneable/example1

Deep Copy


Whenever we need our own meaning of a copy and don't use default implementation we call it as deep copy, whenever we need deep copy of the object we need to implement it according to our need. So for deep copy we need to ensure all the member class also implement the Cloneable interface and override the clone() method of the object class. After that we override the clone() method in all those classes even in the classes where we have only primitive type members otherwise we would not be able to call the protected clone() method of Object class on the instances of those classes inside some other class. It’s typical restriction of the protected access. 


https://github.com/omerhashmininjago/java-programs/tree/master/src/main/java/com/demonstrate/concepts/cloneable/example2


How to implement Deep Copy?


The first and foremost way is already mentioned in the above github link. There are a couple of drawbacks of using this approach


  1. Every Reference class needs to implement Cloneable and override the clone method
  2. What if the class has final fields (they are only initialized through Constructor) and clone does not call the constructor
  3. If a class is implementing Clonebale, then all its superclasses also need to define the clone method or inherit it form their parents, else super.clone() will fail


If you dont want to go this route then there are two ways on you can create a Deep Copy

  1. Creating your own implementation
  2. Using an external Library

Creating your own Implementation

  1. Serialization
    We can serialize the object and then deserialize it, this would give us the copy of the original object, but this also has drawbacks
    1. still need to implement Serializable
    2. Wont be able to modify final fields
    3. Serialization process is slower than cloning

      https://github.com/omerhashmininjago/java-programs/tree/master/src/main/java/com/demonstrate/concepts/cloneable/example4
  2. Copy Constuctor
    This overcomes every design issue that comes with calling the clone method.Here we dont even need to implement any interface

    https://github.com/omerhashmininjago/java-programs/tree/master/src/main/java/com/demonstrate/concepts/cloneable/example3

Using an external Library

We can also opt for external libraries like below
  • BeanUtils.cloneBean(object) - this creates a shallow clone similar to Object.clone()
  • SerializationUtils.clone(object) - this created a deep clone; but all classes need to implement Serializable

    https://github.com/omerhashmininjago/java-programs/tree/master/src/main/java/com/demonstrate/concepts/cloneable/example5

Serialization


To Serialize an object means, to convert its state to a byte stream (which can be moved over a network, persisted on a file drive, persisted in a Data base) so that the byte stream can be reverted back into a copy of the object. A Java object is Serializable  if its class or any of its superclasses implements the Serializable interface or its subinterface i.e. the Externalizable.

Classes that do not implement this interface will not have any of their state serialized or deserialized. All subtypes of a serializable class are themselves serializable. 

The serialization interface has no methods or fields and serves only to identify the semantics of being serializable.
The default serialization mechanism for an object writes 

  • the class of the object
  • the class signature
  • the values of all non-transient and non-static fields - this includes references to other objects (except in transient or static fields) to be written also (only if they are implementing Serializable interface or its subinterface)

Multiple references to a single object are encoded using a reference sharing mechanism so that graphs of objects can be restored to the same shape as when the original was written. 

Deserialization is the process of converting the serialized form of an object back into a copy of the object.

 What if a class implements Serializable but it's parent class does not?


  • To allow subtypes of non-serializable classes to be serialized, the subtype may assume responsibility for saving and restoring the state of the supertype's public, protected, and (if accessible) package fields. The subtype may assume this responsibility only if the class it extends has an accessible no-arg constructor to initialize the class's state. It is an error to declare a class Serializable if this is not the case. The error will be detected at runtime.
  • During deserialization, the fields of non-serializable classes will be initialized using the public or protected no-arg constructor of the class. A no-arg constructor must be accessible to the subclass that is serializable. The fields of serializable subclasses will be restored from the stream.
NOTEWhen traversing a graph, an object may be encountered that does not support the Serializable interface. In this case the NotSerializableException will be thrown and will identify the class of the non-serializable object.


When an object is serialized, information that identifies its class is recorded in the serialized stream. However, the class's definition ("class file") itself is not recorded. It is the responsibility of the system that is deserializing the object to determine how to locate and load the necessary class files. 

What if I want don't want Java to handle Serialization?


The Java platform specifies a default way by which serializable objects are serialized. A (Java) class can override this default serialization and define its own way of serializing objects of that class. The Object Serialization Specification describes object serialization in detail.

Classes that require special handling during the serialization and deserialization process must implement special methods with these exact signatures: 
  • private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {}
  • private void writeObject(java.io.ObjectOutputStream stream) throws IOException {}
  • private void readObjectNoData() throws ObjectStreamException {}

DataOutput Interface


The DataOutput interface provides for converting data from any of the Java primitive types to a series of bytes and writing these bytes to a binary stream. There is also a facility for converting a String into modified UTF-8 format and writing the resulting series of bytes.
For all the methods in this interface that write bytes, it is generally true that if a byte cannot be written for any reason, an IOException is thrown.

There is something known as serialVersionUID; What is it? When to use it? How to use it?

The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long:
 ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members. Array classes cannot declare an explicit serialVersionUID, so they always have the default computed value, but the requirement for matching serialVersionUID values is waived for array classes.

Examples demonstrating all the concepts of Serialization have been commited the below githib repo

https://github.com/omerhashmininjago/java-programs/tree/master/src/main/java/com/demonstrate/concepts/serialization

Volatile keyword, Synchronized keyword and Lock interface

Volatile Marking a member variable as volatile, makes sure, when ever the member variable is accessed, its value is always read from the...