Difference between revisions of "SolvingClassLoaderProblems"

From Protege Wiki
Jump to: navigation, search
m (SolvingClassLoaderProblemsWithKnopflerfish moved to SolvingClassLoaderProblems: Knopflerfish is not part of the story anymore.)
Line 15: Line 15:
  
 
In this case the exception was caused by a trivial stupid typo in the org.protege.common manifest but I was confused at the time and did not figure this out.  So the first item of confusion here might be the question of which class loader is causing the problem.  One might somehow think that this is being caused by the class loader for the org.protege.editor.owl bundle because, in some vague and undefined sense, this sequence of events seemed to be triggered in that bundle.  But this is not how class loaders work.  Actually the class loader that got into trouble (before delegation is taken into account) is the class loader for the org.coode.xml.XMLWriterImp class.  This class loader is the org.semanticweb.owlapi bundle.
 
In this case the exception was caused by a trivial stupid typo in the org.protege.common manifest but I was confused at the time and did not figure this out.  So the first item of confusion here might be the question of which class loader is causing the problem.  One might somehow think that this is being caused by the class loader for the org.protege.editor.owl bundle because, in some vague and undefined sense, this sequence of events seemed to be triggered in that bundle.  But this is not how class loaders work.  Actually the class loader that got into trouble (before delegation is taken into account) is the class loader for the org.coode.xml.XMLWriterImp class.  This class loader is the org.semanticweb.owlapi bundle.
 
+
<p>
 
This should have been enough for me to figure out what happened because (at this time) the org.semanticweb.owlapi bundle imported the package org.apache.commons.lang and the org.protege.common bundle exportedthe package org.apache.commons.lang package.  There were very few things that could go wrong at this point but I didn't see it and I began to doubt my reasoning.
 
This should have been enough for me to figure out what happened because (at this time) the org.semanticweb.owlapi bundle imported the package org.apache.commons.lang and the org.protege.common bundle exportedthe package org.apache.commons.lang package.  There were very few things that could go wrong at this point but I didn't see it and I began to doubt my reasoning.
 
<p>
 
<p>
So I make a knopflerfish distributionI then modify the props.xargs file to set
+
To solve these types of problems I have created a bundle providing some servlets that debug class loading issuesThe source for this bundle can be
 +
found in the svn repository
 
<center>
 
<center>
      -Dorg.knopflerfish.framework.debug.classloader=true.
+
http://smi-protege/repos/protege/protege4/small-projects/org.protege.osgi.debug/trunk
 
</center>
 
</center>
In this mode knopflerfish spits out tons of output describing all its class loading workI work backwards in the resulting output from the exception and find the following log messages:
+
and once it is checked out it can be built with <i>ant dist</i>The result of <i>ant dist</i> will be a relatively minimal OSGi distribution in the directory <i>build/dist/equinox</i> which allows the org.protege.osgi.debug bundle to run.
 
+
To use this with an equinox distribution copy the files
 
<pre>
 
<pre>
## DEBUG: BundleClassLoader(id=14,gen=0) Search for: org/apache/commons/lang/StringEscapeUtils.class
+
  javax.servlet_2.4.0.v200706111738.jar
## DEBUG: BundleClassLoader(id=14,gen=0) Import search: org/apache/commons/lang/StringEscapeUtils.class from #8
+
  org.apache.commons.logging_1.0.4.v200706111724.jar
## DEBUG: BundleClassLoader(id=8,gen=0) Search for: org/apache/commons/lang/StringEscapeUtils.class
+
  org.eclipse.equinox.http.jetty_1.0.1.R33x_v20070816.jar
## DEBUG: BundleClassLoader(id=9,gen=0) Search for: org/protege/editor/core/ui/error/ErrorLog$ErrorLogEntry.class
+
  org.eclipse.equinox.http.servlet_1.0.1.R33x_v20070816.jar
 +
  org.eclipse.osgi.services_3.1.200.v20070605.jar
 +
  org.mortbay.jetty_5.1.11.v200706111724.jar
 +
  org.protege.osgi.debug.jar
 
