Java Reflection - Buffering?

At the moment, I am programming a web project, which is extensible at runtime.

After I uploaded a new module, which i want to install, i am checking, if this module contains a specific class and if this class implements a specific interface.

Class initclass = Class.forName("aecp." + m.getName() +".InitModule");

if (initclass.getInterfaces().length > 0 && initclass.getInterfaces()[0].getName().compareTo("aecp.backbone.module.iModule") == 0)

m is the module uploaded before.

The complete classname is then for example "aecp.Testmodul.InitModule".

The Problem:

I have created 2 identical modules (also name of the module and so the package name), with only one difference: one module implements this specific interface, the other does not.

When I check this at runtime, the first verification works correctly, but when I upload the second module and overwrite the first (and so this one class too), I get the same result as before, so the incorrect file is shown as correct and contrariwise.

Is this a misfeature of Java or what can I do against that?

I am using Java 1.6.0 and Windows XP Professional SP2.

Thank you!

[1311 byte] By [Hannes_Rannesa] at [2007-11-26 13:30:52]
# 1
I'd say, it's because you can only load a class once within the same class loader (which is what you do using Class.forName()). If you inverse the order of loading classes, you should get a positive result each time.
stefan.schulza at 2007-7-7 20:37:14 > top of Java-index,Core,Core APIs...
# 2

Yes, I always get the same result, which depends on the first checked class file.

So that means that the Class.forName(...) result is buffered? There is no way to reset this buffer?

Otherwise I would just know one solution:

I will have to rename the package first in a temporary folder, then check it and then rename it to e.g. "Testmodul".

EDIT:

That also doesn't work, because then the package-information are not correct. :(

EDIT:

There is a similar thing what does not work how it should.

Again 2 similar modules except one thing:

File 1: package aecp.Testmodul;

File 2: package aecp.Testmodul2;

Both are extracted to aecp/Testmodul2/...

When I extract the first file first, it does not work:

"aecp/Testmodul2/InitModul (wrong name: aecp/Testmodul/InitModul)"

When I then extract the second (correct) file, this second does not work too.

When I start with the second, both work.

I deleted the old files between to make sure, that the first uploaded files are not overwritten and checked it too, but there are really the new files in the folder.

Java seems to buffer such data...

Message was edited by:

Hannes_Rannes

Hannes_Rannesa at 2007-7-7 20:37:14 > top of Java-index,Core,Core APIs...
# 3

> Is this a misfeature of Java or what can I do against

> that?

To do hotloading a typical app must be able to do the following

1. Provide a custom class loader

2. The class loader loads the target class

3. A proxy exists which uses an instantiation of the target class (there are many variations on this.)

To reload the target class the following must occur

1. A trigger event occurs

2. The proxy disallows current processing

3. The proxy drops all references to the targer

4. A new custom class loader is created

5. A new instance of the target class is instantiated

6. The proxy hooks into the new instance

7. The proxy unblocks.

There are many variations on the above but the the basic logic is that a custom class loader must exist and the target class must ONLY be accessed via that class loader.

In your case the problem is that you do not have a custom class loader.

Note that the interface should be loaded via the system class loader and not via the custom class loader. Normally this will mean that it must be in a different package.

jschella at 2007-7-7 20:37:14 > top of Java-index,Core,Core APIs...
# 4

Thank you very much!

I got help just some minutes before and this link:

http://mindprod.com/jgloss/reloading.html

In the meantime I decided, that I will use a different, simpler way:

I will recommend a restart of the Tomcat Server and the JVM. It should not happen very often, that I have to install 2 versions of a module one after another.

I just have to find a way how to notice, when the server was restarted.

Hannes_Rannesa at 2007-7-7 20:37:14 > top of Java-index,Core,Core APIs...
# 5

> The Problem:

> I have created 2 identical modules (also name of the

> module and so the package name), with only one

> difference: one module implements this specific

> interface, the other does not.

That's the problem all right. Why do you have to do anything so abstruse as this?

ejpa at 2007-7-7 20:37:14 > top of Java-index,Core,Core APIs...
# 6

> That's the problem all right. Why do you have to do

> anything so abstruse as this?

They don't have to be completely identical. But when I have a module installed and I want to install a newer version of this module, it won't work.

The class-Files are replaced, but the old Files are still loaded by the JVM.

Hannes_Rannesa at 2007-7-7 20:37:14 > top of Java-index,Core,Core APIs...
# 7

> In the meantime I decided, that I will use a

> different, simpler way:

> I will recommend a restart of the Tomcat Server and

> the JVM. It should not happen very often, that I have

> to install 2 versions of a module one after another.

Not sure what you mean, but you can't have two different classes with the same name in the context of a single class loader.

