J2EE ClassLoading Explained

by Jyotheeswara Naidu Malapati

Every java class file will be loaded by JVM before it gets executed. It uses the component called ‘Class Loader’ . Without class loader simply your java applications will not work.

Class Loader concept is one of the most searched topic on web by developers and it is also one of the misunderstood concept.

Let us see this Class loading in detail

What’s the Class Loader Job?

This is a Java Component and the simple job of it is loading the java byte code from the file system and executing them on the Java Virtual Machine ( JVM ). It just pretty simple isn’t it?

No, It is not so simple because most of the developers are getting still ClassNotFoundExceptions.

 

Let’s first take a look into the Hierarchy of the ClassLoader.

The above diagram shows the hierarchy structure of the class loader.

Null classloader:

This is the first class loader in the hierarchy and this one loads platform specific
Java Runtime Environment classes.

System ClassLoader :

Loads java library classes which are underJRE\lib directory

Bootstrap ClassLoader:

This loads the necessary classes to run your J2EE application in the was environment.
It loads the library classes to support J2EE specification ( loads the classes sitting under path WAS \ lib directory )

Application ClassLoader:

This is one loads your application stuff ( classes under your ear file, WAR,RAR,jar files etc).

What happens when one of these classloaders can not find the class you’re interested in? Answer is simple, you will get ClassNotFoundExceptions

The hierarchy of the classloaders is very cool because it actually offers a secure and consistant behaviour preventing our cute developers hacking in the prebuilt classes. For e.g., Developers could write their own version of java.lang.Integer.

The way the hierarchy works when you call this

Class.forName("com.codedairy.EmployeeDetails"); // OR

com.codedairy.EmployeeDetails empDetails = new com.codedairy.EmployeeDetails();

in your code, Your application loader first passes the control to its parent to check if it can load this class before trying to look in its
class path. So it’s parent which is BootStrapClassLoader will intern ask its parent which is SystemClassLoader. We know that these class loaders
will not find your EmployeeDetails class because this class file is sitting in your ear in some jar (say employee.jar).
Finally, the class loaders above
the ApplicationClassLoader will handover job back to ApplicationClassLoader and says “Hey ApplicationClassLoader”, the class file
you asked me load doesn’t appear in our path mate. Why don’t you look in your class path?”.

The Application class loader will look-in his class path, finds it and loads class on to the JVM.

For e.g., When you have a code referencing to the classes like java.lang.Integer, java.util.* will not be loaded by
ApplicationClassLoader even though you have hacked this class and placed this in your ear because the way the class loading
hierarchy works.It first handovers to its parent which eventually find a class because these classes will be loaded by your System ClassLoader

This is how the class loader works in Java J2EE Applications.

What is PARENT_LAST or PARENT_FIRST ?

This is some thing Websphere has introduced to us and provide flexiblity to the
change the class loader hierarchy behavior slightly.

Consider a secnario where your application is running with a Third party library which are shared libararies across multiple applications
and they are placed in your Bootstrap class loader and your application isn’t working now becuase there seems to be a bug in the that third
party library jar. You would not want update that jar and put it back to its calsspath. Instead the updated jar alone you want to apply to
your application. In that case, you can change the class loader behaviour to PARENT_LAST which means it will only handover job of look for a class
to its parent only if it can’t find in its classpath.

PARENT_FIRST:

This is the default behaviour of your application. Looks for a class first in their parent class loaders before lookin in its class path.

PARENT_LAST :

This will first look for a requested class in the current class loader before asks its parent.

Where should I change the settings of PARENT_FIRST / PARENT_LAST?

You can chane this settings in your application deployment descriptor as shown in the below screenshot.

What is Single ClassLoader?

if you have an WAR modules in your application. You can have a single class loader for your application in which case your provide access to the classes
of web module in the ear level. That means you’ll have only one class loader for your entire application.

How to change my application to use a single classloader?

Change your WAR module class loader policy settings in the application.xml to “Application”.
Bydefault its set to MODULE which will use its own class loader.

Thanks for reading my post. please do not hesitate to post your comments or ask any questions below ( or even you find any mistakes too :-) )

This is a sticky post! continue reading?

Registering WebSphere MQ JMS client with the application server due to exception

Websphere MQ JMS Client registering error on the application start up

