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.
x-pack/plugin/security/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java
}
    private static ClusterScope getAnnotation(Class<?> clazz) {
        if (clazz == Object.class || clazz == SecurityIntegTestCase.class) {
            return null;
        }
        ClusterScope annotation = clazz.getAnnotation(ClusterScope.class);
        if (annotation != null) {
            return annotation;
        }
        return getAnnotation(clazz.getSuperclass());
    }
    Scope getCurrentClusterScope() {
        return getCurrentClusterScope(this.getClass());
    }
    private static Scope getCurrentClusterScope(Class<?> clazz) {
        ClusterScope annotation = getAnnotation(clazz);
        return annotation == null ? Scope.SUITE : annotation.scope();
    }
    @BeforeClass
    public static void initDefaultSettings() {
        if (SECURITY_DEFAULT_SETTINGS == null) {
            SECURITY_DEFAULT_SETTINGS = new SecuritySettingsSource(randomBoolean(), createTempDir(), Scope.SUITE);
        }
    }
    /**
     * Set the static default settings to null to prevent a memory leak. The test framework also checks for memory leaks
     * and computes the size, this can cause issues when running with the security manager as it tries to do reflection
     * into protected sun packages.
     */
    @AfterClass