Насколько я понимаю, этот список JAR-файлов отправляется как "аннотация класса" в ответе RMI.
Я обнаружил, что с помощью инструмента SerializationDumper
, доступного в https://github.com/NickstaDB/SerializationDumper.
(Совет: у меня былпоменять порядок байтов в дампе из Wireshark, используя dd conv=swab <data.orig >data.swapped
, чтобы передать его SerializationDumper -r
.)
....
classAnnotations
TC_STRING - 0x74
newHandle 0x00 7e 00 01
Length - 21685 - 0x54 b5
Value - file:/app/my-rmi-server-app.jar file:/tmp/cache/repository/org/springframework/boot/spring-boot-starter-web/2.1.4.RELEASE/spring-boot-starter-web-2.1.4.RELEASE.jar file:/tmp/maven/repository/org/springframework/boot/spring-boot-starter/2.1.4.RELEASE/spring-boot-starter-2.1.4.RELEASE.jar ...
Я не эксперт по RMI, но мне не совсем понятно, как этипути на сервере RMI могут быть полезны для клиента RMI, который явно не имеет доступа к этим путям?!?
В любом случае, это значение аннотации класса генерируется в https://github.com/openjdk/jdk/blob/master/src/java.rmi/share/classes/sun/rmi/server/LoaderHandler.java#L194.
Алгоритм использует так называемые загрузчики классов / кодовых баз, чтобы определить, какое значение должно быть.
В моем случае я использую Spring Boot Thin Launcher для упаковки и запуска моего приложения, так что это, вероятно, влияет на этот алгоритм.
Способ, который я нашел, всегда отправляет пусто аннотация класса, переопределяет значение по умолчанию RMIClassLoaderSpi
на мое собственное:
package my.app;
import java.net.MalformedURLException;
import java.rmi.server.RMIClassLoader;
import java.rmi.server.RMIClassLoaderSpi;
public class LeanRMIClassLoaderSpi extends RMIClassLoaderSpi {
private final RMIClassLoaderSpi delegate;
public LeanRMIClassLoaderSpi() {
this.delegate = RMIClassLoader.getDefaultProviderInstance();
}
@Override
public Class<?> loadClass(String codebase, String name,
ClassLoader defaultLoader) throws MalformedURLException,
ClassNotFoundException {
return delegate.loadClass(codebase, name, defaultLoader);
}
@Override
public Class<?> loadProxyClass(String codebase, String[] interfaces,
ClassLoader defaultLoader) throws MalformedURLException,
ClassNotFoundException {
return delegate.loadProxyClass(codebase, interfaces, defaultLoader);
}
@Override
public ClassLoader getClassLoader(String codebase)
throws MalformedURLException {
return delegate.getClassLoader(codebase);
}
@Override
public String getClassAnnotation(Class<?> cl) {
return null;
}
}
Системное свойство Java java.rmi.server.RMIClassLoaderSpi
должно быть установлено на my.app.LeanRMIClassLoaderSpi
, чтобы код в https://github.com/openjdk/jdk/blob/master/src/java.rmi/share/classes/java/rmi/server/RMIClassLoader.java можно было выбратьэто.
И, вуаля, ваш трафик RMI значительно сократился - и приложение все еще работало просто отлично в моем случае.