Deploy wisely

Inside the JBoss AS 7 modularity

DaneMarcelo
jboss

The Java Classloader is a part of the Java Runtime Environment that dynamically loads Java classes into the Java Virtual Machine. However there are some various ways in which the classloading process can end up not working. Let’s take a look

The Java Classloader is a part of the Java Runtime
Environment that dynamically loads Java classes into the Java
Virtual Machine. However there are various ways in which the
classloading process can end up not working. Let’s take a
look:

- A developer or deployer of a Java application
has accidentally made two different versions of a library available
to the system. This will not be considered an error by the system.
Rather, the system will load classes from one or the other library.
Adding the new library to the list of available libraries instead
of replacing it, may see the application still behaving as though
the old library is in use, which it may well be.

- Two libraries (or a library and the
application) require different versions of the same third library.
If both versions of the third library use the same class names,
there is no way to load both versions of the third library with the
same classloader.

- The most complex JAR hell problems arise in
circumstances that take advantage of the full complexity of the
classloading system. A Java program is not required to use only a
single “flat” classloader, but instead may be composed of several
(potentially very many) nested, cooperating classloaders. Classes
loaded by different classloaders may interact in complex ways not
fully comprehended by a developer, leading to inexplicable errors
or bugs.

Class loading is considerably different to previous
versions of JBoss AS. Class loading is based on the JBoss Modules
project. Instead of the more familiar hierarchical class loading
environment, AS7′s class loading is based on modules that have to
define explicit dependencies on other modules. Deployments in AS7
are also modules, and do not have access to classes that are
defined in jars in the application server unless an explicit
dependency on those classes is defined.

How does it work?

To understand how it works internally we
use
JArchitect and
CQLinq queries to query the JBoss-modules code base.

Let’s start off by finding out what happens when
the main method is invoked by executing the following CQLinq
query:

from m in Methods where m.IsUsedBy
(“org.jboss.modules.Main.main(String[])”)

select new { m, m.NbBCInstructions }

 

The java.lang.Thread.setContextClassLoader()
method is invoked to set the context ClassLoader. The context
ClassLoader can be set when a thread is created, and allows the
creator of the thread to provide the appropriate class loader to
code running in the thread when loading classes and
resources.

Let’s discover the class loaders defined by
JBoss.

from t in Types where !t.IsThirdParty

let depth0 =
t.DepthOfDeriveFrom(“java.lang.ClassLoader”)

where depth0 >= 0 orderby depth0

select new { t, depth0,IsAbstract=t.IsAbstract
}

There are two classes inheriting from
ClassLoader but only ModuleClassLoader could be
instantiated.

 ModuleClassLoader inherit
from ConcurrentClassLoader which inherit from SecureClassLoader
from the jdk. ConcurrentClassLoader is useful to treat dead lock
problems.

Where the ClassModuleLoader is
instantiated:

from m in Methods

let depth0 =
m.DepthOfCreateA(“org.jboss.modules.ModuleClassLoader”)

where depth0 == 1

select new { m, depth0 }

What’s interesting is that each module has its
own class loader, different version of the same jar could be loaded
for different modules loaded.

What’s actually in a module?

To understand what the module is, let’s discover
how a module is described, and here’s an example of a module
descriptor:

<module xmlns=”urn:jboss:module:1.1″
name=”org.jboss.msc”>

<main-class
name=”org.jboss.msc.Version”/>

<properties>

<property name=”my.property”
value=”foo”/>

</properties>

<resources>

<resource-root
path=”jboss-msc-1.0.1.GA.jar”/>

</resources>

<dependencies>

<module name=”javax.api”/>

<module
name=”org.jboss.logging”/>

<module
name=”org.jboss.example”>

<imports>

<exclude-set>

<path
name=”org.jboss.example.tests”/>

</exclude-set>

</imports>

</module>


<!– Optional deps –>

<module name=”javax.inject.api”
optional=”true”/>

