Class Loading

  • November 2019
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Class Loading as PDF for free.

More details

  • Words: 1,061
  • Pages: 18
Class Repositories or How JBoss Class Loading Works

When a new UCL is created and associated with the repository,  it contributes to the repository a map of packages it can  potentially serve classes from.  It doesn't add any class to the repository's class cache yet,  because nobody has requested any class at this stage. The repository just walks through the class loader's URL to see  what packages that UCL is capable of handling.  So, the UCL just declares that it can potentially serve classes  from the packages that are present in its classpath. 

When requested to load a class, a UCL overrides the standard  Java2 class loading model by first trying to load a class from its  associated repository's cache. If it doesn't find it there, it delegates the task of loading the  class to the first UCL associated with the repository that  declared it can load that class.  The order in which the UCLs have been added to the repository  becomes important, because this is what defines "first" in this  context. 

If no "available" UCL is found, the initiating UCL falls back to  the standard Java2 parent delegation. 

At the end of this process, if no class definition is found in the  bootstrap libraries, in the $JBOSS_HOME/lib libraries nor  among the libraries associated with the repository's UCL, the  UCL throws a ClassNotFoundException.  However, if one of the pair UCL is able to load the class, the  class will be added to the repository's class cache and from this  moment on, it will be returned to any UCL requesting it.  Even if the Java bootstrap packages or $JAVA_HOME/lib  packages are not added to the repository's package map, the  classes belonging to those packages can be loaded through the  process described above and they are added to the repository  too

Class sharing can be turned off. J2EE­style class namespace isolation  is available. You get an "isolated" application by scoping the  application's deployment. At the JBoss class loading management  system level, scoping translates into creating a child repository.  A scoped application still can load the classes present in the classpaths  of the UCLs or the root repository.  Depending on whether repository's "Java2ParentDelegation" flag is  turned on or off, a scoped application even has access to the class  instances available in the root repository's cache

Case 1. The Utility.class is present in the application's archive, but nowhere else on  the server.

First time the application needs to use a strong­typed Utility reference, the  VM asks the current UCL to load the class. The UCL tries to get the class  from the repository's cache  (1). If it is found, the class is returned and the process stops right here. If the  class is not found, the UCL queries the repository for UCLs capable to load  classes from the package the unknown class is part of (3). Being the single  UCL able to define the class, the control returns to it and load manager calls  loadClassLocally() on it (4). loadClassLocally() first tries to call  super.loadClass() (5), which ends by involving the  NoAnnotationClassLoader in the loading process. If the class is present in  the bootstrap libraries or $JBOSS_HOME/lib (the URLs associated with the  NoAnnotationClassLoader instance), it is loaded. Otherwise, the class is  loaded from the URLs associated with the current UCL. Finally, the class is  added to the repository's class cache (6).  This is the configuration of the UnifiedLoaderRepository after the class  loading takes place. 

Case 2. The Utility.class is present both in the application's archive AND  server/default/lib. The deployment is non­scoped.

The key element here is that when  getPackageClassLoaders() is invoked on the repository, the  method calls returns two potential classloaders that can load  org.useful.Utility: UCL0 and UCL1.  The UCL0 is chosen, because it was added to the repository  before UCL1 and it will be used to load org.useful.Utility.  This is the configuration of the UnifiedLoaderRepository after  the class loading takes place. 

Case 3. The Utility.class is present both in the application's archive AND server/default/lib.  The deployment is scoped and Java2ParentDelegation is turned off (default).

 

Because Java2ParentDelegation is turned off by default, the  Step (1.1) is never executed,  parentRepository.getCachedClass() never gets called, so  the UCL doesn't have access to the repository's cached  classes.  Within the scope of the call to getPackageClassLoaders() at  Step 3, the child repository also calls  getPackageClassLoaders() on its parent, and also includes  into the returned class loader set a UCL (constructed on the  spot and associated to the child repository) that has among its  ancestors an instance of NoAnnotationURLClassLoader,  which ultimately can reach the system class loader. 

Why is that? Remember that the UCL's parent,  HierarchicalLoaderRepository3$NoParentClassLoader,  overrides loadClass() to always throw a  ClassNotFoundException, thus forcing the UCL to only load from  its URLs. If the UCL relies only on its class loader parent to load  bootstrap classes, it will throw ClassNotFoundException and fail  when your application wants to load "java.lang.String", for example.  The NoAnnotationURLClassLoader­delegating UCL instance  included in the return set provides a way load bootstrap library  classes.  Always the HierarchialLoaderRepository's class loaders take  precedence over the parent's (their "order" is lower). For the case  depicted above, UCL1 is the preferred class loader. 

This is the configuration of the UnifiedLoaderRepository  after the class loading takes place. 

Case 4. The Utility.class is present both in the application's  archive AND server/default/lib. The deployment is scoped, but  java2ParentDelegation is turned on.

When Java2ParentDelegation is turned on, the Step (1.1) is  executed, and if a cached class is found in the parent repository, it  is returned and the process stops here.  Within the scope of the call to getPackageClassLoaders() at Step  (3), the child repository also calls getPackageClassLoaders() on its  parent, but does not include into the returned class loader set a  UCL with a parent to the system class loader.  If there are no class loaders in the repository capable of handling  the request ask the class loader itself in the event that its parent(s)  can load the class (repository.loadClassFromClassLoader())  The HierarchialLoaderRepository's class loaders take precedence  over the parent's (their "order" is lower). For the case depicted  above, UCL1 is the preferred class loader. 

This is the configuration of the UnifiedLoaderRepository  after the class loading takes place.

Question: What happens if the parent delegation is  true and a classloader already loaded the class in the  parent repository's class cache? 

Answer: My scoped application will use the already  loaded class from the parent repository's class cache. 

Related Documents

Class Loading
November 2019 21
Class Loading
November 2019 15
Unit-rail-loading-class
December 2019 11
Blast Loading
July 2020 11
Anticipation Loading
November 2019 14
Loading Images
October 2019 21