{"id":2917,"date":"2018-10-07T14:11:24","date_gmt":"2018-10-07T14:11:24","guid":{"rendered":"http:\/\/codethataint.com\/blog\/?p=2917"},"modified":"2018-10-07T14:13:40","modified_gmt":"2018-10-07T14:13:40","slug":"hot-code-deployment","status":"publish","type":"post","link":"https:\/\/codethataint.com\/blog\/hot-code-deployment\/","title":{"rendered":"Hot Code Deployment"},"content":{"rendered":"<p>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<\/p>\n<p><strong>IServer.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npublic interface IServer {\r\n\tpublic String getQuote();\r\n}\r\n<\/pre>\n<p><strong>ServerImpl.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npublic class ServerImpl implements IServer{\r\n\t@Override\r\n    public String getQuote() {\r\n        return &quot;Its Working Man&quot;;\r\n    }\r\n}\r\n<\/pre>\n<p><strong>Client.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport java.io.IOException;\r\nimport java.net.URL;\r\nimport java.net.URLClassLoader;\r\nimport java.io.BufferedReader;\r\nimport java.io.InputStreamReader;\r\n\r\npublic class Client {\r\n    static ClassLoader cl;\r\n    static IServer server;\r\n\r\n    public static void reloadServer() throws Exception {\r\n        URL&#x5B;] urls = new URL&#x5B;]{new URL(&quot;file:\/\/\/D:\/java\/HotDeplyment\/appclasses&quot;)};\r\n        System.out.println(&quot;Reloaded.....&quot;);\r\n        cl = new URLClassLoader(urls);\r\n        server  = (IServer) cl.loadClass(&quot;com.mugil.org.ServerImpl&quot;).newInstance();\r\n    }\r\n\r\n    public static void main(String &#x5B;] args) throws Exception {\r\n        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));\r\n        reloadServer();\r\n        while (true) {\r\n            System.out.print(&quot;Enter QUOTE, RELOAD, or QUIT: &quot;);\r\n            String cmdRead = br.readLine();\r\n            String cmd = cmdRead.toUpperCase();\r\n            if (cmd.equals(&quot;QUIT&quot;)) {\r\n                return;\r\n            } else if (cmd.equals(&quot;QUOTE&quot;)) {\r\n                System.out.println( server.getQuote());\r\n            } else if (cmd.equals(&quot;RELOAD&quot;)) {\r\n            \treloadServer();\r\n            }\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p><strong>The Above code is not working<\/strong> 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.<\/p>\n<p><strong>MyURLClassLoader.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport java.lang.reflect.Field;\r\nimport java.net.URL;\r\nimport java.net.URLClassLoader;\r\nimport java.util.Collection;\r\nimport java.util.jar.JarFile;\r\n\r\npublic class MyURLClassLoader extends URLClassLoader {\r\n\r\n\tpublic MyURLClassLoader(URL&#x5B;] urls, ClassLoader parent) {\r\n\t    super(urls, parent);\r\n\t}\r\n\r\n    \/**\r\n     * Closes all open jar files\r\n     *\/\r\n    public void close() {\r\n        try {\r\n            Class clazz = java.net.URLClassLoader.class;\r\n            Field ucp = clazz.getDeclaredField(&quot;ucp&quot;);\r\n            ucp.setAccessible(true);\r\n            Object sunMiscURLClassPath = ucp.get(this);\r\n            Field loaders = sunMiscURLClassPath.getClass().getDeclaredField(&quot;loaders&quot;);\r\n            loaders.setAccessible(true);\r\n            Object collection = loaders.get(sunMiscURLClassPath);\r\n            for (Object sunMiscURLClassPathJarLoader : ((Collection) collection).toArray()) {\r\n                try {\r\n                    Field loader = sunMiscURLClassPathJarLoader.getClass().getDeclaredField(&quot;jar&quot;);\r\n                    loader.setAccessible(true);\r\n                    Object jarFile = loader.get(sunMiscURLClassPathJarLoader);\r\n                    ((JarFile) jarFile).close();\r\n                } catch (Throwable t) {\r\n                    \/\/ if we got this far, this is probably not a JAR loader so skip it\r\n                }\r\n            }\r\n        } catch (Throwable t) {\r\n            \/\/ probably not a SUN VM\r\n        }\r\n        return;\r\n    }\r\n}\r\n<\/pre>\n<p>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.<\/p>\n<p><strong>TestClassLoader.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npackage com.mugil.org;\r\n\r\nimport java.io.BufferedReader;\r\nimport java.io.File;\r\nimport java.io.IOException;\r\nimport java.io.InputStreamReader;\r\nimport java.lang.reflect.InvocationTargetException;\r\nimport java.net.MalformedURLException;\r\nimport java.net.URL;\r\n\r\npublic class TestClassLoader {\r\n\tstatic ClassLoader cl;\r\n    static IServer server;\r\n\t\r\n\tpublic static void main(String&#x5B;] args) throws Exception {\r\n\t\t\r\n\t\twhile(true) {\r\n\t\t\ttry {\r\n\t\t\tBufferedReader br = new BufferedReader(new InputStreamReader(System.in));\r\n\t\t\tTestClassLoader obj = new TestClassLoader();\r\n\t\t\tobj.loadAndInstantiate();\t\t\t\r\n\t\t\tSystem.out.println(server.getQuote());\t\t\t\r\n\t\t\t}\r\n\t\t\tcatch (Exception e){\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\tfinally {\r\n\t\t\t\ttry {\r\n                    Thread.sleep(3000);\r\n                } catch (InterruptedException e) {\r\n                    e.printStackTrace();\r\n                }\r\n\t\t\t}\r\n\t\t}    \r\n\t}\r\n\t\r\n\tvoid loadAndInstantiate() throws Exception {\r\n\t    MyURLClassLoader cl = null;\r\n\t    try {\t    \t\r\n\t        File file = new File(&quot;D:\\\\java\\\\HotDeplyment\\\\bin\\\\Sample.jar&quot;);\r\n\t        String classToLoad = &quot;com.mugil.org.ServerImpl&quot;;\r\n\t        URL jarUrl = new URL(&quot;file:&quot; + file.getAbsolutePath());\r\n\t        cl = new MyURLClassLoader(new URL&#x5B;] {jarUrl}, getClass().getClassLoader());\r\n\t        Class loadedClass = cl.loadClass(classToLoad);\r\n\t        Object o = loadedClass.getConstructor().newInstance();\r\n\t        server  = (IServer) o;\r\n\t        \r\n\t    } finally {\r\n\t        if(cl != null)\r\n\t            cl.close();\r\n\t    } \r\n\t}\r\n}\r\n<\/pre>\n<p>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 <\/p>\n<p><strong>Output<\/strong><\/p>\n<pre>\r\n.\r\n.\r\nIts Working Man\r\nIts Working Man\r\nIts Working Man\r\nIts Working Man\r\nIts Working \r\nIts Working \r\nIts Working \r\n.\r\n.\r\n<\/pre>\n<p><strong>The Above code is not working either<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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&hellip; <a href=\"https:\/\/codethataint.com\/blog\/hot-code-deployment\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[99,142],"tags":[],"class_list":["post-2917","post","type-post","status-publish","format-standard","hentry","category-classes-and-objects","category-java-concepts"],"_links":{"self":[{"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts\/2917","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/comments?post=2917"}],"version-history":[{"count":3,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts\/2917\/revisions"}],"predecessor-version":[{"id":2920,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts\/2917\/revisions\/2920"}],"wp:attachment":[{"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/media?parent=2917"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/categories?post=2917"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/tags?post=2917"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}