Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

javax.swing.ImageIcon classloader leak #113

Open
scholzb-hb opened this issue Aug 4, 2021 · 0 comments
Open

javax.swing.ImageIcon classloader leak #113

scholzb-hb opened this issue Aug 4, 2021 · 0 comments

Comments

@scholzb-hb
Copy link

The class javax.swing.ImageIcon causes a classloader leak which is not covered yet by default (as of classloader-leak-prevention 2.7.0).

Steps to reproduce:

  1. Build the attached example project imageicon-leak.zip (mvn clean install)
  2. Deploy the .war file into a Tomcat 8.5.65
  3. Undeploy it again

Then the classloader is not garbage collected due to the following Path2GC:
imageicon-leak

Obviously the instance of the anonymous class javax.swing.ImageIcon$3 has a reference to an AccessControlContext retaining the ParallelWebappClassLoader. It is created at ImageIcon.java line 347 (from AdoptOpenJDK jdk8u272-b10):

    private MediaTracker getTracker() {
        Object trackerObj;
        AppContext ac = AppContext.getAppContext();
        // Opt: Only synchronize if trackerObj comes back null?
        // If null, synchronize, re-check for null, and put new tracker
        synchronized(ac) {
            trackerObj = ac.get(TRACKER_KEY);
            if (trackerObj == null) {
                Component comp = new Component() {};   // <--- javax.swing.ImageIcon$3
                trackerObj = new MediaTracker(comp);
                ac.put(TRACKER_KEY, trackerObj);
            }
        }
        return (MediaTracker) trackerObj;
    }

Adding the following clean-up step solves this issue:

public class AwtMediaTrackerCleanUp implements ClassLoaderPreMortemCleanUp {

    @Override
    public void cleanUp(ClassLoaderLeakPreventor preventor) {
        StringBuilder trackerKey = preventor.getStaticFieldValue(ImageIcon.class, "TRACKER_KEY");
        AppContext appContext = AppContext.getAppContext();
        synchronized (appContext) {
            appContext.remove(trackerKey);
        }
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant