package org.apache.markt.leaks.io;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import org.apache.markt.leaks.LeakBase;
import org.apache.markt.leaks.RelaxedClassLoader;

/**
 * All JREs leak
 */
public class ObjectStreamClassLeak extends LeakBase {

    public static void main(String[] args) {
        ObjectStreamClassLeak objectStreamClassLeak = new ObjectStreamClassLeak();
        objectStreamClassLeak.doLeakTest();
    }


    @Override
    protected void createLeakingObjects() {

        // The class that is going to trigger the leak when serialized.
        Class<?> clazz = null;

        // clazz needs to be loaded by the module class loader.
        // Get the class loader
        RelaxedClassLoader cl = (RelaxedClassLoader) Thread.currentThread().getContextClassLoader();

        // Load the bytes for the class that will be serialized to trigger the
        // leak
        byte[] classBytes = new byte[2048];
        int offset = 0;
        InputStream is = null;
        try {
            is = cl.getResourceAsStream("org/apache/markt/leaks/io/Dummy.class");
            int read = is.read(classBytes, offset, classBytes.length-offset);
            while (read > -1) {
                offset += read;
                if (offset == classBytes.length) {
                    // Buffer full - double size
                    byte[] tmp = new byte[classBytes.length * 2];
                    System.arraycopy(classBytes, 0, tmp, 0, classBytes.length);
                    classBytes = tmp;
                }
                read = is.read(classBytes, offset, classBytes.length-offset);
            }

            clazz = cl.defineClass0("org.apache.markt.leaks.io.Dummy", classBytes, 0, offset,
                    this.getClass().getProtectionDomain());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }

        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(clazz);
            oos.flush();
        } catch (IOException e) {
            RuntimeException r = new RuntimeException();
            r.initCause(e);
            throw r;
        }
    }


    @Override
    protected void cleanUpLeakingObjects() {
        // None
    }
}
@@ -154,24 +154,138 @@
 tputStream;%0A
+import java.lang.ref.Reference;%0Aimport java.lang.reflect.Field;%0Aimport java.util.Iterator;%0Aimport java.util.Map;%0A%0A
 import org.a
@@ -2705,15 +2705,1297 @@
     
-// None
+try %7B%0A            Class%3C?%3E clazz = Class.forName(%22java.io.ObjectStreamClass$Caches%22);%0A            clearCache(clazz, %22localDescs%22);%0A            clearCache(clazz, %22reflectors%22);%0A        %7D catch (ReflectiveOperationException %7C SecurityException %7C ClassCastException e) %7B%0A            // Clean-up failed%0A            e.printStackTrace();%0A        %7D%0A    %7D%0A%0A%0A    private void clearCache(Class%3C?%3E target, String mapName)%0A            throws ReflectiveOperationException, SecurityException, ClassCastException %7B%0A        Field f = target.getDeclaredField(mapName);%0A        f.setAccessible(true);%0A        Map%3C?,?%3E map = (Map%3C?,?%3E) f.get(null);%0A        Iterator%3C?%3E keys = map.keySet().iterator();%0A        while (keys.hasNext()) %7B%0A            Object key = keys.next();%0A            if (key instanceof Reference) %7B%0A                Object clazz = ((Reference%3C?%3E) key).get();%0A                if (clazz instanceof Class) %7B%0A                    ClassLoader cl = ((Class%3C?%3E) clazz).getClassLoader();%0A                    while (cl != null) %7B%0A                        if (cl == getModuleClassLoader()) %7B%0A                            keys.remove();%0A                            break;%0A                        %7D%0A                        cl = cl.getParent();%0A                    %7D%0A                %7D%0A            %7D%0A        %7D
 %0A   

Add the 'fix'