Tomcat использует разные загрузчики классов для каждого приложения, поэтому он может изолировать их.То есть, если у вас есть веб-приложение, которое предоставляет класс Consumer (как Person), и другое веб-приложение, которое предоставляет одно и то же имя класса Consumer (как поток), оно может вызвать конфликт и проблему для обоих приложений (которые Consumer должен загрузить Tomcat).?).Чтобы ответить на этот вопрос, создайте ClassLoader для каждого приложения со своими изолированными банками и классами.Как мы можем видеть на диаграмме ниже, это иерархия загрузчиков классов Tomcat.Проблема в том, что ваш JNI-вызов получает System ClassLoader (по умолчанию), в котором нет информации о классе, который вы пытаетесь вызвать.
Bootstrap
|
System
|
Common
/ \
Catalina Shared
/ \
Webapp1 Webapp2 ...
Чтобы решить эту проблему, вам нужно найти загрузчик классов приложения.,Вы можете легко сделать это, вызвав getClass().getClassLoader()
в некотором классе, который вы определили в своем приложении.Это получит ClassLoader, который загрузил этот класс, который, как мы знаем, является вашим ClassLoader веб-приложения.После этого вы вызываете метод loadClass("foo.bar.ClassThatIWant"
) и получаете нужный класс.В Java все выглядело бы так:
ClassLoader cl = AWebClass.class.getClassLoader();
Class myClass = cl.loadClass("foo.bar.ClassThatIWant");
Сделайте трюк в JNI, сделав следующее, предположим, что вы передали загрузчик классов веб-приложений в качестве параметра с именем webCL
.
jclass classLoaderClass = env->GetObjectClass(webCL);
jmethodID loadClassMethod = env->GetMethodID(classLoaderClass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
const char *className = "foo.bar.ClassThatIWant"; // This needs dots because it's the arg for Java
jstring javaClassName = env->NewStringUTF(desiredClass);
jclass desiredClass = env->CallObjectMethod(webCL, loadClassMethod, javaClassName);