You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Michel Costa <mc...@agem.com.br> on 2006/01/11 14:01:07 UTC
Problems Using Context Loader
Hi everyone,
I am trying to create a ClassLoader for my application so then I will not have to reload all the hibernate and struts when a new class is compiled.
Then my problems started:
I do not know where to put my special ClassLoader.
I got lots of classcast exceptions until I found that a instance of org.apache.catalina.loader.WebappClassLoader.
So far so good, just extended my class and apache can't find org.apache.catalina.loader.WebappClassLoader.
Now I have a java.lang.ClassNotFoundException: org.apache.catalina.loader.WebappClassLoader
I think the error is just because I put my classloader in the wrong place (which is CATALINA_HOME/common/classes) but i could not avoid this common folder... Before this one, I tried webapps/MYAPP/WEB-INF/classes but java didnt found my class.
My guess is something about the ClassLoader hierarchy and visibility of the classes...
Well... here goes some info:
I am runing catalina on a linux workstation, ubuntu.
my app's context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Loader loaderClass="DeployerClassLoader" delegate="false" reloadable="false"/>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
</Context>
the tomcat output:
11/01/2006 10:56:33 org.apache.catalina.loader.WebappLoader start
SEVERE: LifecycleException
java.lang.NoClassDefFoundError: org/apache/catalina/loader/WebappClassLoader
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:299)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:164)
at org.apache.catalina.loader.WebappLoader.createClassLoader(WebappLoader.java:769)
at org.apache.catalina.loader.WebappLoader.start(WebappLoader.java:638)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4076)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:759)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:739)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:524)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:910)
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:873)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:474)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1118)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:310)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1020)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:718)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1012)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:442)
at org.apache.catalina.core.StandardService.start(StandardService.java:450)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:700)
at org.apache.catalina.startup.Catalina.start(Catalina.java:551)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:275)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
11/01/2006 10:56:33 org.apache.catalina.core.ContainerBase addChildInternal
SEVERE: ContainerBase.addChild: start:
LifecycleException: start: : java.lang.NoClassDefFoundError: org/apache/catalina/loader/WebappClassLoader
at org.apache.catalina.loader.WebappLoader.start(WebappLoader.java:675)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4076)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:759)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:739)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:524)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:910)
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:873)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:474)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1118)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:310)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1020)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:718)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1012)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:442)
at org.apache.catalina.core.StandardService.start(StandardService.java:450)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:700)
at org.apache.catalina.startup.Catalina.start(Catalina.java:551)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:275)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org
Re: Problems Using Context Loader
Posted by Michel Costa <mc...@agem.com.br>.
The major problem is not about putting hibernate in the context's lib folder, but as you may know, hibernate does some mapping stuff, which means it reads a bunch of .hbm.xml files into memory, connects and validate these mappings everytime the context gets reloaded, and depending on how much mappings you use, a bigger problem you have, about the loading time... It takes about 30 seconds for each reload and a maximum of 4 reloads.
The difficult part of it is to make my custom ClassLoader access the webapp's classloader... because it must be placed in the server folder and because of this, it is not in the webapp's classloader hiearchy.
Mine implementation speed is a little slow, i am just trying to load the classes primarly, with no errors, and then is time to think about reloading... I think it would be much easier if I could monitorate these files directly from the WebApp's classloader, but this means modify tomcat's distribution.
This is all I have done so far:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.AccessControlException;
import java.util.Hashtable;
import org.apache.catalina.loader.WebappClassLoader;
public class DeployerClassLoader extends WebappClassLoader {
private static Hashtable<String, Class> classes = new Hashtable<String, Class>();
private String rootFolder;
public DeployerClassLoader(ClassLoader parent) {
super(parent);
init();
showTree(this, "");
}
private String showTree(ClassLoader cls, String pre) {
if (cls.getParent() != null) {
pre = showTree(cls.getParent(), pre);
}
System.out.println(pre + " - " + cls.getClass().toString());
return pre + " ";
}
private void init() {
System.out.println("!!!calling init!!!");
rootFolder = "/opt/tomcat/webapps/AppRoot/WEB-INF/classes/";
}
private byte[] findInPath(String name) {
String path = name.replaceAll("\\.", "/");
File fClass = new File(rootFolder + path + ".class");
if (fClass.exists()) {
try {
FileInputStream fStream = new FileInputStream(fClass);
byte[] all = new byte[(int) fClass.length()];
fStream.read(all);
return all;
} catch (FileNotFoundException e) {
return null;
} catch (IOException e) {
return null;
}
}
return null;
}
protected Class findLoadedClass0(String name) {
System.out.println("findLoaded: " + name);
if (name.startsWith("br.com.agem.sige")) {
// se encontrar chamar defineClass(String name, byte[] b, int off,
// int len)
if (classes.get(name) != null)
return classes.get(name);
}
return super.findLoadedClass0(name);
}
protected Class findClassInternal(String name) throws ClassNotFoundException {
byte[] data = findInPath(name);
if (data != null) {
synchronized (this) {
Class c = defineClass(name, data, 0, data.length);
classes.put(name, c);
return c;
}
}
throw new ClassNotFoundException(name);
}
public Class findClass(String name) throws ClassNotFoundException {
if (!started) throw new ClassNotFoundException(name);
// (1) Permission to define this class when using a SecurityManager
if (securityManager != null) {
int i = name.lastIndexOf('.');
if (i >= 0) {
try {
securityManager.checkPackageDefinition(name.substring(0,i));
} catch (Exception se) {
throw new ClassNotFoundException(name, se);
}
}
}
// Ask our superclass to locate this class, if possible
// (throws ClassNotFoundException if it is not found)
Class clazz = null;
try {
clazz = findClassInternal(name);
} catch(ClassNotFoundException cnfe) {
} catch(AccessControlException ace) {
throw new ClassNotFoundException(name, ace);
}
if (clazz == null) try {
clazz = super.findClass(name);
} catch(AccessControlException ace) {
throw new ClassNotFoundException(name, ace);
}
if (clazz == null) throw new ClassNotFoundException(name);
return clazz;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org
Re: Problems Using Context Loader
Posted by Sriram Narayanan <sr...@gmail.com>.
On 1/12/06, Michel Costa <mc...@agem.com.br> wrote:
> No, that is not a Tomcat problem... it's a specific application problem... I saw some people complaining about the same things in applications similar to mine.
>
By "No, that is not a Tomcat problem...", I believe you're saying that
there's no problem related to startup etc.
Ack on the statement that you're talking about an application specific problem.
> The big whole problem with my application is the framework usage: Hibernate and Struts...
> My guess is that hibernate is not finalizing normally (i done some tests restarting the context using only struts and garbage collecting and checking the amount of free memory)... cause when I restart the context about 4 times using hibernate and struts there is no more free memory neither memory to allocate. It ends with a Heap space error.
>
Ack. So you're placing hibernate in the Context's WEB-INF/lib folder ?
I haven't used Hibernate yet, but will do so to understand this issue.
> Every time a new class is compiled during development the context must be restarted to update the class reference, so now we have a problem.
>
> My way out is to make a classloader to monitor these classes in classes folder and auto-update the reference...
Is this what you want ?
a) Hibernate etc are loaded just once.
b) Your apps' classes are monitored and when ever they change, a fresh
classloader is instantiated.
c) At this time, Hibernate etc are not to be reloaded.
d) Hibernate and Struts and anyone else should continue to to have
access to the latest classes.
I see a problem with Hibernate having a reference to the older classes
(perhaps in objects that are cached, etc. I don't know for sure, I'm
just speculating here). This would be an interesting problem to solve.
If you don't get this right, then let me know, I'd like to help. I'm
interesting in solving this classloader requirement as well - it'll be
a good exercise for the mind :)
> Wish me luck ;-)
>
Best of luck :)
> I will take a look at your idea... but seems you are not trying to reload the classes references.
>
Correct. It was just something I put together late at night. I'm
considering adding stuff like monitoring for changes in the classes
mentioned in these paths, etc. I'll look into this. Let me know if
you'd like to see some feature.
-- Sriram
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org
Re: Problems Using Context Loader
Posted by Michel Costa <mc...@agem.com.br>.
No, that is not a Tomcat problem... it's a specific application problem... I saw some people complaining about the same things in applications similar to mine.
The big whole problem with my application is the framework usage: Hibernate and Struts...
My guess is that hibernate is not finalizing normally (i done some tests restarting the context using only struts and garbage collecting and checking the amount of free memory)... cause when I restart the context about 4 times using hibernate and struts there is no more free memory neither memory to allocate. It ends with a Heap space error.
Every time a new class is compiled during development the context must be restarted to update the class reference, so now we have a problem.
My way out is to make a classloader to monitor these classes in classes folder and auto-update the reference...
Wish me luck ;-)
I will take a look at your idea... but seems you are not trying to reload the classes references.
------------- Segue mensagem original! -------------
De: Sriram Narayanan <sr...@gmail.com>
Data: Thu, 12 Jan 2006 01:59:21 +0530
Para: Tomcat Users List <us...@tomcat.apache.org>
Assunto: Re: Problems Using Context Loader
On 1/11/06, Michel Costa <mc...@agem.com.br> wrote:
> Hi everyone,
>
> I am trying to create a ClassLoader for my application so then I will not have to reload all the hibernate and struts when a new class is compiled.
>
Could you please explain why this is a problem ? Is the startup time an issue ?
> Then my problems started:
> I do not know where to put my special ClassLoader.
> I got lots of classcast exceptions until I found that a instance of org.apache.catalina.loader.WebappClassLoader.
> So far so good, just extended my class and apache can't find org.apache.catalina.loader.WebappClassLoader.
>
I'd taken another approach. See
http://issues.apache.org/bugzilla/show_bug.cgi?id=38223
> Now I have a java.lang.ClassNotFoundException: org.apache.catalina.loader.WebappClassLoader
>
> I think the error is just because I put my classloader in the wrong place (which is CATALINA_HOME/common/classes) but i could not avoid this common folder... Before this one, I tried webapps/MYAPP/WEB-INF/classes but java didnt found my class.
> My guess is something about the ClassLoader hierarchy and visibility of the classes...
>
You place your class at CATALINA_HOME/server/classes. See the bug
report that I've filed for information on how I used my own
Classloader.
-- Sriram
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org
Re: Problems Using Context Loader
Posted by Sriram Narayanan <sr...@gmail.com>.
On 1/11/06, Michel Costa <mc...@agem.com.br> wrote:
> Hi everyone,
>
> I am trying to create a ClassLoader for my application so then I will not have to reload all the hibernate and struts when a new class is compiled.
>
Could you please explain why this is a problem ? Is the startup time an issue ?
> Then my problems started:
> I do not know where to put my special ClassLoader.
> I got lots of classcast exceptions until I found that a instance of org.apache.catalina.loader.WebappClassLoader.
> So far so good, just extended my class and apache can't find org.apache.catalina.loader.WebappClassLoader.
>
I'd taken another approach. See
http://issues.apache.org/bugzilla/show_bug.cgi?id=38223
> Now I have a java.lang.ClassNotFoundException: org.apache.catalina.loader.WebappClassLoader
>
> I think the error is just because I put my classloader in the wrong place (which is CATALINA_HOME/common/classes) but i could not avoid this common folder... Before this one, I tried webapps/MYAPP/WEB-INF/classes but java didnt found my class.
> My guess is something about the ClassLoader hierarchy and visibility of the classes...
>
You place your class at CATALINA_HOME/server/classes. See the bug
report that I've filed for information on how I used my own
Classloader.
-- Sriram
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org