</pre>
 
</pre>
 
+
into from the org.protege.osgi.debug distribution to the Protege 4 OWL editor's plugin directory.  (Note the exclusion of the   org.eclipse.osgi_3.3.1.R33x_v20070828.jar and  org.eclipse.equinox.common_3.3.0.v20070426.jar files).  Now when the OWL editor is started  these bundles  will automatically be loadedOne indicator that these bundles have been seen  are the following messages  on the console:
I am not including any of the other messages (involving class loaders to present the error to me) because there is no good news after thisThe first line
 
 
 
 
<pre>
 
<pre>
## DEBUG: BundleClassLoader(id=14,gen=0) Search for: org/apache/commons/lang/StringEscapeUtils.class
+
Oct 25, 2007 11:35:46 PM org.mortbay.http.HttpServer doStart
 +
INFO: Version Jetty/5.1.x
 +
Oct 25, 2007 11:35:46 PM org.mortbay.util.Container start
 +
INFO: Started org.mortbay.jetty.servlet.ServletHandler@c7e176
 +
Oct 25, 2007 11:35:46 PM org.mortbay.util.Container start
 +
INFO: Started HttpContext[/,/]
 +
Oct 25, 2007 11:35:46 PM org.mortbay.http.SocketListener start
 +
INFO: Started SocketListener on 0.0.0.0:8080
 +
Oct 25, 2007 11:35:46 PM org.mortbay.util.Container start
 +
INFO: Started org.mortbay.http.HttpServer@787144
 
</pre>
 
</pre>
 
+
These message merely indicate that the http servlet code been initialized.
says that the class loader with the identity 14 initially tries to load the StringEscapeUtils.class.  So I need to figure out which class loader has the id 14.  If I search forwards from the top of the log for the number14, I see the lines
+
<p>
 
 
<pre>
 
## DEBUG: BundleClassLoader(id=14,gen=0) Created new classloader
 
Installed plugin The OWL API
 
</pre>
 
 
 
This means that during the installation of the OWL API the class loader 14 was created.  So it was the OWL API bundle (org.semanticweb.owlapi) that initially tried to load the StringEscapeUtils class.  Just like it should have been. The next two lines
 
 
 
<pre>
 
## DEBUG: BundleClassLoader(id=14,gen=0) Import search: org/apache/commons/lang/StringEscapeUtils.class from #8
 
## DEBUG: BundleClassLoader(id=8,gen=0) Search for: org/apache/commons/lang/StringEscapeUtils.class
 
</pre>
 
