bug-jel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug-jel] Re: Class Not Found


From: Konstantin L. Metlov
Subject: [Bug-jel] Re: Class Not Found
Date: Wed, 20 Nov 2002 21:16:18 +0100 (CET)

Dear Nayan Hajratwala,

The situation you have encountered is not a bug in JEL, but rather a 
manifestation of intricacy of Java classloaders.

In short, the problem is related to the fact that your class
"com.ford.hr.framework.user.IUser" might be present in the classpath TWICE
by being accessible by two _different_ classloaders at the same time. This
often happens in a servlet engines having both "default" and so called
"zone-specific" classloaders.

The solution is to load JEL (preferably as a whole, but loading only
gnu.jel.ImageLoader class is sufficient) into your JVM using the same
"zone-specific" classloader your classes (e.g. 
com.ford.hr.framework.user.IUser) are loaded with.

Thank you for your interest in JEL !

If some questions still remain, please ask.

With the best regards,
                          Konstantin.



                                 APPENDIX

For more detailed explanation, please read the following excerpt from my
E-mail to one of JEL users having the same problem (in this explanation
class "Message" plays the same role as your
"com.ford.hr.framework.user.IUser", and "TestRouter" stands for a class
within your package referring to "com.ford.hr.framework.user.IUser"  
directly, e.g. not through JEL):

--------------
First, a little of common knowledge (probably redundant). A ClassLoader is
a java class, which loads other Java classes into the memory of Java VM
and maintains their namespace. Actually, the only way to load a bytecode
into JVM is via a ClassLoader of some kind. There can be several
classloaders active at the same time, and, thus several namespaces.

Servlet engines, often, separate different parts of the web site
(sometimes they are called "servlet zones") by using different
classloaders for each zone. Additionally, in each JVM instance, there is a
"default" classloader, which loads classes from a global JVM classpath.

When loading compiled expressions into JVM, JEL does it in the same
context (e.g. in the namespace of the same classloader) the class
gnu.jel.ImageLoader (a part of JEL library) was loaded.  This means, if
JEL is in the global classpath -- the compiled expressions will be loaded
in the context of "default" classloader. Servlets, on the other hand, are
loaded by a classloader specific to their "servlet zone".

The problem arizes when JEL is loaded by "default" classloader and the
same classes (in your case "Message") can be loaded both by "default" and
zone-specific classloaders (e.g. they are on "classpath" of both). In this
case, when expression is compiled the byte code contains only a link to
Message class. When it is loaded into JVM this link is resolved using the
"default" classloader and your Message class is loaded by it. On the other
hand, there exists another instance of Message class (please note the
difference with object), which is loaded by zone-specific classloader
(the one, which allows you to access Message from within your
HttpServlet implementation).

Next, when you call the expression, you pass the instance of Message class
held in Router.msg (which was loaded by zone-specific classloader) into
JEL expression, containing the reference to Message class (which was
loaded by "default" classloader). The main point is that these two classes
are considered DIFFERENT by JVM and can not be converted into one another.

See e.g.

http://216.239.53.100/search?q=cache:A0_GzRToobgC:www.dcs.gla.ac.uk/~huw/papers/eufurt.ps.gz+%22two+classes+with+the+same+name%22+%22different+classloaders%22+ClassCastException&hl=en&ie=UTF-8

for reference.

Therefore, please check that the whole JEL (and gnu.jel.ImageLoader in
particular) is loaded into your JVM not via global CLASSPPATH, but through
the same zone-specific classloader you use to load TestRouter class.
---------------------

and its continuation, with some simple pictures:
---------------------
May be this will explain the situation with classloaders better.

Each classloader has a "parent" classloader to which it passes the
requests to load the classes it can not resolve. This allows to organize
classloaders into a tree (since a single classloader can be a parent of
many). The "default" classloader is a root.

WRONG SITUATION

          |-------->    "default"
          |    namespace:
          |    java.lang.*
          |    java.net.*
          |    ...
          |    gnu.jel.ImageLoader(g.j.I)
          |    Message
          |
          |------------------------------- ....    -------
          |                  |                            |
     g.j.I (instance1)  g.j.I (instance2)           servlet classloader
     namespace:         namespace:                  namespace:
     gnu.jel.E_1        gnu.jel.E_2                 TestRouter
                                                    Message

The class message appears in two namespaces. This is because the compiled
expression refers to it, at its load time the g.j.I classloader, obviously
(because it does not know about anything except JEL expressions), passes
the request to load its parent (which is "default" classloader in this
case). The second Message appears in servlet classloader namespace because
TestRouter refers to it, and this reference is resolved upon loading of
the TestRouter class.

CORRECT SITUATION


          |-------->    "default"
          |    namespace:
          |    java.lang.*
          |    java.net.*
          |    ...
          |
          ---------------
                         |
                         |
          ------> servlet classloader
          |    namespace:
          |    TestRouter
          |    Message
          |    ...
          |    gnu.jel.ImageLoader
          |
          |------------------------------- ....
          |                  |
     g.j.I (instance1)  g.j.I (instance2)
     namespace:         namespace:
     gnu.jel.E_1        gnu.jel.E_2

In this case the parent of JEL classloaders is "servlet classloader", to
which g.j.I (correctly) readdressed request to load Message class, so that
only one instance of Message class exists in JVM.

One g.j.I per compiled expression is required to enable the garbage
collection of classes (additionally to objects).
---------------









reply via email to

[Prev in Thread] Current Thread [Next in Thread]