Java - Interesting Stuffs


I am just still an admirer and constant learner of JAVA, So here are some interesting stuffs .I will try to constantly update once I come across some interesting things (atleast to me:) ),

  1. To resurrect an object(to make the object alive again) instead of reassigning in the object in finalize method "create a clone"
  2. Java Object are created in heap while in C++ ,they are created in Stack
  3. Object persistence can be done using object serialization and DATA ACCESS OBJECTS(DAO)
  4. Making an object alive in finalize method is useful when we use JNI for a c++ class and do it with a "termination condition"(when there is a code to check whether all the object references in the program has been made null) during garbage collection.
  5. System.gc() may or may not run finalize() of for the orphans (object that holds no reference) but Runtime.runFinalizersonExit(true) and System.runFinalizersonExit(true) will surely make the objects ready for the garbage collected.
  6. Java supports only pass by value, either for an object or a primitive type.
  7. Suprising,regertfull!!!
    Let's discuss,

    Actually when we call a method swap(p1,p2) and the method definition goes like this

    public void swap(Point p,Point q){
    Point temp=p;
    p=q;
    q=temp;
    }

    Simple swap isn't but here there are lot more to analyse if p1.i=10,p2.i=11 what
    will happen if we call
    swap(p1,p2);
    p1.i is 11 and p2.i is 10 ??? NO..

    when we call swap(p1,p2) the reference value is passed not the object itself
    (note it passes only reference value) so in method swap
    p-->p1 and q-->p2 (Note: --> synonymous to 'refers')


    so for this snippet,
    Point temp=p; // temp-->p-->p1
    p=q; // p-->q
    q=temp; // q-->temp-->p-->q ( as by above step)

    So both p and q refers to p2 now ... so we will get the output p1.i is 10 and p2.i is 10.
  8. Since the Java uses objects to be created in heap.It's not fast to access as in C++ ( it uses stack ).
    The memory model goes like this,

    1.Processor Registers - faster access since they live in processor itself and they are limited
    2.Stack - They live in RAM but has direct support from processor using "stack pointers".
    It is needed to know the size of the storage element ,since we are in need to move the pointers.So object references are stored in stack not the object.
    Object references are 4 bytes for 32 bit computers and 8 bytes for 64 bit computers.
    3.Heap - It is a memory pool that living in RAM area.It's flexible since the compiler need not to know
    the amount and life of storage.but it is slower when it compared to stack storage allocations.
    4.Static storage - "fixed location" in java the static members of the object are stored in these
    locations but not the object itself.They also live in RAM.
    5.Constant Storage - The constant values are placed directly in the program code, which is safe sice they can never change
    but optionally they are stored in ROM(in embedded systems).
    6.Non-RAM Storage - external file where persistent object mechanisms are used to store the object in the secondary memory
    files and in streaming where object are sent to another machine.

    Since the heap holds the objects, the garbage collection can be expensive and the compiler must be built with effective algorithm to solve this. This can be achieved in the following ways,
    - Like a conveyor belt the object can be allocated with the help of "heap pointer" so it will function like a stack
    (but there is still overhead for book-keeping(maintaining heap pointer) operations but effective
    than searching for a memory ) but this might lead to paging it can be avoided like compacting the memory once a while
    the garbage collectior steps in.

    - There is simple method called 'reference counting' each object has a constant with no. of reference made in it.
    If one reference goes null then the object's referece count is decreased by 1.Likewise , when the reference countof an object goes 0 it is garbage collected.
    One drawback in this is if there is a circular reference like a->b b->a we can find the fault in
    it by putting a->b->a so this is equal to just a,so the reference count of a is 1 , but this just implies it has no
    meaning full reference and it has to be garbage collected.
    So these type of checks needs special algorithm to do it and this method is seldom used.

    - Actually the JVM uses an adaptive method for garbage collection,

    It is the combination of STOP AND COPY , MARK AND SWEEP

    "STOP AND COPY" involves stop the current execution and copy the live objects
    (found out by tracing the path of references in stack and static storage) to another heap while leaving the
    dead objects(those have no references in the stack or static storage) in the old heap for garbage collection.

    Two issues are in this method:
    1.Copy-collectors : since we need to allocate two heaps of same size to copy the live objects.
    2.Copying : sometimes the program gets stabilized and no or only few objects needs to be garbage collected
    at that time the its really in-efficient to copy the whole heap to another heap of same size.

    So this method can be used when there is large amount of objects need to be garbage collected.

    "MARK AND SWEEP":
    Finds the live objects as in STOP AND COPY but the garbage collection is different.
    It marks each live object by setting a flag.
    Here only the marking process is finished the sweep(releasing dead objects) occur.
    It is generally slow but if it is used with small no. of garbage then its pretty fast.

    So the JVM can switch to any one of these methods depending upon the no. of garbage.
    Thats why it is called adaptive method.It can switch to any method in middle of the garbage collection.

    A better alternative available for garbage collection is JIT(Just in time).
    which converts the byte code(.class files) partially or fully to native codes.
    but it has 2 drawbacks:
    1.the conversions slows the execution.
    2.It increases the exectuble memory size resulting fragments(paging) to occur which will still reduce the execution speed.

    So it uses "lazy evaluation" technique where it is not compiled to native code until it is asked for.
    The recent JDK's uses similar approaches to optimize the code like more code it executes faster it gets.
  9. un-initialized member variable are assigned to proper startup value according to the types and if they are local variables they are assigned with garbage values instead compiler error is thrown.
  10. If we have same method with same signature in a abstract class and an interface extended and implemented respectively in a class , it doesn't cause any error but if they have return types different then they give a compile time error this is one of the problems we may face and the possible is to create a inner class with implements or extends depending upon its enclosing class's usage.
  11. equals and hascode method of object should always comply to the following contracts,

    -Reflexive,Symmetric,Transitive,Consistent,Systematic treatment of null values.
    If two objects are equal then their hashcode should always be equal and its not necessary that if objects have same
    hascode can't be equal.
    -when implementing ur own equals method give Object as its argument not ur own class 'coz if u use ur own class
    then it will just overload the equal method but not override,so it always safe to have equals method with object
    argument in order avoid weird beahviours

    Here are some useful guidelines for implementing the hashCode method correctly.

    1. Store an arbitrary non-zero constant integer value (say 7) in an int variable, called hash.
    2. Involve significant variables of your object in the calculation of the hash code, all the variables that are part of equals comparison should be considered for this. Compute an individual hash code int var_code for each variable var as follows -
    1. If the variable(var) is byte, char, short or int, then var_code = (int)var;
    2. If the variable(var) is long, then var_code = (int)(var ^ (var >>> 32));
    3. If the variable(var) is float, then var_code = Float.floatToIntBits(var);
    4. If the variable(var) is double, then -
    long bits = Double.doubleToLongBits(var);
    var_code = (int)(bits ^ (bits >>> 32));
    5. If the variable(var) is boolean, then var_code = var ? 1 : 0;
    6. If the variable(var) is an object reference, then check if it is null, if yes then var_code = 0; otherwise invoke the hashCode method recursively on this object reference to get the hash code. This can be simplified and given as -
    var_code = (null == var ? 0 : var.hashCode());
    3. Combine this individual variable hash code var_code in the original hash code hash as follows -
    hash = 31 * hash + var_code;
    4. Follow these steps for all the significant variables and in the end return the resulting integer hash.
    5. Lastly, review your hashCode method and check if it is returning equal hash codes for equal objects. Also, verify that the hash codes returned for the object are consistently the same for multiple invocations during the same execution.

    The guidelines provided here for implementing equals and hashCode methods are merely useful as guidelines, these are not absolute laws or rules. Nevertheless, following them while implementing these two methods will certainly give you correct and consistent results.

    TIPS,
    * Equal objects must produce the same hash code as long as they are equal, however unequal objects need not produce distinct hash codes.
    * The equals method provides "deep comparison" by checking if two objects are logically equal as opposed to the "shallow comparison" provided by the equality operator ==.
    * However, the equals method in java.lang.Object class only provides "shallow comparison", same as provided by the equality operator ==.
    * The equals method only takes Java objects as an argument, and not primitives; passing primitives will result in a compile time error.
    * Passing objects of different types to the equals method will never result in a compile time error or runtime error.
    * For standard Java wrapper classes and for java.lang.String, if the equals argument type (class) is different from the type of the object on which the equals method is invoked, it will return false.
    * The class java.lang.StringBuffer does not override the equals method, and hence it inherits the implementation from java.lang.Object class.
    * The equals method must not provide equality comparison with any built in Java class, as it would result in the violation of the symmetry requirement stated in the general contract of the equals method.
    * If null is passed as an argument to the equals method, it will return false.
    * Equal hash codes do not imply that the objects are equal.
    * return 1; is a legal implementation of the hashCode method, however it is a very bad implementation. It is legal because it ensures that equal objects will have equal hash codes, it also ensures that the hash code returned will be consistent for multiple invocations during the same execution. Thus, it does not violate the general contract of the hashCode method. It is a bad implementation because it returns same hash code for all the objects. This explanation applies to all implementations of the hashCode method which return same constant integer value for all the objects.
    * In standard JDK 1.4, the wrapper classes java.lang.Short, java.lang.Byte, java.lang.Character and java.lang.Integer simply return the value they represent as the hash code by typecasting it to an int.
    * Since JDK version 1.3, the class java.lang.String caches its hash code, i.e. it calculates the hash code only once and stores it in an instance variable and returns this value whenever the hashCode method is called. It is legal because java.lang.String represents an immutable string.
    * It is incorrect to involve a random number directly while computing the hash code of the class object, as it would not consistently return the same hash code for multiple invocations during the same execution.

    ref:http://www.geocities.com/technofundo/tech/java/equalhash_cartoon.html



Comments

Unknown said…
Great Info about Java.Will be very useful for Java Programmers.

Knowledge is meant for sharing.I would really appreciate my buddy for sharing his knowledge.

Cool,
Thiags.S
M3hm0^2d: said…
hey thiags , thanks little time constraint so couldn't edit it properly,will do it in weekends... k also comment if any wrong or any doubt!!!

Popular posts from this blog

Hibernate queries are slow ! SQL Server's are not my type ? - Here is what you need to know!

IFTTT Service descriptions with Google Search

Detecting browser event closing in Javascript