We pass `null` for the class name here:

https://github.com/elastic/elasticsearch/blob/f086dd18ddc705bf84a1ff99d35196ec2498fd52/server/src/main/java/org/elasticsearch/plugins/PluginDescriptor.java#L261

However the class name is mandatory for the transport protocol today:

https://github.com/elastic/elasticsearch/blob/f086dd18ddc705bf84a1ff99d35196ec2498fd52/server/src/main/java/org/elasticsearch/plugins/PluginDescriptor.java#L156

This prevents various APIs from working in a cluster with stable plugins installed.
server/src/test/java/org/elasticsearch/plugins/PluginsServiceTests.java
}
    static final class Loader extends ClassLoader {
        Loader(ClassLoader parent) {
            super(parent);
        }
    }
    
    static void closePluginLoaders(PluginsService pluginService) {
        for (var lp : pluginService.plugins()) {
            if (lp.loader() instanceof URLClassLoader urlClassLoader) {
                try {
                    PrivilegedOperations.closeURLClassLoader(urlClassLoader);
                } catch (IOException unexpected) {
                    throw new UncheckedIOException(unexpected);
                }
            }
            if (lp.loader() instanceof UberModuleClassLoader loader) {
                try {
                    PrivilegedOperations.closeURLClassLoader(loader.getInternalLoader());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    private static class TestExtensiblePlugin extends Plugin implements ExtensiblePlugin {
        private List<TestExtensionPoint> extensions;
        @Override
        public void loadExtensions(ExtensionLoader loader) {
            assert extensions == null;