How to distinguish two instances of the same loaded different classloader?

I have two different webapps, and each loads one class A with another classloader. When I put one instance in a session and then get it from another webapp, a ClassCastException is ClassCastException .

For example, in webapp A, I store a in the session, and then in webapp B, I get a from the session and drop it in A, a ClassCastException is ClassCastException .

Is there any way to solve this problem?

+6
source share
6 answers

Is there any way to solve this problem?

In principle, no.

As for JLS, types are different types, and the JVM doesn't let you pretend otherwise. For example, classes can have different code and different layouts of objects. If you could trick the JVM into treating the types as the same, you could deflate the security of the JVM environment. This is insanity.

The solution is to make sure that you do not have two different class loaders loading the same class. In the context of Tomcat, this means that if two or more web folders need to share instances of a class, then this class must be defined in the class loader, which is common to both; for example, put the JAR file in the $CATALINA_HOME/lib or $CATALINA_HOME/common .


If there is a good reason why classes should be loaded by different class loaders (perhaps because the classes are really different), then you can solve this problem by specifying the interface that both versions implement the class, and then programming to the interface, not to the class implementation. Of course, there can only be one version of the loaded interface ... or again you will encounter the same problem again.

+5
source

You should avoid this situation, basically - either put both bits of the functionality in the same webapp, or move the library containing the class A to the appropriate location, so only one classloader will be used. The two classes loaded by different class loaders are completely different in the JVM - you simply cannot use between them.

See the Tomcat classloader documentation for more information on the various class loaders . It looks like you want to put this generic class in the generic scope of the class loader. As noted in the documentation, this is rather unusual, but if you really want to share an object between two webapps (which is also unusual), this is probably the easiest way to move forward.

+3
source

You can not. The two classes loaded by different class loaders are different.

+1
source

Perhaps you can serialize shared objects?

I do not necessarily advocate this approach, but again, what serialization essentially does: you serialize from some JVM or ClassLoader X and load it (deserialize) it into another JVM / ClassLoader Y ...

0
source

You cannot drop two objects from different classes, even if the classes have the same name and package signature, however, you can copy data from one to another simply using apache bean utils library, BeanUtils.copyProperties(o1, o2);

0
source

This is possible using a workaround.

Although it’s true that you cannot drop an object from one class loaded by class loader A to the same class loaded by class loader B (classes with the same name are incompatible if they are loaded under different class loaders like ) , in a webapp container such like Jetty or Tomcat, you can load this class once in the parent classloader, which will be used by all webapps in the JVM. Each webapp class loader sets aside a common (parent) class loader to define the class, and dropping it fine works fine.

For example, with Jetty, use WebAppContext.addSystemClass() , as described here .

0
source

Source: https://habr.com/ru/post/915590/


All Articles