Вопрос по string, java – Это хорошая практика, чтобы использовать java.lang.String.intern ()?

192

Error: User Rate Limit ExceededString.intern()Error: User Rate Limit Exceeded==)

  • When would I use this function in favor to String.equals()?
  • Are there side effects not mentioned in the Javadoc, i.e. more or less optimization by the JIT compiler?
  • Are there further uses of String.intern()?
Error: User Rate Limit Exceeded Peter Lawrey
Error: User Rate Limit Exceeded lacroix1547

Ваш Ответ

20   ответов
4

i.e. more or less optimization by the JIT compiler?

Error: User Rate Limit Exceededthere is direct bytecode support for the string poolError: User Rate Limit ExceededCONSTANT_String_infoError: User Rate Limit Exceeded

JVMS

Error: User Rate Limit Exceeded:

A string literal is a reference to an instance of class String, and is derived from a CONSTANT_String_info structure (§4.4.3) in the binary representation of a class or interface. The CONSTANT_String_info structure gives the sequence of Unicode code points constituting the string literal.

The Java programming language requires that identical string literals (that is, literals that contain the same sequence of code points) must refer to the same instance of class String (JLS §3.10.5). In addition, if the method String.intern is called on any string, the result is a reference to the same class instance that would be returned if that string appeared as a literal. Thus, the following expression must have the value true:

("a" + "b" + "c").intern() == "abc"

To derive a string literal, the Java Virtual Machine examines the sequence of code points given by the CONSTANT_String_info structure.

If the method String.intern has previously been called on an instance of class String containing a sequence of Unicode code points identical to that given by the CONSTANT_String_info structure, then the result of string literal derivation is a reference to that same instance of class String.

Otherwise, a new instance of class String is created containing the sequence of Unicode code points given by the CONSTANT_String_info structure; a reference to that class instance is the result of string literal derivation. Finally, the intern method of the new String instance is invoked.

Bytecode

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

public class StringPool {
    public static void main(String[] args) {
        String a = "abc";
        String b = "abc";
        String c = new String("abc");
        System.out.println(a);
        System.out.println(b);
        System.out.println(a == c);
    }
}

Error: User Rate Limit Exceeded

#2 = String             #32   // abc
[...]
#32 = Utf8               abc

Error: User Rate Limit Exceededmain:

 0: ldc           #2          // String abc
 2: astore_1
 3: ldc           #2          // String abc
 5: astore_2
 6: new           #3          // class java/lang/String
 9: dup
10: ldc           #2          // String abc
12: invokespecial #4          // Method java/lang/String."<init>":(Ljava/lang/String;)V
15: astore_3
16: getstatic     #5          // Field java/lang/System.out:Ljava/io/PrintStream;
19: aload_1
20: invokevirtual #6          // Method java/io/PrintStream.println:(Ljava/lang/String;)V
23: getstatic     #5          // Field java/lang/System.out:Ljava/io/PrintStream;
26: aload_2
27: invokevirtual #6          // Method java/io/PrintStream.println:(Ljava/lang/String;)V
30: getstatic     #5          // Field java/lang/System.out:Ljava/io/PrintStream;
33: aload_1
34: aload_3
35: if_acmpne     42
38: iconst_1
39: goto          43
42: iconst_0
43: invokevirtual #7          // Method java/io/PrintStream.println:(Z)V

Error: User Rate Limit Exceeded

0 and 3: the same ldc #2 constant is loaded (the literals) 12: a new string instance is created (with #2 as argument) 35: a and c are compared as regular objects with if_acmpne

Error: User Rate Limit Exceeded

it has a dedicated CONSTANT_String_info structure, unlike regular objects (e.g. new String) the struct points to a CONSTANT_Utf8_info Structure that contains the data. That is the only necessary data to represent the string.

Error: User Rate Limit Exceededldc.

Error: User Rate Limit Exceeded

static final String s = "abc" points to the constant table through the ConstantValue Attribute non-final fields don't have that attribute, but can still be initialized with ldc

BonusError: User Rate Limit ExceededError: User Rate Limit ExceededError: User Rate Limit ExceededCONSTANT_String_infoError: User Rate Limit Exceeded

Error: User Rate Limit Exceeded Daniel Rikowski
0

Error: User Rate Limit Exceeded
7

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit ExceededUserIdError: User Rate Limit Exceededjava.lang.StringError: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

1

0

Error: User Rate Limit Exceeded
2

equals()equals()

if (this == anObject) {
    return true;
}

Collection

0

2

subString()

new String( s.subString(...))subString(...)intern()

Error: User Rate Limit ExceededChanges to String internal representation made in Java 1.7.0_06.
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
0

/**
 * Extends the notion of String.intern() to different mechanisms and
 * different types. For example, an implementation can use an
 * LRUCache<T,?>, or a WeakHashMap.
 */
