private static void runTest(boolean cloneAssets, boolean smartCache, boolean keepRefs, int limit) {
        counter = 0;
        List<Object> refs = new ArrayList<>(limit);
        
        AssetCache cache;
        AssetProcessor proc = null;
        
        if (cloneAssets) {
            proc = new CloneableAssetProcessor();
        }
        
        if (smartCache) {
            if (cloneAssets) {
                cache = new WeakRefCloneAssetCache();
            } else {
                cache = new WeakRefAssetCache();
            }
        } else {
            cache = new SimpleAssetCache();
        }
        
        System.gc();
        System.gc();
        System.gc();
        System.gc();
        
        long memory = Runtime.getRuntime().freeMemory();
        
        while (counter < limit){
            // Create a key
            DummyKey key = new DummyKey();
            
            // Create some data
            DummyData data = new DummyData();
            
            // Postprocess the data before placing it in the cache.
            if (proc != null){
                data = (DummyData) proc.postProcess(key, data);
            }
            
            if (data.key != null){
                // Keeping a hard reference to the key in the cache
                // means the asset will never be collected => bug
                throw new AssertionError();
            }
            
            cache.addToCache(key, data);
            
            // Get the asset from the cache
            AssetKey<DummyData> keyToGet = key.clone();
            
            // NOTE: Commented out because getFromCache leaks the original key
//            DummyData someLoaded = (DummyData) cache.getFromCache(keyToGet);
//            if (someLoaded != data){
//                // Failed to get the same asset from the cache => bug
//                // Since a hard reference to the key is kept, 
//                // it cannot be collected at this point.
//                throw new AssertionError();
//            }
            
            // Clone the asset
            if (proc != null){
                // Data is now the clone!
                data = (DummyData) proc.createClone(data);
                if (smartCache) {
                    // Registering a clone is only needed
                    // if smart cache is used.
                    cache.registerAssetClone(keyToGet, data);
                    // The clone of the asset must have the same key as the original
                    // otherwise => bug
                    if (data.key != key){
                        throw new AssertionError();
                    }
                }
            }
            
            // Keep references to the asset => *should* prevent
            // collections of the asset in the cache thus causing
            // an out of memory error.
            if (keepRefs){
                // Prevent the saved references from taking too much memory.
                if (cloneAssets) {
                    data.data = null;
                }
                refs.add(data);
            }
            
            if ((counter % 1000) == 0){
                long newMem = Runtime.getRuntime().freeMemory();
                System.out.println("Allocated objects: " + counter);
                System.out.println("Allocated memory: " + ((memory - newMem)/(1024*1024)) + " MB" );
                memory = newMem;
            }
        }
    }
Dummy key is indexed by a generated ID
jme3-examples/src/main/java/jme3test/asset/TestAssetCache.java