Restarting lets you replace an existing one, not add another.

jschella at 2007-7-7 20:37:14 > top of Java-index,Core,Core APIs...
# 8
No I mean that I replace the old classes (which are still loaded by the JVM), but when I then restart the JVM, the new classes should be loaded.
Hannes_Rannesa at 2007-7-7 20:37:14 > top of Java-index,Core,Core APIs...
# 9

> No I mean that I replace the old classes (which are

> still loaded by the JVM), but when I then restart the

> JVM, the new classes should be loaded.

If you are restarting the VM then there is no point in using a class loader.

You only need a class loader if you can not restart the VM.

jschella at 2007-7-7 20:37:14 > top of Java-index,Core,Core APIs...
# 10

Yes, that's exactly what I want.

I let everything how it is (I don't use a class loader), but I will "force" a restart of the JVM.

But when I really want to force the restart, I would have to know, when the JVM was restarted and when the programm can give full access to the functions again.

Hannes_Rannesa at 2007-7-7 20:37:14 > top of Java-index,Core,Core APIs...
# 11

> Yes, that's exactly what I want.

>

> I let everything how it is (I don't use a class

> loader), but I will "force" a restart of the JVM.

>

> But when I really want to force the restart, I would

> have to know, when the JVM was restarted and when the

> programm can give full access to the functions again.

Double huh?

If the VM is restarted then there is no "access" to classes until they are loaded. Once they are loaded then they are "assessible".

So I have no idea what you are talking about.

Stating it again...

If you can't restart the VM then to change an existing class you must be able to hot load it which requires a a custom class loader.

If you can restart the VM then you don't need to do anything at all.

jschella at 2007-7-7 20:37:14 > top of Java-index,Core,Core APIs...
# 12

No, I mean, I want to restrict the access to the updated/new classes/specific functions, until the JVM is restarted.

1. Normal mode

2. Some changes (module installed)

3. Restrict access to specific functions

4. Restart JVM

5. Full access to all functions

But how should I know, that the JVM has already been restarted?

Hannes_Rannesa at 2007-7-7 20:37:14 > top of Java-index,Core,Core APIs...
# 13
> But how should I know, that the JVM has already been> restarted?You use a static variable that's initialized to false and set to true after step 2.
DrClapa at 2007-7-7 20:37:14 > top of Java-index,Core,Core APIs...
# 14

I think that isn't this easy. The whole thing isn't a "normal", single-user Java-programm.

This changes would just affect the actual session, so everybody else resp. the user before himself when he logs himself out and in again, would have full access again.

So I have to save that in the database and query that.

Probably it's not possible to check that, so that I only can recommend a restart and the user himself is responsible for the rest.

I hope you could understand everything, my English isn't this good! ;-)

Hannes_Rannesa at 2007-7-7 20:37:14 > top of Java-index,Core,Core APIs...
# 15

> No, I mean, I want to restrict the access to the

> updated/new classes/specific functions, until the JVM

> is restarted.

>

> 1. Normal mode

> 2. Some changes (module installed)

> 3. Restrict access to specific functions

> 4. Restart JVM

> 5. Full access to all functions

>

> But how should I know, that the JVM has already been

> restarted?

Unless you use a custom class loader the VM will NOT reload classes. I don't care what you do with them the VM will not use them.

So are you using a custom class loader or not?

jschella at 2007-7-7 20:37:15 > top of Java-index,Core,Core APIs...
# 16
No, when I restart the JVM, the new classes should be loaded too, aren't they?(No I'm not using a custom class loader.)
Hannes_Rannesa at 2007-7-7 20:37:15 > top of Java-index,Core,Core APIs...
# 17

> No, when I restart the JVM, the new classes should be

> loaded too, aren't they?

>

> (No I'm not using a custom class loader.)

Today you have the following classes in your VM that is running.

MyStuff.MyClassX

MyStuff.MyClassY1

You then create the following classes and copy them to the system where the VM is running.

MyStuff.MyClassX (replacement)

MyStuff.MyClassY2

The VM will NOT load the above just because you put them on the system.

When you restart the VM the following classes will be loaded.

MyStuff.MyClassX (replacement)

MyStuff.MyClassY1

MyStuff.MyClassY2

--

Now the above is correct when discussing the VM and not when discussing J2EE containers. Presumably you are not using a container or you are not delivering the classes via standard container delivery mechanism.

jschella at 2007-7-7 20:37:15 > top of Java-index,Core,Core APIs...
# 18
Yes, that's fine.The old MyStuff.MyClassX isn't loaded any more, but the MyStuff.MyClassX (replacement).That's exactly what I want.
Hannes_Rannesa at 2007-7-7 20:37:15 > top of Java-index,Core,Core APIs...