Below is a code example of CustomClass Loader which Servers use internally for HotCode Swap without restarting the server.When you change the Quote in ServerImpl.java file the file should be reloaded by selecting the RELOAD option while running Client.java

IServer.java

public interface IServer {
	public String getQuote();
}

ServerImpl.java

public class ServerImpl implements IServer{
	@Override
    public String getQuote() {
        return "Its Working Man";
    }
}

Client.java

import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Client {
    static ClassLoader cl;
    static IServer server;

    public static void reloadServer() throws Exception {
        URL[] urls = new URL[]{new URL("file:///D:/java/HotDeplyment/appclasses")};
        System.out.println("Reloaded.....");
        cl = new URLClassLoader(urls);
        server  = (IServer) cl.loadClass("com.mugil.org.ServerImpl").newInstance();
    }

    public static void main(String [] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        reloadServer();
        while (true) {
            System.out.print("Enter QUOTE, RELOAD, or QUIT: ");
            String cmdRead = br.readLine();
            String cmd = cmdRead.toUpperCase();
            if (cmd.equals("QUIT")) {
                return;
            } else if (cmd.equals("QUOTE")) {
                System.out.println( server.getQuote());
            } else if (cmd.equals("RELOAD")) {
            	reloadServer();
            }
        }
    }
}

The Above code is not working as windows is not clearing cached .class files or JAR files. So the alternative is to try with the below Custom Class Loader(MyURLClassLoader) which in turn extends URLClassLoader again.

MyURLClassLoader.java

import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import java.util.jar.JarFile;

public class MyURLClassLoader extends URLClassLoader {

	public MyURLClassLoader(URL[] urls, ClassLoader parent) {
	    super(urls, parent);
	}

    /**
     * Closes all open jar files
     */
    public void close() {
        try {
            Class clazz = java.net.URLClassLoader.class;
            Field ucp = clazz.getDeclaredField("ucp");
            ucp.setAccessible(true);
            Object sunMiscURLClassPath = ucp.get(this);
            Field loaders = sunMiscURLClassPath.getClass().getDeclaredField("loaders");
            loaders.setAccessible(true);
            Object collection = loaders.get(sunMiscURLClassPath);
            for (Object sunMiscURLClassPathJarLoader : ((Collection) collection).toArray()) {
                try {
                    Field loader = sunMiscURLClassPathJarLoader.getClass().getDeclaredField("jar");
                    loader.setAccessible(true);
                    Object jarFile = loader.get(sunMiscURLClassPathJarLoader);
                    ((JarFile) jarFile).close();
                } catch (Throwable t) {
                    // if we got this far, this is probably not a JAR loader so skip it
                }
            }
        } catch (Throwable t) {
            // probably not a SUN VM
        }
        return;
    }
}

In the below code the CustomClass Loader is called to load the classes which inturn calls the Super Class loader which is again Loaders from URL Class Loader.Once it is done we have defined a custom close method which closes the JAR files or .class files which is loaded by class loader.

TestClassLoader.java

package com.mugil.org;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;

public class TestClassLoader {
	static ClassLoader cl;
    static IServer server;
	
	public static void main(String[] args) throws Exception {
		
		while(true) {
			try {
			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
			TestClassLoader obj = new TestClassLoader();
			obj.loadAndInstantiate();			
			System.out.println(server.getQuote());			
			}
			catch (Exception e){
				
			}
			finally {
				try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
			}
		}    
	}
	
	void loadAndInstantiate() throws Exception {
	    MyURLClassLoader cl = null;
	    try {	    	
	        File file = new File("D:\\java\\HotDeplyment\\bin\\Sample.jar");
	        String classToLoad = "com.mugil.org.ServerImpl";
	        URL jarUrl = new URL("file:" + file.getAbsolutePath());
	        cl = new MyURLClassLoader(new URL[] {jarUrl}, getClass().getClassLoader());
	        Class loadedClass = cl.loadClass(classToLoad);
	        Object o = loadedClass.getConstructor().newInstance();
	        server  = (IServer) o;
	        
	    } finally {
	        if(cl != null)
	            cl.close();
	    } 
	}
}

Since the infinite while loop is called indefinitely with the thread sleep interval of every 3 seconds we replace the JAR file in the middle which takes the class from the new JAR file loaded.You need to change the ServerImpl.java file and build the JDK before you want to see the changes

Output

