1 Reply Latest reply on Apr 27, 2005 1:16 AM by zboris

    jboss-4.0.1sp1: Cancelling Timer does not kill timer thread

    zboris

      I have encountered interesting problem.

      I'm using jboss 4.0.1sp1 EJBTimerService with stateless session beans.

      Login in Jboss management console and note number of threads in stats overview:

      JVM Environment
      Free Memory: 72 MB
      Max Memory: 1016 MB
      Total Memory: 127 MB
      #Threads: 64

      JVM Version: 1.4.2-b28 (Sun Microsystems Inc.)
      JVM Name: Java HotSpot(TM) Client VM

      Then I create say 100 timers to expire in 5 minutes using:

      TimerService ts = sessionContext.getTimerService();
      ts.createTimer(timeoutDuration, reference);


      Then I am logging in Jboss management console again and note that number of threads increased accordingly by 100 and something threads

      Then I wait for 5 minutes till the timers expire and ejbTimeout(Timer) will be called. So again I refresh Jboss management console and note that number of threads went back to 64.

      This is all fine, buit the other test is as of below:

      Create AND cancel 100 timers using the code something like that:

      TimerService ts = sessionContext.getTimerService();
      Timer timer = ts.createTimer(timeoutDuration, reference);
      timer.cancel();


      If you check Jboss management console you will notice that the number of threads increased and never went back after timers were cancelled.

      ==================================

      The reason I am asking this question is beacuse in the application Im developing - I need to use number of timers. The simultaneous number of timers is unlikely to exceed 100. I need to set a timer per entity bean bearing some status in it. The timer should change the status field in entity bean from status 2 to status 1 once it expires, unless the timer was cancelled.
      Cancelling works fine - i.e. ejbTimeout() never gets called, but timer.cancel() call "leaves" the timer thread running (according to Jboss management console). After I mocked around with 1000 timerService.createTimer() and timer.cancel() JBoss AS throws an error:

      java.lang.OutOfMemoryError: unable to create new native thread.

      Jboss java_opts are set to: -Xms128m -Xmx1024m

      It is a requirement to use timers within session bean rather that entity bean.

      Please clarify, if anyone had similar problem.

      The code for testing the timers is as of below. This code will create and cancell 4000 timers and jboss will result in OutOfMemoryError:

      TestTimerBean...

      public void ejbTimeout(Timer timer)
       {
       log("ejbTimeout() called at: " + new Date(System.currentTimeMillis()) + " with info: "+ timer.getInfo());
      
       try
       {
       String reference = (String) timer.getInfo();
       log( reference + " timer timedout");
       }
       catch (Exception e)
       {
       //bad luck, how to handle if could not acknowledge or could not find?
       e.printStackTrace();
       }
       }
      
      
       public void setSessionContext(SessionContext sessionContext) {
       this.sessionContext = sessionContext;
       }
      
       public void createTimer(long timeoutDuration, String reference)
       {
       try
       {
       TimerService ts = sessionContext.getTimerService();
       ts.createTimer(timeoutDuration, reference);
       log("Created timer for: " + reference + ". It will expire in " + timeoutDuration + " milliseconds if not cancelled.");
       log("+ + + + timers count: "+ts.getTimers().size());
       }
       catch (Exception ex)
       {
       log("Exception caught during timer creation ...");
       }
       }
      
       public void cancelTimer(String reference)
       {
       try
       {
       TimerService ts = sessionContext.getTimerService();
       Collection timers = ts.getTimers();
       Iterator it = timers.iterator();
       log(" timers count before cancelling timer: "+ts.getTimers().size());
       while (it.hasNext())
       {
       try
       {
       Timer myTimer = (Timer) it.next();
       if ( (myTimer.getInfo().toString().equals(reference)))
       {
       myTimer.cancel();
       log("Timer Found and Cancelled: " + reference);
       log("- - - - timers count after cancelling: "+ts.getTimers().size());
       break;
       }
       }
       catch (NoSuchObjectLocalException nsole)
       {
       //this exception can be throw if timer we are getInfo() or cancel()-ling
       //has already expired - in other words timeout() was already called and
       //invalidated the timer
       }
       }
       }
       catch (Exception e)
       {
      
       log("Exception after cancelling timer : " + e.toString());
       }
       return ;
       }
      


      Create a client for that bean

      Sample class to call the client and timers creation, cancellation:
      package test;

      import testtimer.TestTimerTestClient;
      import testtimer.TestTimer;
      
      public class Timers
      {
       public Timers()
       {
       }
      
       public static void main(String[] args)
       {
       Timers timers = new Timers();
      
       TestTimerTestClient connector = new TestTimerTestClient();
      
       try
       {
       connector.create();
      
       for (int i=0; i< 4000; i++)
       {
       connector.createTimer(300000, "ref" + i);
       connector.cancelTimer("ref" + i);
       }
      
       }
       catch (Exception e)
       {
       e.printStackTrace();
       }
       }
      }


        • 1. Re: jboss-4.0.1sp1: Cancelling Timer does not kill timer thr
          zboris

          To make sure that spawning of a new Timers and then cancelling them do not result in thread's pool growing in its size
          mark the cancelTimer method's transaction in ejb-jar.xml as NotSupported. i.e.:

          <container-transaction>

          <ejb-name>MyEnterpriseBean</ejb-name>
          <method-name>*</method-name>

          <trans-attribute>Required</trans-attribute>
          </container-transaction>

          <container-transaction>

          <ejb-name>MyEnterpriseBean</ejb-name>
          <method-name>cancelTimer</method-name>

          <trans-attribute>NotSupported</trans-attribute>
          </container-transaction>