From 9d44c40037cf299e77e19993a5dbd422fcff16e9 Mon Sep 17 00:00:00 2001 From: Justin Bertram Date: Thu, 8 Aug 2019 11:06:07 -0500 Subject: [PATCH] ARTEMIS-2449 limit size of producer details The core server session tracks details about producers like what addresses have had messages sent to them, the most recent message ID sent to each address, and the number of messages sent to each address. This information is made available to users via the listProducersInfoAsJSON method on the various management interfaces (JMX, web console, etc.). However, in situations where a server session is long lived (e.g. in a pool) and is used to send to many different addresses (e.g. randomly named temporary JMS queues) this info can accumulate to a problematic degree. Therefore, we should limit the amount of producer details saved by the session. --- .../artemis/utils/collections/MaxSizeMap.java | 34 +++++++++++++++++++ .../core/server/impl/ServerSessionImpl.java | 3 +- .../jms/client/TemporaryDestinationTest.java | 20 +++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/MaxSizeMap.java diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/MaxSizeMap.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/MaxSizeMap.java new file mode 100644 index 0000000000..0c78638b85 --- /dev/null +++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/collections/MaxSizeMap.java @@ -0,0 +1,34 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.activemq.artemis.utils.collections; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class MaxSizeMap extends LinkedHashMap { + private final int maxSize; + + public MaxSizeMap(int maxSize) { + this.maxSize = maxSize; + } + + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > maxSize; + } +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java index c442e71e9b..90443026cc 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java @@ -95,6 +95,7 @@ import org.apache.activemq.artemis.spi.core.protocol.SessionCallback; import org.apache.activemq.artemis.utils.CompositeAddress; import org.apache.activemq.artemis.utils.JsonLoader; import org.apache.activemq.artemis.utils.PrefixUtil; +import org.apache.activemq.artemis.utils.collections.MaxSizeMap; import org.apache.activemq.artemis.utils.collections.TypedProperties; import org.jboss.logging.Logger; @@ -175,7 +176,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener { private final OperationContext context; // Session's usage should be by definition single threaded, hence it's not needed to use a concurrentHashMap here - protected final Map> targetAddressInfos = new HashMap<>(); + protected final Map> targetAddressInfos = new MaxSizeMap<>(100); private final long creationTime = System.currentTimeMillis(); diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/client/TemporaryDestinationTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/client/TemporaryDestinationTest.java index 260b1f509b..01cde6305c 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/client/TemporaryDestinationTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/client/TemporaryDestinationTest.java @@ -246,6 +246,26 @@ public class TemporaryDestinationTest extends JMSTestBase { } } + @Test + public void testForTempQueueTargetInfosSizeLimit() throws Exception { + try { + conn = createConnection(); + Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE); + for (int i = 0; i < 200; i++) { + TemporaryQueue temporaryQueue = s.createTemporaryQueue(); + MessageProducer producer = s.createProducer(temporaryQueue); + producer.send(s.createMessage()); + } + for (ServerSession serverSession : server.getSessions()) { + assertTrue(((ServerSessionImpl)serverSession).cloneTargetAddresses().size() <= 100); + } + } finally { + if (conn != null) { + conn.close(); + } + } + } + @Test public void testForSecurityCacheLeak() throws Exception { server.getSecurityStore().setSecurityEnabled(true);