.
.
Its Working Man
Its Working Man
Its Working Man
Its Working Man
Its Working 
Its Working 
Its Working 
.
.

The Above code is not working either

Why Tomcat Server does not needs restart if changes are done in servlet and JSP?
Tomcat is capable of adding/modifying classpath to Web Application classloader at runtime. Tomcat will be having their custom Classloader implementation which allows them to add the classpaths at runtime.a new classloader is created for the Servlet/JSP with Application classloader as parent classloader. And the new classloader will load the modified class again.

It is always best to reload the entire application incase changes are done to servlet. If you were simply to reload one class, in isolation, you might break dependencies or miss some initialization steps. Therefore, it’s much safer to reload the entire application clicking deploy option in tomcat server.JSPs on the other hand, when properly coded, shouldn’t have anything in them by markup text. So reloading a single JSP, without reloading the entire app, should be safe. By default, tomcat is started in development mode, which means JSP-derived servlets recompiled when a change is detected.

In the web.xml you need to set the below config

<servlet>
   .
   .
    <!-- Add the following init-param -->
    <init-param>
        <param-name>development</param-name>
        <param-value>true</param-value>
    </init-param>
   .
   .
   .
</servlet>

In the Server.xml reloadable should be set to true

<Context path="/simple" docBase="webapps/simple"  debug="0" reloadable="true" ></Context>

More on how CustomClass loader works for Hot Deployment here

Java Bean Class – EmployeeBean

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class EmployeeBean {
	private String Name;
	private int EmpNo;
	private int Age;
	private float Weight;
	
	public String getName() {
		return Name;
	}
	public void setName(String name) {
		Name = name;
	}
	public int getEmpNo() {
		return EmpNo;
	}
	public void setEmpNo(int empNo) {
		EmpNo = empNo;
	}
	public int getAge() {
		return Age;
	}
	public void setAge(int age) {
		Age = age;
	}
	public float getWeight() {
		return Weight;
	}
	public void setWeight(float weight) {
		Weight = weight;
	}
	
	
	
	public EmployeeStringBean getStringBean() {
		
		EmployeeStringBean objEmpBean = new EmployeeStringBean();
		
		objEmpBean.setName(getName() == null?null:getName().toString());
		objEmpBean.setEmpNo(Integer.toString(getEmpNo()));
		objEmpBean.setAge(Integer.toString(getAge()));		
		objEmpBean.setWeight(getWeight()+"");
		
		return objEmpBean;
	}
	
	
	public static List getStringBeanList(List beanList) {
		 List stringBeanList = new ArrayList();

	        if (beanList != null) {
	            Iterator itr = beanList.iterator();

	            while (itr.hasNext()) {
	            	EmployeeBean bean = (EmployeeBean) itr.next();
	                stringBeanList.add(bean.getStringBean());
	            }
	        }

	        return stringBeanList;
	}
}

String Bean Class – EmployeeStringBean

public class EmployeeStringBean {
	private String Name;
	private String EmpNo;
	private String Age;
	private String Weight;
	
	public String getName() {
		return Name;
	}
	public void setName(String name) {
		Name = name;
	}
	public String getEmpNo() {
		return EmpNo;
	}
	public void setEmpNo(String empNo) {
		EmpNo = empNo;
	}
	public String getAge() {
		return Age;
	}
	public void setAge(String age) {
		Age = age;
	}
	public String getWeight() {
		return Weight;
	}
	public void setWeight(String weight) {
		Weight = weight;
	}	
	
	public EmployeeBean getBean()
	{
		EmployeeBean objEmployeeBean = new EmployeeBean();
		
		objEmployeeBean.setName(getName());
		objEmployeeBean.setEmpNo(Integer.parseInt(getEmpNo()));
		objEmployeeBean.setAge(Integer.parseInt(getAge()));
		objEmployeeBean.setWeight(Float.parseFloat((getWeight())));
		
		return objEmployeeBean;
	}	
}

The below code generates no compilation error in eclipse but throws error during Runtime.

public class Animal
{
  public void eat(){}
}
public class Dog extends Animal
{
  public void eat(){}
  public void main(String[] args)
  {
    Animal animal=new Animal();
    Dog dog=(Dog) animal;
  }
}

Output

Exception in thread "main" java.lang.ClassCastException: com.mugil.wild.Animal cannot be cast to com.mugil.wild.Dog
	at com.mugil.wild.Dog.main(Dog.java:12)

