ICEfaces
  1. ICEfaces
  2. ICE-9275

NegativeArraySizeException thrown by MonitorRunner.java

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: EE-1.8.2.GA_P06
    • Fix Version/s: EE-1.8.2.GA_P07
    • Component/s: Framework
    • Labels:
      None
    • Environment:
      JETTY 8.1.4
    • Assignee Priority:
      P2
    • Salesforce Case Reference:

      Description

      The user is seeing the following exception thrown:

      "NegativeArraySizeException: MonitorRunner.java:56 ":
      java.lang.NegativeArraySizeException
      at java.util.Arrays.copyOf(Arrays.java:2772)
      at java.util.Arrays.copyOf(Arrays.java:2746)
      at java.util.ArrayList.toArray(ArrayList.java:296)
      at java.util.ArrayList.<init>(ArrayList.java:151)
      at com.icesoft.util.MonitorRunner$1.run(MonitorRunner.java:56)

      The exception is thrown on line 56: (Iterator i = new ArrayList(monitors).iterator();) in MonitorRunner.java. This code should be synchronized in order to prevent further issues.

        Activity

        Hide
        Deryk Sinotte added a comment - - edited

        Working on fixing the errors in two similar cases (this one and ICE-9242) as there is no test app and the user says they are hard to produce.

        It's difficult to even find a Jetty 6 download anymore but I found one here: http://olex.openlogic.com/packages/jetty/6.1.14#package_detail_tabs. We don't currently officially support Jetty 8 (which is mentioned in one of the SalesForce cases) but it would be good to know if that's what they require support for. The issue is that, as of Jetty 7 and up (currently at 9), the Jetty project is now handled by the Eclipse Foundation. They've re-packaged the classes (org.mortbay is now org.eclipse) which is why our Jetty Continuation code doesn't work anymore (it's looking for and using the incorrect classes).

        Without a test case or a way to generate the problem the best I could do was make an educated guess as to the solution. For both issues, I've taken the same approach - wrapping the collection and synchronizing access to the collection during iteration. That way there should be no alterations of the collection during iteration which should hopefully mitigate the issues related to what is likely multiple thread access.

                   
        Index: src/com/icesoft/util/MonitorRunner.java
        ===================================================================
        --- src/com/icesoft/util/MonitorRunner.java	(revision 36585)
        +++ src/com/icesoft/util/MonitorRunner.java	(working copy)
        @@ -37,11 +37,12 @@
         
         import java.util.ArrayList;
         import java.util.Collection;
        +import java.util.Collections;
         import java.util.Iterator;
         
         public class MonitorRunner {
             private static final Log log = LogFactory.getLog(MonitorRunner.class);
        -    private Collection monitors = new ArrayList();
        +    private Collection monitors = Collections.synchronizedList(new ArrayList());
             private Thread thread;
             private boolean run = true;
         
        @@ -53,13 +54,15 @@
                             while (run) {
                                 if (count * 1000 >= interval) {
                                     count = 0;
        -                            Iterator i = new ArrayList(monitors).iterator();
        -                            while (i.hasNext()) {
        -                                Runnable monitor = (Runnable) i.next();
        -                                try {
        -                                    monitor.run();
        -                                } catch (Throwable t) {
        -                                    log.warn("Failed to run monitor: " + monitor, t);
        +                            synchronized (monitors) {
        +                                Iterator i = new ArrayList(monitors).iterator();
        +                                while (i.hasNext()) {
        +                                    Runnable monitor = (Runnable) i.next();
        +                                    try {
        +                                        monitor.run();
        +                                    } catch (Throwable t) {
        +                                        log.warn("Failed to run monitor: " + monitor, t);
        +                                    }
                                         }
                                     }
                                 }
        
        Show
        Deryk Sinotte added a comment - - edited Working on fixing the errors in two similar cases (this one and ICE-9242 ) as there is no test app and the user says they are hard to produce. It's difficult to even find a Jetty 6 download anymore but I found one here: http://olex.openlogic.com/packages/jetty/6.1.14#package_detail_tabs . We don't currently officially support Jetty 8 (which is mentioned in one of the SalesForce cases) but it would be good to know if that's what they require support for. The issue is that, as of Jetty 7 and up (currently at 9), the Jetty project is now handled by the Eclipse Foundation. They've re-packaged the classes (org.mortbay is now org.eclipse) which is why our Jetty Continuation code doesn't work anymore (it's looking for and using the incorrect classes). Without a test case or a way to generate the problem the best I could do was make an educated guess as to the solution. For both issues, I've taken the same approach - wrapping the collection and synchronizing access to the collection during iteration. That way there should be no alterations of the collection during iteration which should hopefully mitigate the issues related to what is likely multiple thread access. Index: src/com/icesoft/util/MonitorRunner.java =================================================================== --- src/com/icesoft/util/MonitorRunner.java (revision 36585) +++ src/com/icesoft/util/MonitorRunner.java (working copy) @@ -37,11 +37,12 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Iterator; public class MonitorRunner { private static final Log log = LogFactory.getLog(MonitorRunner.class); - private Collection monitors = new ArrayList(); + private Collection monitors = Collections.synchronizedList(new ArrayList()); private Thread thread; private boolean run = true; @@ -53,13 +54,15 @@ while (run) { if (count * 1000 >= interval) { count = 0; - Iterator i = new ArrayList(monitors).iterator(); - while (i.hasNext()) { - Runnable monitor = (Runnable) i.next(); - try { - monitor.run(); - } catch (Throwable t) { - log.warn("Failed to run monitor: " + monitor, t); + synchronized (monitors) { + Iterator i = new ArrayList(monitors).iterator(); + while (i.hasNext()) { + Runnable monitor = (Runnable) i.next(); + try { + monitor.run(); + } catch (Throwable t) { + log.warn("Failed to run monitor: " + monitor, t); + } } } }
        Hide
        Deryk Sinotte added a comment -

        Change checked in as described. Resolving as fixed but the customer will need to test to see if it fixes their issue as we cannot reproduce it.

        Show
        Deryk Sinotte added a comment - Change checked in as described. Resolving as fixed but the customer will need to test to see if it fixes their issue as we cannot reproduce it.

          People

          • Assignee:
            Deryk Sinotte
            Reporter:
            Tyler Johnson
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: