diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/StringInterner.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/StringInterner.java new file mode 100644 index 0000000000..d087610a5d --- /dev/null +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/StringInterner.java @@ -0,0 +1,78 @@ +/** + * 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.hadoop.util; + +import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.classification.InterfaceStability; + +import com.google.common.collect.Interner; +import com.google.common.collect.Interners; + +/** + * Provides equivalent behavior to String.intern() to optimize performance, + * whereby does not consume memory in the permanent generation. + */ +@InterfaceAudience.Public +@InterfaceStability.Stable +public class StringInterner { + + /** + * Retains a strong reference to each string instance it has interned. + */ + private final static Interner strongInterner; + + /** + * Retains a weak reference to each string instance it has interned. + */ + private final static Interner weakInterner; + + + + static { + strongInterner = Interners.newStrongInterner(); + weakInterner = Interners.newWeakInterner(); + } + + /** + * Interns and returns a reference to the representative instance + * for any of a collection of string instances that are equal to each other. + * Retains strong reference to the instance, + * thus preventing it from being garbage-collected. + * + * @param sample string instance to be interned + * @return strong reference to interned string instance + */ + public static String strongIntern(String sample) { + return strongInterner.intern(sample); + } + + /** + * Interns and returns a reference to the representative instance + * for any of a collection of string instances that are equal to each other. + * Retains weak reference to the instance, + * and so does not prevent it from being garbage-collected. + * + * @param sample string instance to be interned + * @return weak reference to interned string instance + */ + public static String weakIntern(String sample) { + return weakInterner.intern(sample); + } + +} diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestStringInterner.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestStringInterner.java new file mode 100644 index 0000000000..e43da49d75 --- /dev/null +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestStringInterner.java @@ -0,0 +1,76 @@ +/** + * 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.hadoop.util; + +import static org.junit.Assert.*; +import static org.apache.hadoop.util.StringInterner.*; + +import org.junit.Test; + +/** + * + * Tests string interning {@link StringInterner} + */ +public class TestStringInterner { + + /** + * Test different references are returned for any of string + * instances that are equal to each other but not interned. + */ + @Test + public void testNoIntern() { + String literalABC = "ABC"; + String substringABC = "ABCDE".substring(0,3); + String heapABC = new String("ABC"); + assertNotSame(literalABC, substringABC); + assertNotSame(literalABC, heapABC); + assertNotSame(substringABC, heapABC); + } + + + /** + * Test the same strong reference is returned for any + * of string instances that are equal to each other. + */ + @Test + public void testStrongIntern() { + String strongInternLiteralABC = strongIntern("ABC"); + String strongInternSubstringABC = strongIntern("ABCDE".substring(0,3)); + String strongInternHeapABC = strongIntern(new String("ABC")); + assertSame(strongInternLiteralABC, strongInternSubstringABC); + assertSame(strongInternLiteralABC, strongInternHeapABC); + assertSame(strongInternSubstringABC, strongInternHeapABC); + } + + + /** + * Test the same weak reference is returned for any + * of string instances that are equal to each other. + */ + @Test + public void testWeakIntern() { + String weakInternLiteralABC = weakIntern("ABC"); + String weakInternSubstringABC = weakIntern("ABCDE".substring(0,3)); + String weakInternHeapABC = weakIntern(new String("ABC")); + assertSame(weakInternLiteralABC, weakInternSubstringABC); + assertSame(weakInternLiteralABC, weakInternHeapABC); + assertSame(weakInternSubstringABC, weakInternHeapABC); + } + +}