<module name=”org.jboss.threads”
optional=”true”/>

<module name=”org.jboss.vfs”
optional=”true”/>

</dependencies>

</module>

A module descriptor is an XML file which
describes the structure, content, dependencies, filtering, and
other attributes of a module.

ConcreteModuleSpec is the class from JBoss
containing these infos. And here’s the dependency graph showing all
classes used by it.

 

A resource is described by the
ResourceLoaderSpec, a dependency by DependencySpec and the
properties by a Map.

Let’s describe each section of the module
descriptor.

Main Class

A module which is defined with a “main-class”
element is said to be executable. In other words, the module name
can be listed on the command line, and the standard static
main(String[]) method in the named module’s “main-class” will be
loaded and executed.

Let’s discover all the methods using directly or
indirectly the ConcreteModuleSpec.mainClass field

from m in Methods

let depth0 =
m.DepthOfIsUsing(“org.jboss.modules.ConcreteModuleSpec.mainClass”)

where depth0 >= 0 orderby depth0

select new { m, depth0 }

 

Many methods use it specially loadModule which
needs to execute it if it’s assigned.

Resources

In order for a module to actually have content,
you must define the “resources” element with at least one resource
root.

A resource root is a specification of a location
where the class loader for a module will look for classes and
resources. Each module has zero or more resource roots, though most
regular modules will contain exactly one, which refers to the JAR
file with the module’s content.

A resource is defined in the code base by the
interface Resource, Let’s search for all classes implementing
it.

from t in Types where t.Implement
(“org.jboss.modules.Resource”)

select new { t, t.NbBCInstructions }

 

 

The resource could be defined by a jar, a path
or a URL path containing the jars.

Properties: The modules API
exposes a method which can read property (string key-value pair)
values from a module. To specify values for these properties you
use the “properties” element which can contain zero or more
“property” elements.

dependencies: A module may
express one or more dependencies on other module(s) via the
“dependencies” element.

A dependency is defined by the Dependency class
which is an abstract class, here are all dependencies classes
inheriting from it.

 

Let’s
search for all methods using directly the Dependency
class.

from m in Methods where m.IsUsing
(“org.jboss.modules.Dependency”)

select new { m, m.NbBCInstructions }

 

The methods addPaths and addExportedPaths treat
all the dependencies specified in the module descriptor, and we can
search for all types used by addPaths.

from t in Types where t.IsUsedBy
(“org.jboss.modules.Module.addPaths(Dependency[],Map,FastCopyHashSet,FastCopyHashSet,FastCopyHashSet,Set)”)

select new { t, t.NbBCInstructions }

As shown in the dependency graph this method
uses the dependencies and also the filters specified in the module
descriptor to assign all possible module dependencies.

Modules management

To manage the modules from a console for
example, JMX is the appropriate solution in the java
world.

Java Management Extensions (JMX) is a Java
technology that supplies tools for managing and monitoring
applications, system objects, devices (e. g. printers) and service
oriented networks. Those resources are represented by objects
called MBeans (for Managed Bean). In the API, classes can be
dynamically loaded and instantiated. Managing and monitoring
applications can be designed and developed using the Java Dynamic
Management Kit.

JBoss-modules conatins the package
org.jboss.modules.management which contains the ModuleLoaderMXBean,
this interface defines methods to get all interesting infos for a
module, and we can also unload the module.

 

This interface is implemented by the
org.jboss.modules.ModuleLoader.MXBeanImpl class.

Conclusion

JBoss Modules is a standalone implementation of a modular
(non-hierarchical) class loading and execution environment for
Java. In other words, rather than a single class loader which loads
all JARs into a flat class path, each library becomes a module
which only links against the exact modules it depends on, and
nothing more. It implements a thread-safe, fast, and highly
concurrent delegating class loader model.

 


 

 



 

 


 



 

 


Author
Comments
comments powered by Disqus