Skip to content

BridgeMethodResolver resolveAll does not close InputStream #115

@yogregg

Description

@yogregg

I uncovered a problem in BridgeMethodResolver resolveAll: it opens an InputStream that is never closed.

The problem is in cglib/cglib/src/main/java/net/sf/cglib/proxy/BridgeMethodResolver.java, in line 63 of resolveAll, which has this code:

        try {
            new ClassReader(classLoader.getResourceAsStream(owner.getName().replace('.', '/') + ".class"))
              .accept(new BridgedFinder(bridges, resolved),
                      ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG);
        } catch(IOException ignored) {}

The stream returned by classsLoader.getResourceAsStream is never closed. The ClassReader instance that it is passed to doesn't close it, and nothing else holds a reference to it that could be used to close it.

The fix is simple, and I've attached a patch file for it. The heart of it is this change to the above code block:

        InputStream classStream = null;
        try {
            classStream = classLoader.getResourceAsStream(owner.getName().replace('.', '/') + ".class");
            new ClassReader(classStream)
              .accept(new BridgedFinder(bridges, resolved),
                      ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG);
        } catch(IOException ignored) {}
        finally {
          try {
            if (classStream != null) {
              classStream.close();
            }
          }
          catch (IOException ignoreMe) {}
        }

Here is the patch file:
BridgeMethodResolver.zip

I noticed this when using cglib indirectly via the Spring framework. When my web application is deployed to Tomcat 8.5 on Windows, Tomcat refuses to undeploy the web application -- I have to shut down the entire Tomcat server. This happens because Tomcat's classloader keeps a Windows file lock on jar files when someone has an open input stream on one of the classes in the jar file (when opened by classLoader.getResourceAsStream). This is a substantial problem for users of my web application, since they cannot upgrade it without shutting down Tomcat, which often means that user get kicked out of all other web applications that Tomcat is hosting.

The change above resolved the problem I was having in Spring with Tomcat 8.5.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions