简体   繁体   English

实习字符串

[英]Interning a string

When we intern a string, we are making sure that all uses of that string are referring to the same instance. 当我们内联一个字符串时,我们要确保该字符串的所有使用都指向同一实例。

I would assume that the underlying string object is in the heap. 我假设基础字符串对象在堆中。

However, where is the referring variable stored in the memory? 但是,引用变量存储在内存中的什么位置?

Does it have the same behaviour as static - wherein the reference gets stored in permgen and makes the string instance available for gc only after the classloader(and application) exits? 它是否具有与static相同的行为-引用仅存储在permgen中,并且仅在类加载器(和应用程序)退出后才使字符串实例可用于gc?

Up to JDK 6, Intern'ed strings are stored in the memory pool in a place called the Permanent Generation, which is an area of the JVM that is reserved for non-user objects, like Classes, Methods and other internal JVM objects. 直到JDK 6,Intern字符串都存储在内存池中的一个名为Permanent Generation的位置,该位置是JVM的一个区域,为非用户对象(如类,方法和其他内部JVM对象)保留。 The size of this area is limited, and is usually much smaller than the heap. 该区域的大小是有限的,并且通常比堆小得多。

From 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. 从JDK 7开始,不再将永久字符串分配给Java堆的永久代中,而是与应用程序创建的其他对象一起分配给Java堆的主要部分(称为年轻代和老一代)中。 。 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. 此更改将导致更多数据驻留在主Java堆中,而永久生成中的数据更少,因此可能需要调整堆大小。 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. 由于此更改,大多数应用程序只会看到相对较小的堆使用差异,但是加载许多类或大量使用String.intern()方法的大型应用程序将看到更大的差异。

A detailed explanation of this can be found on this answer . 在此答案中可以找到对此的详细说明。

When we intern a string, we are making sure that all uses of that string are referring to the same instance. 当我们内联一个字符串时,我们要确保该字符串的所有使用都指向同一实例。

Not exactly. 不完全是。 When you do this: 执行此操作时:

    String s2 = s1.intern();

what you are doing is ensuring that s2 refers to a String in the string pool. 你正在做的是确保s2是指一个String在字符串池中。 This does not affect the value in s1 , or any other String references or variables. 这不会影响s1的值或任何其他String引用或变量。 If you want other copies of the string to be interned, you need to do that explicitly ... or assign interned string references to the respective variables. 如果要插入字符串的其他副本,则需要明确地执行此操作……或将插入的字符串引用分配给相应的变量。

I would assume that the underlying string object is in the heap. 我假设基础字符串对象在堆中。

That is correct. 那是对的。 It might be in the "permgen" heap or the regular heap, depending on the version of Java you are using. 它可能在“ permgen”堆中,也可能在常规堆中,这取决于所使用的Java版本。 But it is always "in the heap". 但是它始终是“堆中的”。

However, where is the referring variable stored in the memory? 但是,引用变量存储在内存中的什么位置?

The "referring variable" ... ie the one that holds the reference that you got from calling intern() ... is no different from any other variable. “引用变量” ...即保存您通过调用intern()获得的引用的引用变量,与任何其他变量没有什么不同。 It can be 有可能

  • a local variable or parameter (held in a stack frame), 局部变量或参数(保存在堆栈框架中),
  • an instance field (held in a regular heap object), 一个实例字段(保存在常规堆对象中),
  • a static field (held in a permgen heap object) ... or even 一个静态字段(保存在permgen堆对象中)...甚至
  • a jstring variable or similar in JNI code (held "somewhere else".) 一个jstring变量或JNI代码中的类似变量(保存在“其他地方”。)

In fact, a typical JVM uses a private hash table to hold the references to interned strings, and it uses the JVM's weak reference mechanism to ensure that interned strings can be garbage collected if nothing else is using them. 实际上,典型的JVM使用私有哈希表来保存对实习生字符串的引用,并且它使用JVM的弱引用机制来确保如果没有其他任何使用的实习生字符串可以被垃圾回收。

Does it have the same behaviour as static - wherein the reference gets stored in permgen and makes the string instance available for gc only after the classloader(and application) exits? 它是否具有与static相同的行为-引用仅存储在permgen中,并且仅在类加载器(和应用程序)退出后才使字符串实例可用于gc?

Typically no ... see above. 通常没有...请参见上文。

In most Java platforms, interned Strings can be garbage collected just like other Strings. 在大多数Java平台中,可以像其他字符串一样对垃圾字符串进行垃圾回收。 If the interned Strings are stored in "permgen" space, it may take longer for the object to be garbage collected, because "permgen" is collected infrequently. 如果将内联的字符串存储在“ permgen”空间中,则可能会花费更长的时间来垃圾回收对象,因为“ permgen”很少被收集。 However the lifetime of an interned String is not tied to the lifetime of a classloader, etc. 但是,实习生String的生存期与类加载器等的生存期无关。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM