{"id":2862,"date":"2018-10-01T06:03:00","date_gmt":"2018-10-01T06:03:00","guid":{"rendered":"http:\/\/codethataint.com\/blog\/?p=2862"},"modified":"2018-10-07T14:41:39","modified_gmt":"2018-10-07T14:41:39","slug":"class-loaders-basics","status":"publish","type":"post","link":"https:\/\/codethataint.com\/blog\/class-loaders-basics\/","title":{"rendered":"Class Loaders Basics"},"content":{"rendered":"<p><strong>Class Loaders<\/strong><br \/>\nLet&#8217;s take two simple Java Files as below<\/p>\n<p><strong>Helper.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npackage com.mugil.org;\r\npublic class Helper {\r\n\tpublic String getMessage()\r\n\t{\r\n\t\treturn &quot;Helper Method&quot;;\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>TestHelper.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npackage com.mugil.org;\r\npublic class TestHelper {\r\n\tpublic static void main(String&#x5B;] args) {\r\n\t\tHelper objHelper = new Helper();\r\n\t\tSystem.out.println(objHelper.getMessage());\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>How to Compile class in Command Prompt<\/strong><br \/>\nNormally when you compile Java class the class files would be created in bin folder with<br \/>\nthe folder structure same as package name bin->com->mugil->org.<br \/>\nWhen you want the .class to be created in a specific folder then use the below command<\/p>\n<pre>\r\nD:\\java\\ClassLoaders>javac -d classes -sourcepath src src\\com\\mugil\\org\\Helper.java\r\n<\/pre>\n<p>Classes folder should be created manually or it&#8217;s going to throw<br \/>\njavac: directory not found: classes<\/p>\n<p>Before Running the code the Classpath needs to be set which could be done either globally<br \/>\nby adding to the System classPath or locally at the application level<\/p>\n<p>To Set globally the following should be run in Command Prompt<\/p>\n<pre>\r\nD:\\java\\ClassLoaders>set CLASSPATH=classes\r\n<\/pre>\n<p>After this, the Java code can be run as below<\/p>\n<pre>\r\nD:\\java\\ClassLoaders>java com.mugil.org.TestHelper\r\nHelper Method\r\n<\/pre>\n<p>Setting Globally is not a good idea as other applications Classpath would be affected.If you<br \/>\nhave set classpath globally chances are you may end up running wrong JAR file in the Classpath<br \/>\nThe Better option is to set classpath while running the application itself<\/p>\n<pre>\r\nD:\\java\\ClassLoaders>java -cp classes com.mugil.org.TestHelper\r\nHelper Method\r\n<\/pre>\n<p>Now let&#8217;s see how to take .class files in some other folder or .class files in JAR folder to<\/p>\n<p>To run the .class file in other folders along with the one we are running adding the .class files separated by semicolon would be an easy way<br \/>\nas below<\/p>\n<pre>\r\nD:\\java\\ClassLoaders>java -cp D:\\java\\ClassLoaders\\classes;D:\\class1; com.mugil.org.TestHelper\r\nHelper Method\r\n<\/pre>\n<p>The Helper.class is moved to D:\\class1 folder and  TestHelper.class is in D:\\java\\ClassLoaders\\classes folder<br \/>\nTestHelper.class needs Helper.class to run.<\/p>\n<p>Now how about JAR Files<\/p>\n<pre>\r\nD:\\class1>jar cvf helper.jar com\\mugil\\org\\Helper.class\r\nadded manifest\r\nadding: com\/mugil\/org\/Helper.class(in = 296) (out= 227)(deflated 23%)\r\n<\/pre>\n<p>To run the classes in the JAR Files the same command applies.<em>D:\\class1<\/em> is the location where the JAR&#8217;s are located(helper.jar).<\/p>\n<pre>\r\nD:\\java\\ClassLoaders>java -cp D:\\java\\ClassLoaders\\classes;D:\\class1; com.mugil.org.TestHelper\r\nHelper Method\r\n<\/pre>\n<p>Once the JAR is created the .class files can be deleted and added to lib folder<\/p>\n<p><em>While Creating JAR make sure you maintain the folder structure.Creating JAR file without adding com\\mugil\\org folder will result in classNotFound Exception<\/em><\/p>\n<pre>\r\nD:\\java\\ClassLoaders>java -cp D:\\java\\ClassLoaders\\classes\\lib\\Helper.jar;D:\\java\\ClassLoaders\\classes\\; com.mugil.org.TestHelper\r\n<\/pre>\n<p>Class loaders are the part of the Java Runtime Environment that dynamically loads Java classes into the Java virtual machine. It is responsible for locating libraries, reading content and loading the classes contained within the libraries. When JVM is started three class loaders are used<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/codethataint.com\/blog\/wp-content\/uploads\/2018\/10\/java_classloader_hierarchy.png\" alt=\"\" height=\"234\" width=\"447\"\/><\/p>\n<p><strong>How ClassLoaders works<\/strong><\/p>\n<ol>\n<li>When JVM requests for a class, it invokes loadClass function of the ClassLoader by passing the fully classified name of the Class.<\/li>\n<li>loadClass function calls for findLoadedClass() method to check that the class has been already loaded or not. It\u2019s required to avoid loading the class multiple times.<\/li>\n<li>If the Class is not already loaded then it will delegate the request to parent ClassLoader to load the class.<\/li>\n<li>If the parent ClassLoader is not finding the Class then it will invoke findClass() method to look for the classes in the file system.<\/li>\n<\/ol>\n<p>1. Bootstrap class loader (Written in C)<br \/>\n2. Extensions class loader (Written in Java)<br \/>\n3. System or Application class loader (Written in Java)<\/p>\n<p>Apart from CLASSPATH java looks into two other locations to load the JAR Folder<br \/>\nC:\\Program Files\\Java\\jdk1.8.0_111\\jre\\lib in JRE installation Folder<br \/>\nC:\\Program Files\\Java\\jdk1.8.0_111\\jre\\lib\\ext<\/p>\n<p><b>Bootstrap class loader<\/b><br \/>\nIt loads JDK internal classes, typically loads rt.jar and other core classes for example java.lang.* package classes<\/p>\n<p>rt.jar is one of the JAR files in JRE Folder. You can see the content in  rt.jar by renaming it into rt.jar.<br \/>\nrt.jar is loaded by the bootstrap class loader.<\/p>\n<p><b>Extensions class loader<\/b><br \/>\nIt loads classes from the JDK extensions directory, usually $JAVA_HOME\/lib\/ext directory.<br \/>\nYou can add your JAR files like DB Connection JAR in the EXT folder and would be available to all application which runs on JVM<\/p>\n<p><strong>helper.jar added to ext folder<\/strong><br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/codethataint.com\/blog\/wp-content\/uploads\/2018\/10\/ClassLoader1.png\" alt=\"\" height=\"403\" width=\"769\"\/><\/p>\n<pre>\r\nD:\\java\\ClassLoaders>java -cp D:\\java\\ClassLoaders\\classes;D:\\class1; com.mugil.org.TestHelper\r\nHelper Method\r\n\r\nD:\\java\\ClassLoaders>java -cp D:\\java\\ClassLoaders\\classes; com.mugil.org.TestHelper\r\nHelper Method\r\n<\/pre>\n<p><b>Note<\/b>:In the second statement the <i>D:\\class1<\/i> is missing which has the JAR files which is now moved to EXT folder.No need to specify the JAR files as JAR files in EXT are loaded by default<\/p>\n<p><b>System (or) Application class loader<\/b><br \/>\nSystem or Application class loader and it is responsible for loading application specific classes from CLASSPATH environment variable, -classpath or -cp command line option, Class-Path attribute of Manifest file inside JAR.<\/p>\n<p><strong>Delegation of Classes<\/strong><\/p>\n<ol>\n<li>Delegation Classes are classes which delegates the call to its Parent Class which inturn Delegates to its Parent<\/li>\n<li>Each class loader has a parent. Class Loaders may delegate to its Parent. Parent may or may not load the class<\/li>\n<li>Loaded classes are always cached<\/li>\n<li>Application loader asks the Extension Class loader which inturn asks Bootstap loader<\/li>\n<li>If Bootstap loader couldnt find the class it will send fail message which makes the Extension Class loader to search for classes within<\/li>\n<li>If Extension loader couldnt find the class it will send fail message to Application Class Loader and makes to search for classes within<\/li>\n<li>If Application Class loader couldnt find the class <strong>NoClassDefinition Error <\/strong>would be Displayed<\/li>\n<\/ol>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/codethataint.com\/blog\/wp-content\/uploads\/2018\/10\/ClassLoader2.png\" alt=\"\" height=\"392\" width=\"478\"\/><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport java.net.URLClassLoader;\r\n\r\npublic class Delegation \r\n{\r\n\tpublic static void main(String&#x5B;] args) \r\n\t{\r\n\t\tURLClassLoader classloader = (URLClassLoader)ClassLoader.getSystemClassLoader();\r\n\t\t\r\n\t\tdo {\r\n\t\t\tSystem.out.println(classloader);\r\n\t\t} while ((classloader = (URLClassLoader)classloader.getParent()) != null);\r\n\t\t\r\n\t\tSystem.out.println(&quot;Bootstrap ClassLoader&quot;);\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>Output<\/strong><\/p>\n<pre>\r\nsun.misc.Launcher$AppClassLoader@1497b7b1\r\nsun.misc.Launcher$ExtClassLoader@749cd006\r\nBootstrap ClassLoader\r\n<\/pre>\n<p>To See the location of the Class Files loaded you can use the below code<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n.\r\n.\r\ndo {\r\n\t\t\tSystem.out.println(classloader);\r\n\t\t\t\r\n\t\t\tfor(URL url : classloader.getURLs())\t\t\r\n\t\t\t System.out.println(&quot;\\t %s&quot;+ url.getPath());\r\n\t\t\t\r\n\t\t} while ((classloader = (URLClassLoader)classloader.getParent()) != null);\r\n.\r\n.\r\n<\/pre>\n<p><strong>Output<\/strong><\/p>\n<pre>\r\nsun.misc.Launcher$AppClassLoader@1497b7b1\r\n\t %s\/D:\/java\/ClassLoaders\/bin\/\r\nsun.misc.Launcher$ExtClassLoader@749cd006\r\n\t %s\/C:\/Program%20Files\/Java\/jdk1.7.0_45\/jre\/lib\/ext\/access-bridge-64.jar\r\n\t %s\/C:\/Program%20Files\/Java\/jdk1.7.0_45\/jre\/lib\/ext\/dnsns.jar\r\n\t %s\/C:\/Program%20Files\/Java\/jdk1.7.0_45\/jre\/lib\/ext\/jaccess.jar\r\n\t %s\/C:\/Program%20Files\/Java\/jdk1.7.0_45\/jre\/lib\/ext\/localedata.jar\r\n\t %s\/C:\/Program%20Files\/Java\/jdk1.7.0_45\/jre\/lib\/ext\/sunec.jar\r\n\t %s\/C:\/Program%20Files\/Java\/jdk1.7.0_45\/jre\/lib\/ext\/sunjce_provider.jar\r\n\t %s\/C:\/Program%20Files\/Java\/jdk1.7.0_45\/jre\/lib\/ext\/sunmscapi.jar\r\n\t %s\/C:\/Program%20Files\/Java\/jdk1.7.0_45\/jre\/lib\/ext\/zipfs.jar\r\nBootstrap ClassLoader\r\n<\/pre>\n<p>In the above Output, you can see the Application Class Loaders loads the Java class from the Project Directory and EXT jars from the EXT C:\/Program%20Files\/Java\/jdk1.7.0_45\/jre\/lib\/ext\/ Folder<\/p>\n<p><strong>Why we need Custom ClassLoader?<\/strong><br \/>\nWhenever a class is referenced in a java program it is loaded using JVM\u2019s bootstrap class loader. This often becomes a problem when two different classes with same name and same package declaration are to be loaded. For example relying on JVM\u2019s class loader one cannot load two different versions of the same JDBC driver. The work around to this problem is lies in making a custom class loader and loading classes directly from JAR archives.<\/p>\n<p><em>Other Reasons<\/em><\/p>\n<ol>\n<li>Better Memory Management Unused modules can be removed which unloads the classes used by that module, which cleans up memory.<\/li>\n<li>Load classes from anywhere Classes can be loaded from anywhere, for ex, Database, Networks, or even define it on the fly.<\/li>\n<li>Runtime Reloading Modified Classes Allows you to reload a class or classes runtime by creating a child class loader to the actual class loader, which contains the modified classes.<a href=\"http:\/\/codethataint.com\/blog\/hot-code-deployment\/\">Hot Deployment<\/a><\/li>\n<li>Provides Modular architecture Allows to define multiple class loader allowing modular architecture.<\/li>\n<li>Support Versioning Supports different versions of class within same VM for different modules. <a href=\"#sidebysidedeployment\">Multiple Version Support<\/a><\/li>\n<li>Avoiding conflicts Clearly defines the scope of the class to within the class loader.<\/li>\n<li>Class loading mechanism forms the basis of Inversion of Control<\/li>\n<\/ol>\n<p>Simple URL Class Loader<br \/>\nIn the below example we are using URL Class Loading method to load the Classes from the JAR file.We can load Classes from File Based URL or Network Based URL<br \/>\nWe can also load class from DB<\/p>\n<p><strong>SimpleClassLoader.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npublic class SimpleClassLoader {\r\n\tpublic static void main(String&#x5B;] args) {\r\n\t\tURL url;\r\n        try {\r\n            url = new URL(&quot;file:\/\/\/D:\/jars\/helper.jar&quot;);\r\n            URLClassLoader ucl = new URLClassLoader(new URL&#x5B;]{url});\r\n            Class clazz = ucl.loadClass(&quot;com.mugil.org.Helper&quot;);\r\n            Object o = clazz.newInstance();\r\n            Helper objHelper = (Helper)o;\r\n            System.out.println(o.toString());\r\n    \t\tSystem.out.println(objHelper.getMessage());            \r\n        } catch (MalformedURLException e) {\r\n            e.printStackTrace();\r\n        } catch (ClassNotFoundException e) {\r\n            e.printStackTrace();\r\n        } catch (InstantiationException e) {\r\n            e.printStackTrace();\r\n        } catch (IllegalAccessException e) {\r\n            e.printStackTrace();\r\n        }\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>Output<\/strong><\/p>\n<pre>\r\nHelper Method\r\ncom.mugil.org.Helper@4631c43f\r\n<\/pre>\n<p><strong>Note:<\/strong> In the above example you can see the Typecasting from Object to Helper which again makes the code tightly coupled and defeats the purpose of the class loader dynamically loads Java classes into the Java Virtual Machine. To resolve this issue we can use Interface which is loaded by application class loader with the implementing class loaded by our own class loader.<\/p>\n<p><strong>Account.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npublic interface Account {\r\n\tpublic Integer getInterestRate(); \r\n}\r\n<\/pre>\n<p><strong>SavingsAccount.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npublic class SavingsAccount implements Account {\r\n\t@Override\r\n\tpublic Integer getInterestRate() {\r\n\t\treturn 10;\r\n\t}\r\n}\r\n<\/pre>\n<p>Implementation classes added to our JAR so it can be loaded by our Class Loader<\/p>\n<pre>\r\nD:\\java\\ClassLoaders\\bin> jar cvf Accounts.jar com\\mugil\\org\\SavingsAccount.class\r\nadded manifest\r\nadding: com\/mugil\/org\/SavingsAccount.class(in = 496) (out= 301)(deflated 39%)\r\n<\/pre>\n<p><strong>CalculateInterest.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npublic class CalculateInterest {\r\n\tpublic static void main(String&#x5B;] args) \r\n\t{\r\n\t\tURL url;\r\n        try {\r\n            url = new URL(&quot;file:\/\/\/D:\/jars\/Accounts.jar&quot;);\r\n            URLClassLoader ucl = new URLClassLoader(new URL&#x5B;]{url});\r\n            Class clazz = ucl.loadClass(&quot;com.mugil.org.SavingsAccount&quot;);\r\n            Account o = (Account)clazz.newInstance();            \r\n            System.out.println(o.toString());\r\n    \t\tSystem.out.println(o.getInterestRate());            \r\n        } catch (MalformedURLException e) {\r\n            e.printStackTrace();\r\n        } catch (ClassNotFoundException e) {\r\n            e.printStackTrace();\r\n        } catch (InstantiationException e) {\r\n            e.printStackTrace();\r\n        } catch (IllegalAccessException e) {\r\n            e.printStackTrace();\r\n        }\r\n\t}\r\n}\t\r\n<\/pre>\n<p><strong>In the above code I can change the logic interest is calculated in the SavingsAccount and redeploy the JAR without taking effect in other parts of the program.<\/strong><\/p>\n<p>The above jar file could be loaded accross network by giving URL as below<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n.\r\n.\r\nURL url = new URL(&quot;http:\/\/localhost:8080\/Accounts.jar&quot;);\r\n.\r\n.\r\n<\/pre>\n<p><strong>Multiple version Support of Same JAR<\/strong><br \/>\n<a name=\"sidebysidedeployment\"><\/a><br \/>\nJava bytecode is universal across platforms, you can use it to instrument classes on any system: a measure which methods are called, suppress security-critical calls, divert System.out accesses to your own custom logging routines, or perform advanced dynamic bug-testing routines.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n\tpublic static void main(String&#x5B;] args) {\r\n\t\ttry { \r\n            URL url1 = new URL(&quot;file:\/\/\/D:\/jars\/Accounts1.jar&quot;); \r\n            URLClassLoader ucl1 = new URLClassLoader(new URL&#x5B;]{url1}); \r\n            Class clazz1 = Class.forName(&quot;com.mugil.org.SavingsAccount&quot;, true, ucl1);\r\n            Account quote1 = (Account) clazz1.newInstance();\r\n\r\n            URL url3 = new URL(&quot;file:\/\/\/D:\/jars\/Accounts.jar&quot;);\r\n            URLClassLoader ucl3 = new URLClassLoader(new URL&#x5B;]{url3});\r\n            Class clazz2 = Class.forName(&quot;com.mugil.org.SavingsAccount&quot;, true, ucl3);\r\n            Account quote2 = (Account) clazz2.newInstance();\r\n\r\n            System.out.printf(&quot;clazz1 == clazz2? %b\\n&quot;, clazz1 == clazz2);\r\n            System.out.printf(&quot;quote1.class == quote2.class? %b\\n&quot;, quote1.getClass() == quote2.getClass());\r\n\r\n        } catch (MalformedURLException e) {\r\n            e.printStackTrace();\r\n        } catch (ClassNotFoundException e) {\r\n            e.printStackTrace();\r\n        } catch (InstantiationException e) {\r\n            e.printStackTrace();\r\n        } catch (IllegalAccessException e) {\r\n            e.printStackTrace();\r\n        }\r\n\t}\r\n<\/pre>\n<p><strong>Output<\/strong><\/p>\n<pre>\r\nclazz1 == clazz2? false\r\nquote1.class == quote2.class? false\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Class Loaders Let&#8217;s take two simple Java Files as below Helper.java package com.mugil.org; public class Helper { public String getMessage() { return &quot;Helper Method&quot;; } } TestHelper.java package com.mugil.org; public class TestHelper { public static void main(String&#x5B;] args) { Helper objHelper = new Helper(); System.out.println(objHelper.getMessage()); } } How to Compile class in Command Prompt Normally&hellip; <a href=\"https:\/\/codethataint.com\/blog\/class-loaders-basics\/\">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":[248],"tags":[],"class_list":["post-2862","post","type-post","status-publish","format-standard","hentry","category-core-java"],"_links":{"self":[{"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts\/2862","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=2862"}],"version-history":[{"count":31,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts\/2862\/revisions"}],"predecessor-version":[{"id":2924,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts\/2862\/revisions\/2924"}],"wp:attachment":[{"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/media?parent=2862"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/categories?post=2862"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/tags?post=2862"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}