Обновление : добавлена дополнительная информация, поскольку обходной путь не работает надежно
У меня есть модуль RMI, который я загружаю с помощью специального загрузчика классов для Spring bean-компонентов. Этот загрузчик классов также используется для загрузки этого модуля.
ClassLoader наследуется от URLClassLoader. Для родительского загрузчика классов этого пользовательского загрузчика классов установлено значение AppClassLoader.
В этом модуле я запускаю реестр RMI с загрузчиком классов conxt в соответствии с этим загрузчиком классов.
Теперь, если я сделаюВызовы RMI, реестр RMI:
- способен определить классы по пути URL-адресов, которые я предоставляю своему загрузчику классов
- НЕ способен определить классы в родительском классеloader.
Включив отладку на стороне сервера RMI через
"-Djava.rmi.server.logCalls=true",
"-Dsun.rmi.server.logLevel=VERBOSE",
"-Dsun.rmi.loader.logLevel=VERBOSE",
, я смог убедиться, что в реестре RMI используется правильный загрузчик классов (также ссылка наparent)
Я попытался добавить URL из AppClassLoader в мой ClassLoader. Во-первых, это, кажется, работает, но он работает случайно.
В настоящее время у меня есть следующий вывод из журнала RMI
Nov 04, 2019 2:56:33 PM sun.rmi.server.LoaderHandler loadClass
FEINER: RMI TCP Connection(4)-10.45.42.206: (thread context class loader: class org.jvoicexml.config.JVoiceXmlClassLoader[repo=jsapi20,...,file:/C:/Users/dwalka/Documents/git/JVoiceXML/org.jvoicexml/build/libs/org.jvoicexml-0.7.9.jar,...,parent=sun.misc.Launcher$AppClassLoader@3d4eac69])
Nov 04, 2019 2:56:33 PM sun.rmi.server.LoaderHandler loadClass
FEIN: RMI TCP Connection(4)-10.45.42.206: class "org.jvoicexml.UuidSessionIdentifer" not found via codebase
java.lang.ClassNotFoundException: org.jvoicexml.UuidSessionIdentifer
Загрузчик родительского класса выглядит следующим образом
2019-11-04T14:56:08,505 [JVoiceXmlMain ] INFO cexml.jndi.classserver.ClassloaderServer ( 56) - parent class loader 'sun.misc.Launcher$AppClassLoader@3d4eac69'
...
2019-11-04T14:56:08,506 [JVoiceXmlMain ] INFO cexml.jndi.classserver.ClassloaderServer ( 64) - parent class loader entry: 'file:/C:/Users/dwalka/Documents/git/JVoiceXML/org.jvoicexml/build/libs/org.jvoicexml-0.7.9.jar'
...
Примечание: Найдены классы из JDK, такие как java.net.URI
В банке содержится класс
C:\Users\dwalka\Documents\git\JVoiceXML\org.jvoicexml\build\libs>jar -tf org.jvoicexml-0.7.9.jar | findstr "UuidSessionIdentifer"
org/jvoicexml/UuidSessionIdentifer.class
Я провел несколько модульных тестов, чтобы убедиться, что это работает (безRMI). Он находит классы
- в той же банке
- из обсуждаемой банки
- из других банок, не входящих в CLASSPATH
Здесьмой ClassLoader
public final class JVoiceXmlClassLoader extends URLClassLoader {
/** The repository that this class loader is responsible for. */
private final String repository;
/**
* Constructs a new object.
* @param parent the parent class loader.
*/
public JVoiceXmlClassLoader(final ClassLoader parent) {
this(parent, null);
}
/**
* Constructs a new object.
* @param parent the parent class loader.
* @param repo the repository that this class loader is responsible for
*/
public JVoiceXmlClassLoader(final ClassLoader parent, final String repo) {
super(new URL[0], parent);
repository = repo;
}
/**
* Retrieves the used repository
* @return the repository.
* @since 0.7.9
*/
public String getRepository() {
return repository;
}
/**
* {@inheritDoc}
*/
@Override
public void addURL(final URL url) {
super.addURL(url);
}
}
Установлен менеджер безопасности
"-Djava.security.manager",
"-Djava.security.policy=${project(':org.jvoicexml').buildDir}/config/jvoicexml.policy",
и файл политики очень разрешительный
grant {
permission java.security.AllPermission;
};
Странно то, что он работаетранее без проблем. Изменения, которые я сделал с тех пор
- Переключиться на Windows 10
- Тем временем я убедился, что такая же проблема возникает в Linux (Ubuntu)
- Обновление до Gradle 5.4. 1