public interface Internalizer<T> {
    public T get(T obj);
}
public static class LRUInternalizer<T> implements Internalizer<T> {
    private final LRUCache<T, T> cache;
    public LRUInternalizer(int size) {
        cache = new LRUCache<T, T>(size) {
            private static final long serialVersionUID = 1L;
            @Override
            protected T retrieve(T key) {
                return key;
            }
        };
    }
    @Override
    public T get(T obj) {
        return cache.get(obj);
    }
}
public class PermGenInternalizer implements Internalizer<String> {
    @Override
    public String get(String obj) {
        return obj.intern();
    }
}

LRUCacheLinkedHashMap<K,V>retrieve()

LRUInternalizer

Internalizer<String> internalizer = new LRUInternalizer(2048);
// ... get some object "input" that stream fields
for (String s : input.nextField()) {
    s = internalizer.get(s);
    // store s...
}
36

String.intern()Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded

// java -cp .
public class UserOfIntern {
    public static void main(String[] args) {
        Random random = new Random();
        System.out.println(random.nextLong());
        while (true) {
            String s = String.valueOf(random.nextLong());
            s = s.intern();
        }
    }
}

Error: User Rate Limit ExceededError: User Rate Limit Exceeded.

1

Error: User Rate Limit Exceeded

Error: User Rate Limit ExceededString.equals()Error: User Rate Limit Exceeded"=="Error: User Rate Limit ExceededStringError: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceededintern()Error: User Rate Limit Exceededequals()Error: User Rate Limit Exceeded

Error: User Rate Limit ExceededString.equals()Error: User Rate Limit Exceeded"=="Error: User Rate Limit Exceededequals()Error: User Rate Limit ExceededString.equals()Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

    Integer i = 1;
    System.out.println("1".equals(i));

Error: User Rate Limit ExceedediError: User Rate Limit Exceededi.toString()Error: User Rate Limit Exceededtrue.

Error: User Rate Limit ExceededSetError: User Rate Limit ExceededMapError: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceededintern()Error: User Rate Limit Exceeded

Error: User Rate Limit Exceededintern()Error: User Rate Limit Exceededintern()Error: User Rate Limit Exceeded

0

String a = SOME_RANDOM_VALUE
a.intern()

String a = SOME_RANDOM_VALUE.intern()
2

193

String.intern()

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededand an extra oneError: User Rate Limit Exceededstr.intern()Error: User Rate Limit ExceededstrError: User Rate Limit Exceeded"Hello".
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
6

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Daniel Rikowski
Error: User Rate Limit ExceededveryError: User Rate Limit ExceededinternError: User Rate Limit ExceededequalsError: User Rate Limit ExceededinternError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
0

private static WeakHashMap<String, WeakReference<String>> internStrings = new WeakHashMap<>();
public static String internalize(String k) {
    synchronized (internStrings) {
        WeakReference<String> weakReference = internStrings.get(k);
        String v = weakReference != null ? weakReference.get() : null;
        if (v == null) {
            v = k;
            internStrings.put(v, new WeakReference<String>(v));
        }
        return v;
    }
}

highEnoughValue.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
124

Error: User Rate Limit ExceededspeedError: User Rate Limit Exceeded

Are there side effects not mentioned in the Javadoc?

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededif (s1.equals(s2))Error: User Rate Limit Exceededif (i1 == i2)Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Daniel Rikowski
13

Comparing strings with == is much faster than with equals()

5 Time faster, but since String comparision usually represents only a small percentage of the total execution time of an application, the overall gain is much smaller than that, and the final gain will be diluted to a few percent.

String.intern() pull the string away from Heap and put it in PermGen

String internalized are put in a different storage area : Error: User Rate Limit ExceededError: User Rate Limit Exceeded

String.intern() string are garbage collected

In the new versions of JVM also internalized string are garbage collected when not referenced by any object.

Error: User Rate Limit Exceeded

Error: User Rate Limit ExceededJava 7, interned strings are in the heap.
Error: User Rate Limit Exceeded
16

.

Avoid String.intern() in Java 6, because it goes into PermGen Prefer String.intern() in Java 7 & Java 8: it uses 4-5x less memory than rolling your own object pool Be sure to tune -XX:StringTableSize (the default is probably too small; set a Prime number)
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
4

String interning is meant to save memory (heap).

In JDK 7, interned strings are no longer allocated in the permanent generation of the Java heap, but are instead allocated in the main part of the Java heap (known as the young and old generations), along with the other objects created by the application. This change will result in more data residing in the main Java heap, and less data in the permanent generation, and thus may require heap sizes to be adjusted. Most applications will see only relatively small differences in heap usage due to this change, but larger applications that load many classes or make heavy use of the String.intern() method will see more significant differences.

Error: User Rate Limit ExceededStringError: User Rate Limit Exceededintern()Error: User Rate Limit Exceeded

Похожие вопросы