By using a cast you’re essentially telling the compiler “trust me. I’m a professional, I know what I’m doing and I know that although you can’t guarantee it, I’m telling you that this animal variable is definitely going to be a dog

Because you’re essentially just stopping the compiler from complaining, every time you cast it’s important to check that you won’t cause a ClassCastException by using instanceof in an if statement.

Generally, downcasting is not a good idea. You should avoid it. If you use it, you better include a check:

Animal animal = new Dog();

if (animal instanceof Dog)
{
Dog dog = (Dog) animal;
}

public class ClassA 
{	
	public void MethodA()
	{
		System.out.println("This is Method A");
	}
}

public class ClassB extends ClassA
{	
	public void MethodB()
	{
		System.out.println("I am Method in Class B");
	}
}


public class ClassC 
{
	public static void main(String[] args) 
	{
		ClassA objClassA1 = new ClassA();
		ClassB objClassB2 = new ClassB();
		
		//Child Class of Parent Type can be Created  
		ClassA objClassB1 = new ClassB();
		
		//Assigning a Parent class Type to Child Class is Not Allowed  
		//Casting Should be Carried out
		ClassB objClassA2 = (ClassB) new ClassA();
		
		objClassA1.MethodA();
		objClassB2.MethodA();
		objClassB2.MethodB();
		
		objClassB1.MethodA();
	}
}

Sample1.java

package com.apryll.package1;
//import static com.apryll.package2.sample2.Funct3;

public class Sample1 
{
	public static void main(String[] args) 
	{
		Sample1 objSample1 = new Sample1();		
		//sample2 objSample2 = new sample2();
		
		System.out.println(com.apryll.package2.sample2.City);
		
		objSample1.Funct2();
		//objSample2.Funct4();
		
		//Sample1.Funct1();
	}
	
	static void Funct1()
	{
	  System.out.println("I am Static Function 1");
	}
	
	void Funct2()
	{	
	  System.out.println(Funct3());
	  System.out.println(City);
	}		
}

Sample2.java

 package com.apryll.package2;

  public class sample2 
  {
     public static int City = 555;
     public static String Funct3()  
     {
	return "Hi there";
     }
	
     public void Funct4()  
     {
	System.out.println("Hello There");
     }
}

1

  package com.apryll.package1;
  
  import  com.apryll.package2.sample2.*;

  public class Sample1 
  {
    public static void main(String[] args) 
    {
      sample2 objSample2 = new sample2();	
    }
  }  

The Above Code Does not Work when creating a object for sample2 since in the import statements is sample2.* is given.It should be

import  com.apryll.package2.sample2;
.
.
.
.

2
While Importing class methods and variables the static will not get imported unless you specify static
import in the import statement

You can Import the Static Methods and Variables in class as below

To Import static methods and Variables

  import  static com.apryll.package2.sample2.*;  

To Import static methods and Variables

  import  static com.apryll.package2.sample2.*;  

To Import static Variable City

  import  static com.apryll.package2.sample2.City;  

To Import static Function getCityName

  import  static com.apryll.package2.sample2.getCityName;  

3
You can directly access static method and Variable declared in some other package in static void main() method as follows

  System.out.println(com.apryll.package2.sample2.City);
  System.out.println(com.apryll.package2.sample2.Funct3());

How Static and Constructor will work when class is Extended

  public class Main2 extends A   
  {
   public static void main(String args[])
    {	
	   
    }
  }

  class A extends B 
  {
    A()
    {
      System.out.println("I am A Constrctor");
    }
	
    static
   {
      System.out.println("I am Static Method");
   }
	
   {
      System.out.println("Empty");
   }
 }

 class B
 {
   B()
   {
     System.out.println("I am B Constrctor");
   }
 }

OP:I am Static Method

How Static and Constructor will work when class object is Created

   public class Main2 extends A   
  {
   public static void main(String args[])
    {	
       A objA = new A();  
    }
  }

  class A extends B 
  {
    A()
    {
      System.out.println("I am A Constrctor");
    }
	
    static
   {
      System.out.println("I am Static Method");
   }
	
   {
      System.out.println("Empty");
   }
 }

 class B
 {
   B()
   {
     System.out.println("I am B Constrctor");
   }
 }

OP:I am Static Method
I am B Constrctor
Empty
I am A Constrctor