david
david

Reputation: 2142

tomcat - reload classes dynamically

I have a folder with a lot of .class files. This classes are updated from 'app 1'. And there is 'app 2' that loads those classes dinamically.

And the problem is....

'app 2' uses a class file, 'app 1' update that file, then 'app 2' needs again the class but it seemes to keep and to use a copy of the older class.

so, I checked the folder and the class was updated successfully, I tried to reload 'app 2' but it keeps using the older class.

Only if I restart tomcat 'app 2' reads the new class.

Why is that? I'm allowed to reload 'app 2' but, in production enviroment, I cant restart tomcat.

Its very important in my job, I appreciate any idea.....

I'm using a clean installation of tomcat6 and I load the class files with: Class.forName(<classname>).newInstance()

thx a lot

Upvotes: 1

Views: 7908

Answers (4)

Martin Algesten
Martin Algesten

Reputation: 13620

Default behaviour is that classes are cached by the ClassLoader that loaded them. If you do: Class.forName('MyClass') two times in a row, you will only load the class the first time.

To reload a class, you need not only to release any reference you already have to any instance of this class, but also any reference you have to the ClassLoader that loaded it. Only then can you be sure the whole class can be garbage collected (or you will end up with memory leaks - a perennial problem in reloading webapps).

You may be able to extends ClassLoader and alter the caching behaviour.

Upvotes: 2

Alex Marshall
Alex Marshall

Reputation: 10312

The problem is that the runtime has already loaded the old classfile into the classloader being used by the code that wants to use the modified class. You'd have to find a way to get the classloader to refresh its class contents from disk in order to achieve what you want. This is why Class.forName() isn't working : it's accessing the already loaded (and cached) version of the class. Alex R is right that you should try to restructure your code to separate your classes for these two projects. But, if you're dead set on trying to reload that class and keep things they way they are, you can try experimenting with Classloader.defineClass() and loading the new version of the class from its .class File into a byte[], then passing that byte[] to Classloader.defineClass(). You'll most likely want to use the context classloader associated with your application by Tomcat (rather than the top level Tomcat classloader). There's documentation distinguishing between the two in the Tomcat project documentation.

Upvotes: 3

AlexR
AlexR

Reputation: 115328

I think that you should try to separate classes for these 2 applications. Try first to create 2 identical directories. One for app1, second for app2. If this solves your problem pack your classes into jar and keep just 2 duplicate jar files. I think that the problem is not in java but in filesystem. I believe that you are using windows. If so probably try to do what you are doing now in linux (unless it is irrelevant for your company).

Upvotes: 0

Related Questions