Details

    • Bug
    • Status: Closed (View Workflow)
    • Minor
    • Resolution: Fixed
    • 1.1.3
    • 1.1.4
    • None
    • None
    • JDK 1.7.x, Tomcat 7.0.42

    Description

      Hi,

      the MySQLStatement does start a TimerThread to handle the timeouts (which are e.g. applied in transactions).

      Stopping the webapplication does leak those thread because it is never stopped and the complete classloader fails to get garbage collected.
      My current workaround is, to call this in the contextDestroyed method of a webapp listener:

          try {
            final Class<?> clazz = ReflectionUtils.getClassForName("org.mariadb.jdbc.MySQLStatement");
            final Field f = clazz.getDeclaredField("timer");
            f.setAccessible(true);
            Timer timer = (Timer) f.get(null);
            if (timer != null) {
              timer.cancel();
            }
            timer = null;
          } catch (ClassNotFoundException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
            // ignore
          }

      I've done similar for mysql, to stop the scheduler started to destroy connections.
      The difference is that there is an api call, a static method shutdown, to do this and i need no hacks to get that timer variable.

          try {
            final Class<?> clazz = ReflectionUtils.getClassForName("com.mysql.jdbc.AbandonedConnectionCleanupThread");
            MethodUtils.invokeExactStaticMethod(clazz, "shutdown", null);
          } catch (ClassNotFoundException e) {
            // ignore
          } catch (NoSuchMethodException e) {
            // ignore
          } catch (IllegalAccessException e) {
            // ignore
          } catch (InvocationTargetException e) {
            // ignore
          }

      Maybe you can implement similar.

      And if you do so, it would be nice if you can call the constructor, which does take a name for the Timer, e.g. MariaDBTimeoutStatementTimer, or something like this, to get rid of the "Timer-0" name in the thread overview to know what "Timer-0" is about for.

      Attachments

        Activity

          Why do you think it is a leak? what happens if you start/stop webapp multiple times? How many Timer threads you'll have?

          wlad Vladislav Vaintroub added a comment - Why do you think it is a leak? what happens if you start/stop webapp multiple times? How many Timer threads you'll have?
          tkrah Torsten Krah added a comment - - edited

          The webapp has its own classloader which is pinned in memory because of those thread. The complete classloader fails to be collected because of that, so this is imho called a leak.

          Tomcat does even tell this:

          SEVERE: The web application [/] appears to have started a thread named [Timer-0] but has failed to stop it. This is very likely to create a memory leak.

          If i start the app twice, i get two timer threads, if i do this a third time, i get 3 timer threads and so on - until permgen space runs out of space.

          tkrah Torsten Krah added a comment - - edited The webapp has its own classloader which is pinned in memory because of those thread. The complete classloader fails to be collected because of that, so this is imho called a leak. Tomcat does even tell this: SEVERE: The web application [/] appears to have started a thread named [Timer-0] but has failed to stop it. This is very likely to create a memory leak. If i start the app twice, i get two timer threads, if i do this a third time, i get 3 timer threads and so on - until permgen space runs out of space.

          I created a parameterless "unloadDriver" method in the org.mariadb.jdbc.Driver class for this.

          wlad Vladislav Vaintroub added a comment - I created a parameterless "unloadDriver" method in the org.mariadb.jdbc.Driver class for this.
          tkrah Torsten Krah added a comment -

          Can you please give the timer Thread a better name than "Timer"?

          tkrah Torsten Krah added a comment - Can you please give the timer Thread a better name than "Timer"?

          It is the name given by the JVM.

          wlad Vladislav Vaintroub added a comment - It is the name given by the JVM.

          I mean, the timer class has the predefined name for this thread and I see no strong reason to give it a special name, even if it would make finding Tomcat classloader bugs easier.

          wlad Vladislav Vaintroub added a comment - I mean, the timer class has the predefined name for this thread and I see no strong reason to give it a special name, even if it would make finding Tomcat classloader bugs easier.
          tkrah Torsten Krah added a comment -

          To be honest - this has absolutely nothing to do with "obscure tomcat classloading bugs".
          This is just standard java classloading and garbage collection theory.

          Tomcat has its boot classloader and every webapp got its own webapp classloader. Any class loaded has a strong reference to its classloader.
          So is there is a Timer Thread running (which is a class loaded through the root classloader) and this does have a refercence to the MySQLStatement class (just the work the timer has to do). Because of this it also has a strong reference to the webapp classloader because this one did load the MySQLStatement class.
          So as long as this thread is running, the garbage collector can't collect the webapp classloader because there is still a strong reference to this one - through the Timer thread.

          Imho nothing obscure here - where do you see a tomcat classloading bug?

          And yes its the name the JDK does assign - but the JDK does also provide a constructor with a "name" arg to just name your timer thread to something meaningful.

          Just have a look at the http://www.java2s.com/Open-Source/Java-Open-Source-Library/Database/mysql/com/mysql/jdbc/AbandonedConnectionCleanupThread.java.htm code - they are calling the super constructor with a "name" to give their thread a nice name, not only "Thread-0" or something.
          In a webapp container this is really helpful to monitor stuff. Sometimes you got 10 or more "Timer-X" threads and wonder where are they coming from - it would help if they are named better, imho.

          tkrah Torsten Krah added a comment - To be honest - this has absolutely nothing to do with "obscure tomcat classloading bugs". This is just standard java classloading and garbage collection theory. Tomcat has its boot classloader and every webapp got its own webapp classloader. Any class loaded has a strong reference to its classloader. So is there is a Timer Thread running (which is a class loaded through the root classloader) and this does have a refercence to the MySQLStatement class (just the work the timer has to do). Because of this it also has a strong reference to the webapp classloader because this one did load the MySQLStatement class. So as long as this thread is running, the garbage collector can't collect the webapp classloader because there is still a strong reference to this one - through the Timer thread. Imho nothing obscure here - where do you see a tomcat classloading bug? And yes its the name the JDK does assign - but the JDK does also provide a constructor with a "name" arg to just name your timer thread to something meaningful. Just have a look at the http://www.java2s.com/Open-Source/Java-Open-Source-Library/Database/mysql/com/mysql/jdbc/AbandonedConnectionCleanupThread.java.htm code - they are calling the super constructor with a "name" to give their thread a nice name, not only "Thread-0" or something. In a webapp container this is really helpful to monitor stuff. Sometimes you got 10 or more "Timer-X" threads and wonder where are they coming from - it would help if they are named better, imho.

          People

            wlad Vladislav Vaintroub
            tkrah Torsten Krah
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Git Integration

                Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.