/** * 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.bugs; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; import java.lang.management.ManagementFactory; import java.util.concurrent.CountDownLatch; import javax.management.MBeanServer; import javax.management.ObjectName; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.activemq.ActiveMQConnection; import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.broker.BrokerService; import org.apache.activemq.util.Wait; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Unit test for simple App. */ public class AMQ4531Test extends TestCase { private final Logger LOG = LoggerFactory.getLogger(AMQ4531Test.class); private String connectionURI; private MBeanServer mbeanServer; private BrokerService broker; @Override protected void setUp() throws Exception { super.setUp(); broker = new BrokerService(); connectionURI = broker.addConnector("tcp://0.0.0.0:0?maximumConnections=1").getPublishableConnectString(); broker.setPersistent(false); broker.start(); mbeanServer = ManagementFactory.getPlatformMBeanServer(); } @Override protected void tearDown() throws Exception { broker.stop(); super.tearDown(); } /** * Create the test case * * @param testName * name of the test case */ public AMQ4531Test(String testName) { super(testName); } /** * @return the suite of tests being tested */ public static Test suite() { return new TestSuite(AMQ4531Test.class); } public void testFDSLeak() throws Exception { ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(connectionURI); ActiveMQConnection connection = (ActiveMQConnection) factory.createConnection(); connection.start(); int connections = 100; final long original = openFileDescriptorCount(); LOG.info("FD count: " + original); final CountDownLatch done = new CountDownLatch(connections); for (int i = 0; i < connections; i++) { new Thread("worker: " + i) { @Override public void run() { ActiveMQConnection connection = null; try { ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(connectionURI); connection = (ActiveMQConnection) factory.createConnection(); connection.start(); } catch (Exception e) { LOG.debug(getStack(e)); } finally { try { connection.close(); } catch (Exception e) { LOG.debug(getStack(e)); } done.countDown(); LOG.debug("Latch count down called."); } } }.start(); } // Wait for all the clients to finish LOG.info("Waiting for latch..."); done.await(); LOG.info("Latch complete."); LOG.info("FD count: " + openFileDescriptorCount()); assertTrue("Too many open file descriptors: " + openFileDescriptorCount(), Wait.waitFor(new Wait.Condition() { @Override public boolean isSatisified() throws Exception { long openFDs = openFileDescriptorCount(); LOG.info("Current FD count [{}], original FD count[{}]", openFDs, original); return (openFDs - original) < 10; } })); } private long openFileDescriptorCount() throws Exception { return ((Long) mbeanServer.getAttribute(new ObjectName("java.lang:type=OperatingSystem"), "OpenFileDescriptorCount")).longValue(); } private String getStack(Throwable aThrowable) { final Writer result = new StringWriter(); final PrintWriter printWriter = new PrintWriter(result); aThrowable.printStackTrace(printWriter); return result.toString(); } }