says that the owl api bundle (#14) tries to get the definition of the StringEscapeUtils class from the bundle with the number 8.  As before I find out which bundle has the id 8 by searching down from the top of the logs:
 
 
 
<pre>
 
Installed: file:jars/protege/org.protege.common.jar (id#8)
 
</pre>
 
 
 
So the owl api bundle is delegating to org.protege.common just like I thought it should.  At this point there is only one thing that could be wrong and I immediately go to check.  In the manifest the Bundle-Classpath includes an entry lib/commons-lang.jar.  This entry should be lib/commons-lang-2.2.jar.  If I had trusted my logic better I would probably have saved myself some trouble but the knopflerfish debug statements allowed me to determine exactly what parts of my logic were right and what I did wrong.
 

Revision as of 23:38, October 25, 2007

In order to apply the techniques of this section the developer will need to have the ability to capture and navigate the output of a run command and must be able to compile a knopflerfish distribution (ant knopflerfish). Given this I will describe how to debug class loader exceptions (if they cannot be easily figured out and they are giving you a headache). So I recently saw the following exception:

java.lang.NoClassDefFoundError: org/apache/commons/lang/StringEscapeUtils
        at org.coode.xml.XMLWriterImpl.writeEntities(XMLWriterImpl.java:207)
        at org.coode.xml.XMLWriterImpl.startDocument(XMLWriterImpl.java:221)
        at org.coode.owl.rdf.rdfxml.RDFXMLWriter.startDocument(RDFXMLWriter.java:135)
        at org.coode.owl.rdf.rdfxml.RDFXMLRenderer.render(RDFXMLRenderer.java:87)
        at org.coode.owl.rdf.rdfxml.RDFXMLOntologyStorer.storeOntology(RDFXMLOntologyStorer.java:56)
        at uk.ac.manchester.cs.owl.OWLOntologyManagerImpl.saveOntology(OWLOntologyManagerImpl.java:370)
        at org.protege.editor.owl.model.OWLModelManagerImpl.save(OWLModelManagerImpl.java:368)
        at org.protege.editor.owl.OWLEditorKit.handleSave(OWLEditorKit.java:185)
        at org.protege.editor.core.ProtegeManager.saveEditorKit(ProtegeManager.java:187)

In this case the exception was caused by a trivial stupid typo in the org.protege.common manifest but I was confused at the time and did not figure this out. So the first item of confusion here might be the question of which class loader is causing the problem. One might somehow think that this is being caused by the class loader for the org.protege.editor.owl bundle because, in some vague and undefined sense, this sequence of events seemed to be triggered in that bundle. But this is not how class loaders work. Actually the class loader that got into trouble (before delegation is taken into account) is the class loader for the org.coode.xml.XMLWriterImp class. This class loader is the org.semanticweb.owlapi bundle.

This should have been enough for me to figure out what happened because (at this time) the org.semanticweb.owlapi bundle imported the package org.apache.commons.lang and the org.protege.common bundle exportedthe package org.apache.commons.lang package. There were very few things that could go wrong at this point but I didn't see it and I began to doubt my reasoning. <p> To solve these types of problems I have created a bundle providing some servlets that debug class loading issues. The source for this bundle can be found in the svn repository

http://smi-protege/repos/protege/protege4/small-projects/org.protege.osgi.debug/trunk

and once it is checked out it can be built with ant dist. The result of ant dist will be a relatively minimal OSGi distribution in the directory build/dist/equinox which allows the org.protege.osgi.debug bundle to run. To use this with an equinox distribution copy the files

   javax.servlet_2.4.0.v200706111738.jar
   org.apache.commons.logging_1.0.4.v200706111724.jar
   org.eclipse.equinox.http.jetty_1.0.1.R33x_v20070816.jar
   org.eclipse.equinox.http.servlet_1.0.1.R33x_v20070816.jar
   org.eclipse.osgi.services_3.1.200.v20070605.jar
   org.mortbay.jetty_5.1.11.v200706111724.jar
   org.protege.osgi.debug.jar

into from the org.protege.osgi.debug distribution to the Protege 4 OWL editor's plugin directory. (Note the exclusion of the org.eclipse.osgi_3.3.1.R33x_v20070828.jar and org.eclipse.equinox.common_3.3.0.v20070426.jar files). Now when the OWL editor is started these bundles will automatically be loaded. One indicator that these bundles have been seen are the following messages on the console:

Oct 25, 2007 11:35:46 PM org.mortbay.http.HttpServer doStart
INFO: Version Jetty/5.1.x
Oct 25, 2007 11:35:46 PM org.mortbay.util.Container start
INFO: Started org.mortbay.jetty.servlet.ServletHandler@c7e176
Oct 25, 2007 11:35:46 PM org.mortbay.util.Container start
INFO: Started HttpContext[/,/]
Oct 25, 2007 11:35:46 PM org.mortbay.http.SocketListener start
INFO: Started SocketListener on 0.0.0.0:8080
Oct 25, 2007 11:35:46 PM org.mortbay.util.Container start
INFO: Started org.mortbay.http.HttpServer@787144

These message merely indicate that the http servlet code been initialized.

<p>