@SuppressWarnings("unchecked")
    public static synchronized <T extends Cache> T createSerializingCache(String name, Class keyClass, Class valueClass) {
        T cache = (T) caches.get(name);
        if (cache != null) {
            if (cache instanceof CacheWrapper<?,?> && ((CacheWrapper) cache).getWrappedCache() instanceof SerializingCache<?,?>) {
                log.debug("Reset the classes used to serialize data for serializing cache '{}': keyClass '{}', valueClass '{}' (it is likely that a new version of the plugin that uses this class was loaded).", name, keyClass, valueClass);
                ((SerializingCache)((CacheWrapper) cache).getWrappedCache()).registerClasses(keyClass, valueClass);
            }
            return cache;
        }

        final Cache<String, String> delegate = (Cache<String, String>) cacheFactoryStrategy.createCache(name);
        final SerializingCache sCache = new SerializingCache(delegate);
        sCache.registerClasses(keyClass, valueClass);

        log.info("Created serializing cache [{}] for {}, keyClass '{}', valueClass '{}'", cacheFactoryStrategy.getClass().getName(), name, keyClass, valueClass);

        return wrapCache((T) sCache, name);
    }
Returns the serializing cache, creating it as necessary. Unlike the caches returned by
{@link #createCache(String)}, the caches returned by this method store data in serialized form (without a
reference to their class).

The primary benefit of usage of this cache is that the cached data is stored without any references to their
classes. This allows cache content to remain usable after the classes that instantiate the data get reloaded.
This is of particular interest when the cache is used to store data provided by Openfire plugins (as these
classes get loaded by a class loader that is replaced when a plugin gets reloaded or upgraded).

It is important for a Cache that uses class definitions loaded by a plugin to be 'dereferenced' when the plugin
that provided the class definitions get unloaded (failing to do so will cause ClassCastExceptions, when a new
version of the same plugin gets loaded). For this, {@link #dereferenceSerializingCache(String)} can be used.
To (re)register class definitions with the cache, this #createSerializingCache method can be used. When the cache
pre-exists, it will set (or overwrite) the registered class definitions.

As compared to other caches, usage of this cache will require more system resources, as the serialized
representation of an object typically is (much) larger than its original (unserialized) form.

@param name       The name of the cache to create.
@param keyClass   The class of instances used as keys.
@param valueClass The class of instances used as values.
@return the named cache, creating it as necessary.
@see <a href="https://igniterealtime.atlassian.net/browse/OF-2239">Issue OF-2239: Make it easier to cache plugin class instances</a>
xmppserver/src/main/java/org/jivesoftware/util/cache/CacheFactory.java