Details
-
Improvement
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
5.14.5
-
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
Issue Links
- is duplicated by
-
AMQ-8534 Improve ClassLoadingAwareObjectInputStream.checkSecurity(Class) performance
- Closed