when Resources.isUrlConnectionADirectory, inflater memory leak?

14 views
Skip to first unread message

supera...@gmail.com

unread,
Dec 7, 2017, 3:54:45 PM12/7/17
to Play Framework
my english is poor, but I'm very eager to solve the problem.

Play Version

2.3.4

Scala

2.1.1

Operating System

CentOS release 6.9 (Final)
Linux version 2.6.32-696.10.2.el6.x86_64 (mock...@c1bl.rdu2.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC) ) #1 SMP Tue Sep 12 14:33:29 UTC 2017

JDK

java version "1.7.0_67"
Java(TM) SE Runtime Environment (build 1.7.0_67-b01)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)

Behavior

Some time ago,found res memory is constantly increasing, which is much larger than xmx. I learned that when serving application’s static resources,playframework call Resources.isUrlConnectionADirectory,make sure it's not a directory. I use greys-anatomy(like btrace) get the call stack of Inflater constructor,found JarFile getInputStream new a Inflater object, and when close, return it to  inflaterCache. Why not get from the cache, but a new one(in other words, Sometimes borrowed is not returned). ps: when jmap heap:live trigger full gc, res memory droped.

in order to test and verify if getInputStream of application'assets.jar[val is = jar.getJarFile.getInputStream(jar.getJarEntry)] resulting in inflater memory leak, I unzip assets.jar and place directory in classpath, restart application, found the res memory no longer increase much larger.
  /**
   * Tries to work out whether the given URL connection is a directory or not.
   *
   * Depends on the URL connection type whether it's accurate.  If it's unable to determine whether it's a directory,
   * this returns false.
   */
  def isUrlConnectionADirectory(urlConnection: URLConnection) = urlConnection match {
    case file: FileURLConnection => new File(file.getURL.toURI).isDirectory       //unzip asset.jar, execute here, memory perform normally
    case jar: JarURLConnection =>
      if (jar.getJarEntry.isDirectory) {
        true
      } else {
        // JarEntry.isDirectory is rubbish....
        val is = jar.getJarFile.getInputStream(jar.getJarEntry)
        if (is == null) {
          true
        } else {
          is.close()
          false
        }
      }
    case other => false
  }


Reply all
Reply to author
Forward
0 new messages