diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/ipc/AbstractRpcClient.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/ipc/AbstractRpcClient.java index 8fc5b0c588d..629efe6c203 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/ipc/AbstractRpcClient.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/ipc/AbstractRpcClient.java @@ -463,6 +463,7 @@ public abstract class AbstractRpcClient implements RpcC + connection.remoteId); connections.removeValue(remoteId, connection); connection.shutdown(); + connection.cleanupConnection(); } } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestConnectionImplementation.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestConnectionImplementation.java index c8cbe747f0e..98344fe3fcb 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestConnectionImplementation.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestConnectionImplementation.java @@ -67,6 +67,7 @@ import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; import org.apache.hadoop.hbase.util.JVMClusterUtil; import org.apache.hadoop.hbase.util.ManualEnvironmentEdge; import org.apache.hadoop.hbase.util.Threads; +import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -80,6 +81,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.hbase.thirdparty.com.google.common.collect.Lists; +import org.apache.hbase.thirdparty.io.netty.util.ResourceLeakDetector; +import org.apache.hbase.thirdparty.io.netty.util.ResourceLeakDetector.Level; /** * This class is for testing HBaseConnectionManager features @@ -111,6 +114,7 @@ public class TestConnectionImplementation { @BeforeClass public static void setUpBeforeClass() throws Exception { + ResourceLeakDetector.setLevel(Level.PARANOID); TEST_UTIL.getConfiguration().setBoolean(HConstants.STATUS_PUBLISHED, true); // Up the handlers; this test needs more than usual. TEST_UTIL.getConfiguration().setInt(HConstants.REGION_SERVER_HIGH_PRIORITY_HANDLER_COUNT, 10); @@ -125,6 +129,11 @@ public class TestConnectionImplementation { TEST_UTIL.shutdownMiniCluster(); } + @After + public void tearDown() throws IOException { + TEST_UTIL.getAdmin().balancerSwitch(true, true); + } + @Test public void testClusterConnection() throws IOException { ThreadPoolExecutor otherPool = new ThreadPoolExecutor(1, 1, @@ -283,7 +292,7 @@ public class TestConnectionImplementation { TableName tableName = TableName.valueOf("HCM-testConnectionClose" + allowsInterrupt); TEST_UTIL.createTable(tableName, FAM_NAM).close(); - boolean previousBalance = TEST_UTIL.getAdmin().setBalancerRunning(false, true); + TEST_UTIL.getAdmin().balancerSwitch(false, true); Configuration c2 = new Configuration(TEST_UTIL.getConfiguration()); // We want to work on a separate connection. @@ -348,9 +357,9 @@ public class TestConnectionImplementation { RpcClient rpcClient = conn.getRpcClient(); LOG.info("Going to cancel connections. connection=" + conn.toString() + ", sn=" + sn); - for (int i = 0; i < 5000; i++) { + for (int i = 0; i < 500; i++) { rpcClient.cancelConnections(sn); - Thread.sleep(5); + Thread.sleep(50); } step.compareAndSet(1, 2); @@ -365,7 +374,6 @@ public class TestConnectionImplementation { table.close(); connection.close(); Assert.assertTrue("Unexpected exception is " + failed.get(), failed.get() == null); - TEST_UTIL.getAdmin().setBalancerRunning(previousBalance, true); } /** @@ -1089,4 +1097,22 @@ public class TestConnectionImplementation { assertNotNull(ex); } } + + // There is no assertion, but you need to confirm that there is no resource leak output from netty + @Test + public void testCancelConnectionMemoryLeak() throws IOException, InterruptedException { + TableName tableName = TableName.valueOf(name.getMethodName()); + TEST_UTIL.createTable(tableName, FAM_NAM).close(); + TEST_UTIL.getAdmin().balancerSwitch(false, true); + try (Connection connection = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration()); + Table table = connection.getTable(tableName)) { + table.get(new Get(Bytes.toBytes("1"))); + ServerName sn = TEST_UTIL.getRSForFirstRegionInTable(tableName).getServerName(); + RpcClient rpcClient = ((ConnectionImplementation) connection).getRpcClient(); + rpcClient.cancelConnections(sn); + Thread.sleep(1000); + System.gc(); + Thread.sleep(1000); + } + } } diff --git a/pom.xml b/pom.xml index 7b0d2ba77c4..f453a59a2db 100755 --- a/pom.xml +++ b/pom.xml @@ -1401,10 +1401,12 @@ -enableassertions -Dhbase.build.id=${build.id} -Xmx${surefire.Xmx} -Djava.security.egd=file:/dev/./urandom -Djava.net.preferIPv4Stack=true -Djava.awt.headless=true -Djdk.net.URLClassPath.disableClassPathURLCheck=true + -Dorg.apache.hbase.thirdparty.io.netty.leakDetection.level=paranoid -enableassertions -Xmx${surefire.cygwinXmx} -Djava.security.egd=file:/dev/./urandom -Djava.net.preferIPv4Stack=true "-Djava.library.path=${hadoop.library.path};${java.library.path}" + -Dorg.apache.hbase.thirdparty.io.netty.leakDetection.level=paranoid ${hbase-surefire.argLine}