Uploaded image for project: 'ActiveMQ'
  1. ActiveMQ
  2. AMQ-8011

Performance Related issue in ClassLoadingAwareObjectInputStream.checkSecurity( )

Agile BoardAttach filesAttach ScreenshotVotersWatch issueWatchersCreate sub-taskLinkCloneUpdate Comment AuthorReplace String in CommentUpdate Comment VisibilityDelete Comments
    XMLWordPrintableJSON

    Details

    • Type: Improvement
    • Status: Resolved
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 5.14.5
    • Fix Version/s: 5.17.0, 5.16.1, 5.15.14
    • Component/s: JMS client
    • Labels:
      None

      Description

      ClassLoadingAwareObjectInputStream.checkSecurity( ) is inefficient as it's repeatedly calling Class.getPackage( ).
      It only needs to be invoked once.
      It doesn't need to be invoked at all if trustAllPackage( ) == true

       

      Class.getPackage( ) calls Package.getPackage( )
      Package.getPackage( ) calls ClassLoader.getPackage(name)
      ClassLoader.getPackage( ) contains a synchronized block (on HashMap) that ends up delaying other threads when:

      • The rate of messaging is very high when security is enabled.
      • it's made worse by the number of packages in TRUSTED_PACKAGES
      • also made worse by the ordering of packages in TRUSTED_PACKAGES
      • if the package being compared is further down the list, it exacerbates the issue.

      We have seen our code calling clazz.getPackage( ) upwards of 15 times during the handling of a single message.

       

       

      StackTrace of delayed threads:

      "ActiveMQ Session Task-1280" #164931 prio=7 os_prio=0 tid=0x00007f2764002800 nid=0x522d waiting for monitor entry [0x00007f24c3436000]
         java.lang.Thread.State: BLOCKED (on object monitor)
              at java.lang.ClassLoader.getPackage(ClassLoader.java:1611)
              - waiting to lock <0x00000006dd9b39c0> (a java.util.HashMap)
              at java.lang.Package.getPackage(Package.java:334)
              at java.lang.Class.getPackage(Class.java:796)
              at org.apache.activemq.util.ClassLoadingAwareObjectInputStream.checkSecurity(ClassLoadingAwareObjectInputStream.java:106)
              at org.apache.activemq.util.ClassLoadingAwareObjectInputStream.resolveClass(ClassLoadingAwareObjectInputStream.java:57)
              at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1924)
              at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1807)
              at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1941)
              at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1807)
              at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1941)
              at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1807)
              at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2098)
              at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1624)
              at java.io.ObjectInputStream.readObject(ObjectInputStream.java:464)
              at java.io.ObjectInputStream.readObject(ObjectInputStream.java:422)
              at java.util.ArrayList.readObject(ArrayList.java:797)
              at sun.reflect.GeneratedMethodAccessor97.invoke(Unknown Source)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
              at java.lang.reflect.Method.invoke(Method.java:498)
              at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1184)
              at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2234)
              at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2125)
              at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1624)
              at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2343)
              at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2267)
              at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2125)
              at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1624)
              at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2343)
              at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2267)
              at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2125)
              at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1624)
              at java.io.ObjectInputStream.readObject(ObjectInputStream.java:464)
              at java.io.ObjectInputStream.readObject(ObjectInputStream.java:422)
              at org.apache.activemq.command.ActiveMQObjectMessage.getObject(ActiveMQObjectMessage.java:206)
      

       

      StackTrace of the thread holding the lock:

      "ActiveMQ Session Task-3517" #164719 prio=7 os_prio=0 tid=0x00007f26ac008800 nid=0x225c waiting for monitor entry [0x00007f26fb41d000]
         java.lang.Thread.State: BLOCKED (on object monitor)
              at java.lang.ClassLoader.getPackage(ClassLoader.java:1611)
              - locked <0x00000006dd9b39c0> (a java.util.HashMap)
              at java.lang.Package.getPackage(Package.java:334)
              at java.lang.Class.getPackage(Class.java:796)
              at org.apache.activemq.util.ClassLoadingAwareObjectInputStream.checkSecurity(ClassLoadingAwareObjectInputStream.java:106)
              at org.apache.activemq.util.ClassLoadingAwareObjectInputStream.resolveClass(ClassLoadingAwareObjectInputStream.java:57)
              at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1924)
              at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1807)
              at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2098)
              at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1624)
              at java.io.ObjectInputStream.readObject(ObjectInputStream.java:464)
              at java.io.ObjectInputStream.readObject(ObjectInputStream.java:422)
              at org.apache.activemq.command.ActiveMQObjectMessage.getObject(ActiveMQObjectMessage.java:206)

       

      The code in 5.16.0 looks the same and probably is subject to the same issue.

        Attachments

          Activity

            People

            • Assignee:
              jbonofre Jean-Baptiste Onofré
              Reporter:
              levandos Andrew Levandoski

              Dates

              • Created:
                Updated:
                Resolved:

              Time Tracking

              Estimated:
              Original Estimate - Not Specified
              Not Specified
              Remaining:
              Remaining Estimate - 0h
              0h
              Logged:
              Time Spent - 1h 10m
              1h 10m

                Issue deployment