Error:
[8/31/13 22:04:57:897 BST] 0000000e JMSRegistrati E   WMSG1603E: An internal error occurred. It was not possible to register the WebSphere MQ JMS client with the application server due to exception org.osgi.framework.BundleException: An error occurred trying to read the bundle
	at org.eclipse.osgi.internal.baseadaptor.BundleInstall.begin(BundleInstall.java:94)
	at org.eclipse.osgi.framework.internal.core.Framework.installWorkerPrivileged(Framework.java:823)
	at org.eclipse.osgi.framework.internal.core.Framework$2.run(Framework.java:739)
	at java.security.AccessController.doPrivileged(AccessController.java:241)
	at org.eclipse.osgi.framework.internal.core.Framework.installWorker(Framework.java:790)
	at org.eclipse.osgi.framework.internal.core.Framework.installBundle(Framework.java:734)
	at org.eclipse.osgi.framework.internal.core.BundleContextImpl.installBundle(BundleContextImpl.java:221)
	at com.ibm.ejs.jms.JMSRegistration.installBundle(JMSRegistration.java:860)
	at com.ibm.ejs.jms.JMSRegistration.destroy(JMSRegistration.java:1031)
	at com.ibm.ws.runtime.component.ContainerImpl.destroyComponents(ContainerImpl.java:1070)
	at com.ibm.ws.runtime.component.ContainerImpl.destroy(ContainerImpl.java:662)
	at com.ibm.ws.runtime.component.ServerImpl.destroy(ServerImpl.java:480)
	at com.ibm.ws.runtime.component.ServerCollaborator$ShutdownHook$1.run(ServerCollaborator.java:688)
	at com.ibm.ws.security.auth.ContextManagerImpl.runAs(ContextManagerImpl.java:4276)
	at com.ibm.ws.security.auth.ContextManagerImpl.runAsSystem(ContextManagerImpl.java:4373)
	at com.ibm.ws.runtime.component.ServerCollaborator$ShutdownHook.run(ServerCollaborator.java:677)
	at com.ibm.ws.runtime.component.ServerCollaborator$StopAction.alarm(ServerCollaborator.java:641)
	at com.ibm.ejs.util.am._Alarm.run(_Alarm.java:91)
	at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1593)
Caused by: java.io.IOException: The directory "/usr/websphere6/was61_A2/AppServer/configuration/org.eclipse.osgi/bundles/65/1" could not be created
	at org.eclipse.osgi.internal.baseadaptor.BundleInstall.begin(BundleInstall.java:68)
	... 18 more

Solution

Check the permissions on the file system for “org.eclipse.osgi” and
make sure the ownership is set to the “wasdmin”.
this should resolve this error.

Eclipse internal Error – .fileTableLock access is denied

Error / Problem:
Eclipse internal Error – .fileTableLock access is denied

Stack Trace/Error Log:

!ENTRY org.eclipse.osgi 4 0 2013-08-21 15:00:19.904
!MESSAGE Error reading configuration: C:\Apps\IBM\SDP70\configuration\org.eclipse.osgi\.manager\.fileTableLock (Access is denied.)
!STACK 0
java.io.FileNotFoundException: C:\Apps\IBM\SDP70\configuration\org.eclipse.osgi\.manager\.fileTableLock (Access is denied.)
at java.io.RandomAccessFile.open(Native Method)
at java.io.RandomAccessFile.<init>(Unknown Source)
at org.eclipse.core.runtime.internal.adaptor.Locker_JavaNio.lock(Unknown Source)
at org.eclipse.osgi.storagemanager.StorageManager.lock(Unknown Source)
at org.eclipse.osgi.storagemanager.StorageManager.open(Unknown Source)
at org.eclipse.osgi.internal.baseadaptor.BaseStorage.initFileManager(Unknown Source)
at org.eclipse.osgi.internal.baseadaptor.BaseStorage.initialize(Unknown Source)
at org.eclipse.osgi.baseadaptor.BaseAdaptor.initializeStorage(Unknown Source)
at org.eclipse.osgi.framework.internal.core.Framework.initialize(Unknown Source)
at org.eclipse.osgi.framework.internal.core.Framework.<init>(Unknown Source)
at org.eclipse.osgi.framework.internal.core.OSGi.createFramework(Unknown Source)
at org.eclipse.osgi.framework.internal.core.OSGi.<init>(Unknown Source)
at org.eclipse.core.runtime.adaptor.EclipseStarter.startup(Unknown Source)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.core.launcher.Main.invokeFramework(Unknown Source)
at org.eclipse.core.launcher.Main.basicRun(Unknown Source)
at org.eclipse.core.launcher.Main.run(Unknown Source)
at org.eclipse.core.launcher.Main.main(Unknown Source)

Solution: I solved this problem by modifying the parent directory “SDP70″ permissions, to allow all users read/write access.

Also, I found the below useful link on the IBM Support  http://www-01.ibm.com/support/docview.wss?uid=swg21599845