📄 chap08.html
字号:
<P><H4>Step 1. Load the Type and any Superclasses</H4></P>
<P>Resolution of a non-array class or interface begins by making sure the type is loaded into the current name space. If the virtual machine determines that the referenced type hasn韙 yet been loaded into the current name space, it passes the fully qualified name of the type to a class loader. The class loader loads the type, parses the binary data into internal data structures, and creates a <FONT FACE="Courier New">Class</FONT> instance.</P>
<P>Once the referenced type is loaded in, the virtual machine can peer into its binary data. If the type is a class and not <FONT FACE="Courier New">java.lang.Object</FONT>, the virtual machine determines from the classs韘 data the fully qualified name of the class韘 direct superclass. The virtual machine then checks to see if the superclass has been loaded into the current name space. If not, it loads the superclass. Once that class comes in, the virtual machine can again peer into its binary data to find its superclass. This process repeats all the way up to <FONT FACE="Courier New">Object</FONT>.</P>
<P>Through Step 1, the Java Virtual Machine makes sure a type is loaded, and if the type is a class, that all its superclasses are loaded. During this step, these types are not linked and initialized--just loaded.</P>
<P>If the referencing type (the one that contains in its constant pool the <FONT FACE="Courier New">CONSTANT_Class_info</FONT> entry being resolved) was loaded through the primordial class loader, the virtual machine uses the primordial class loader to load the referenced type (and its superclasses, if any). Otherwise, the referencing type was loaded through a class loader object, and the virtual machine uses the same class loader object to load the referenced type.</P>
<P>The Java Virtual Machine maintains a list of the names of all the types already loaded by each class loader. Each of these lists forms a name space inside the Java Virtual Machine. The virtual machine uses this list during resolution to determine whether a class has already been loaded by a particular class loader. If during resolution, the Java Virtual Machine encounters a symbolic reference to a class that was not previously loaded by the appropriate class loader, that class loader will be asked to load the class. If the appropriate class loader is a class loader object, the Java Virtual Machine will make the load request by invoking the class loader object韘 <FONT FACE="Courier New">loadClass()</FONT> method. On the other hand, if the Java Virtual Machine encounters a symbolic reference to a class previously loaded by the same class loader object, the class loader object will not be asked to load it again. Instead, the class previously loaded will automatically be used again. This helps ensure that only one class with a given name is loaded by a particular class loader.</P>
<P>If the referencing type was loaded via the primordial class loader, the virtual machine will check the primordial class loader韘 name space to see if the class was already loaded. If not, the virtual machine will use the primordial class loader to load the referenced type in an implementation-dependent way. If the referenced type is a class, the virtual machine will make sure all the class韘 superclasses are loaded as well. If any of these classes haven韙 yet been loaded into the primordial loader韘 name space, the virtual machine will use the primordial class loader to load those classes.</P>
<P>If the referencing type was loaded via a class loader object, the virtual machine invokes <FONT FACE="Courier New">loadClass()</FONT> on the class loader object that loaded the referencing type, passing in parameter <FONT FACE="Courier New">name</FONT> the fully qualified name of the referenced type and setting the <FONT FACE="Courier New">resolve</FONT> flag to <FONT FACE="Courier New">true</FONT>. When <FONT FACE="Courier New">loadClass()</FONT> returns, it will have performed both Step 1 (loading) and Steps 2a through 2e (linking and initialization). (It will perform Steps 2a through 2e because the <FONT FACE="Courier New">resolve</FONT> flag is set to <FONT FACE="Courier New">true</FONT>.) Nonetheless, the <FONT FACE="Courier New">loadClass()</FONT> method will perform Step 1 completely before embarking on Steps 2a through 2e.</P>
<P>When a class loader object韘 <FONT FACE="Courier New">loadClass()</FONT> method is invoked, it has two ways to do its job. One way is to use the primordial class loader by invoking <FONT FACE="Courier New">findSystemClass()</FONT>. In this case, the primordial loader will load, link, and initialize the requested type. Alternatively, <FONT FACE="Courier New">loadClass()</FONT> can produce the binary data in its own custom way, then call <FONT FACE="Courier New">defineClass()</FONT> and--if <FONT FACE="Courier New">true</FONT> was passed in <FONT FACE="Courier New">loadClass()</FONT>韘 <FONT FACE="Courier New">resolve</FONT> parameter--call <FONT FACE="Courier New">resolveClass()</FONT>. In this case, the class loader object would produce the binary form for the requested type in its own custom way, then used the primordial class loader韘 standard mechanism to link and initialize the type. Here are the declarations for <FONT FACE="Courier New">findSystemClass()</FONT>, <FONT FACE="Courier New">defineClass()</FONT>, and <FONT FACE="Courier New">resolveClass()</FONT>:</P>
<PRE><P><FONT FACE="Courier New">begin</FONT></P>
<FONT FACE="Courier New"><P>// Three methods declared in class java.lang.ClassLoader:</P>
<P>protected final Class findSystemClass(String name)</P>
<P> throws ClassNotFoundException;</P>
<P>protected final Class defineClass(String name, byte data[],</P>
<P> int offset, int length);</P>
<P>protected final void resolveClass(Class c);</P>
</FONT><P><FONT FACE="Courier New">end</FONT></P></PRE>
<P>If the <FONT FACE="Courier New">loadClass()</FONT> method invokes <FONT FACE="Courier New">findSystemClass()</FONT>, the class loader object is in effect asking the virtual machine to use the primordial loader to resolve the reference completely. The <FONT FACE="Courier New">findSystemClass()</FONT> method accepts the fully qualified name of the type to resolve in its <FONT FACE="Courier New">name</FONT> parameter. If the primordial class loader is able to successfully resolve the reference, it returns a reference to a <FONT FACE="Courier New">Class</FONT> instance that represents the referenced type. The <FONT FACE="Courier New">loadClass()</FONT> method would then just return a reference to the same <FONT FACE="Courier New">Class</FONT> instance. If the primordial class loader is unsuccessful, however, <FONT FACE="Courier New">findSystemClass()</FONT> will complete abnormally by throwing a <FONT FACE="Courier New">ClassNotFoundException</FONT>. In this case, the <FONT FACE="Courier New">loadClass()</FONT> method can either throw <FONT FACE="Courier New">ClassNotFoundException</FONT> itself or attempt to load the type in its custom way.</P>
<P>Types brought in through the primordial class loader via <FONT FACE="Courier New">findSystemClass()</FONT> are marked as having no class loader object. Any types they refer to will be requested directly from the primordial loader.</P>
<P>If the <FONT FACE="Courier New">loadClass()</FONT> method produces the stream of binary data for the type in its own custom way (such as if it downloads the type韘 class file across a network), it must invoke <FONT FACE="Courier New">defineClass()</FONT>, passing a reference to a <FONT FACE="Courier New">byte</FONT> array containing the type韘 binary data in the Java class file format.</P>
<P>Invoking <FONT FACE="Courier New">defineClass()</FONT> will cause the virtual machine to do two things. First, the virtual machine will parse the binary data into internal data structures and create a <FONT FACE="Courier New">Class</FONT> instance to represent the type. Second, if the type is a class and not <FONT FACE="Courier New">java.lang.Object</FONT>, the virtual machine will retrieve the name of the class韘 direct superclass. It will then check to see if the direct superclass has been previously loaded by this class loader object (the one whose <FONT FACE="Courier New">loadClass()</FONT> method just invoked <FONT FACE="Courier New">defineClass()</FONT>). This is a check to see if the direct superclass already resides in the current name space. If the direct superclass has already been loaded by this class loader object, the <FONT FACE="Courier New">defineClass()</FONT> method returns the <FONT FACE="Courier New">Class</FONT> instance for the freshly loaded type. Otherwise, the virtual machine invokes <FONT FACE="Courier New">loadClass()</FONT> on the same class loader object, passing the fully qualified name of the direct superclass in the <FONT FACE="Courier New">name</FONT> parameter and setting the <FONT FACE="Courier New">resolve</FONT> flag to <FONT FACE="Courier New">false</FONT>. Because the <FONT FACE="Courier New">resolve</FONT> flag is <FONT FACE="Courier New">false</FONT>, the direct superclass (and recursively, all its superclasses) will be loaded, but not linked or initialized.</P>
<P>The reason the resolve flag is set to false when <FONT FACE="Courier New">loadClass()</FONT> is invoked by <FONT FACE="Courier New">defineClass()</FONT> is because this is Step 1: loading of the type and any superclasses. Linking and initialization, which would occur if <FONT FACE="Courier New">resolve</FONT> were set to <FONT FACE="Courier New">true</FONT>, is saved for Step 2.</P>
<P>When <FONT FACE="Courier New">defineClass()</FONT> has made certain the type and all its superclasses, if any, have been loaded into the current name space. It returns the new <FONT FACE="Courier New">Class</FONT> instance that represents the type. Step 1 is then complete.</P>
<P>During Step 1, the virtual machine may throw the following errors:</P>
<UL><LI> If the binary data can韙 be produced (for example, if a class file of the appropriate name can韙 be found), the virtual machine throws <FONT FACE="Courier New">NoClassDefFoundError</FONT>.
<LI> If the binary data is produced, but isn韙 of the proper structure or a recognized version (such as if the minor or major version number of a Java class file is too high), the virtual machine throws <FONT FACE="Courier New">NoClassDefFoundError</FONT>.
<LI> If the binary data is produced and well formed, but doesn韙 contain the sought after class or interface (such as if file <FONT FACE="Courier New">CuteKitty.class</FONT> is discovered to contain class <FONT FACE="Courier New">HungryTiger</FONT> instead of <FONT FACE="Courier New">CuteKitty</FONT>) , the virtual machine throws <FONT FACE="Courier New">NoClassDefFoundError</FONT>.
<LI> If the class doesn韙 contain a superclass and isn韙 class <FONT FACE="Courier New">Object</FONT> itself, the virtual machine throws a <FONT FACE="Courier New">ClassFormatError</FONT>. (Note that this check has to be done here, during the loading step, because that one piece of information--the symbolic reference to the superclass--is needed by the virtual machine during this step. During Step 1, the virtual machine must load in all the superclasses recursively.)
<LI> If a class appears as its own superclass, the virtual machine throws <FONT FACE="Courier New">ClassCircularityError</FONT>.</UL>
<P><H4>Step 2. Link and Initialize the Type and any Superclasses</H4></P>
<P>At this point, the type being referred to by the <FONT FACE="Courier New">CONSTANT_Class_info</FONT> entry being resolved has been loaded, but not linked or initialized. In addition, if the type being resolved is a class, all its superclasses have been loaded, but not necessarily linked or initialized. Some of the superclasses may be initialized at this point, because they may have been initialized during earlier resolutions.</P>
<P>As described in Chapter 7, "The Lifetime of a Class," superclasses must be initialized before subclasses. If the virtual machine is resolving a reference to a class (not an interface), it must make sure that the superclasses have been initialized, starting with <FONT FACE="Courier New">Object</FONT> and proceeding down the inheritance hierarchy to the referenced class. (Note that this is the opposite order in which they were loaded in Step 1.) If a type hasn韙 yet been linked, it must be linked before it is initialized.</P>
<P><EM>Step 2a. Verify the Type</EM></P>
<P>Step 2 begins with the official verification phase of linking, described in Chapter 7, "The Lifetime of a Class." As mentioned in Chapter 7, the process of verification may require that the virtual machine load new types. For example, when verifying a type, the Java Virtual Machine must check all a type韘 superclasses and superinterfaces to make sure they are all binary compatible with the type. If the type being verified has superinterfaces, they may not yet be loaded. During Step 1, the virtual machine makes sure all the type韘 superclasses are loaded, but not its superinterfaces. Thus, verification may require that a type韘 superinterfaces be loaded. At this point, the superinterfaces would be loaded and possibly linked, but definitely not initialized.</P>
<P>In addition, when verifying bytecodes, the Java Virtual Machine may need to load types to ensure the bytecodes are adhering to the semantics of the Java language. For example, if a reference to an instance of a particular class is assigned to a variable with a declared type of a different class, the virtual machine would have to load both types to make sure one is a subclass of the other. As with the superinterfaces described above, these classes would at this point be loaded and possibly linked, but definitely not initialized.</P>
<P>If during the verification process the Java Virtual Machine uncovers trouble, it throws <FONT FACE="Courier New">VerifyError</FONT>.</P>
<P><EM>Step 2b. Prepare the Type</EM></P>
<P>After the official verification phase is complete, the type must be prepared. As described in Chapter 7, "The Lifetime of a Class," during preparation the virtual machine allocates memory for class variables and implementation-dependent data structures such as method tables. If the virtual machine discovers during this step that a class that is not declared abstract contains an abstract method, the virtual machine throws <FONT FACE="Courier New">AbstractMethodError</FONT>.</P>
<P><EM>Optional Step 2c. Resolve the Type</EM></P>
<P>At this point, the type has been loaded, verified and prepared. As described in Chapter 7, "The Lifetime of a Class," a Java Virtual Machine implementation may optionally resolve the type at this point. Keep in mind that at this stage in the resolution process, Steps 1, 2a, and 2b have been performed on a referenced type to resolve a <FONT FACE="Courier New">CONSTANT_Class_info</FONT> entry in the constant pool of a referencing type. Step 2c is the resolution of symbolic references contained in the referenced type, not the referencing type.</P>
<P>For example, if the virtual machine is resolving a symbolic reference from class <FONT FACE="Courier New">Cat</FONT> to class <FONT FACE="Courier New">Mouse</FONT>, the virtual machine performs Steps 1, 2a, and 2b on class <FONT FACE="Courier New">Mouse</FONT>. At this stage of resolving the symbolic reference to <FONT FACE="Courier New">Mouse</FONT> contained in the constant pool of <FONT FACE="Courier New">Cat</FONT>, the virtual machine could optionally (as Step 2c) resolve all the symbolic references contained in the constant pool for <FONT FACE="Courier New">Mouse</FONT>. If <FONT FACE="Courier New">Mouse</FONT>韘 constant pool contains a symbolic reference to class <FONT FACE="Courier New">Cheese</FONT>, for example, the virtual machine could load and optionally link (but not initialize) <FONT FACE="Courier New">Cheese</FONT> at this time. The virtual machine mustn韙 attempt initialize <FONT FACE="Courier New">Cheese</FONT> here because <FONT FACE="Courier New">Cheese</FONT> is not being actively used. (Of course, <FONT FACE="Courier New">Cheese</FONT> may in fact have already been actively used elsewhere, so it have would been already be loaded into this name space, linked, and initialized.)</P>
<P>As mentioned earlier in this chapter, if an implementation does perform Step 2c at this point in the resolution process (early resolution), it must not report any errors until the symbolic references are actually used by the running program. For example, if during the resolution of <FONT FACE="Courier New">Mouse</FONT>韘 constant pool, the virtual machine can韙 find class <FONT FACE="Courier New">Cheese</FONT>, it won韙 throw a <FONT FACE="Courier New">NoClassDefFound</FONT> error until (and unless) <FONT FACE="Courier New">Cheese</FONT> is actually used by the program.</P>
<P><EM>Step 2d. Initialize the Type</EM></P>
<P>At this point, the type has been loaded, verified, prepared and optionally resolved. At long last, the type is ready for initialization. As defined in Chapter 7, "The Lifetime of a Class," initialization consists of two steps. The initialization of the type韘 superclasses in top down order, if the type has any superclasses, and the execution of the type韘 class initialization method, if it has one. Step 2d just consists of executing the class initialization method, if one exists. Because Steps 2a through 2e are performed for all the referenced type韘 superclasses, from the top down, Step 2d will occur for superclasses before it occurs for subclasses.</P>
<P>If the class initialization method completes abruptly by throwing some exception that isn韙 a subclass of <FONT FACE="Courier New">Error</FONT>, the virtual machine throws <FONT FACE="Courier New">ExceptionInInitializerError</FONT> with the thrown exception as a parameter to the constructor. Otherwise, if the thrown exception is already a subclass of <FONT FACE="Courier New">Error</FONT>, that error is thrown. If the virtual machine can韙 create a new <FONT FACE="Courier New">ExceptionInInitializerError</FONT> because there isn韙 enough memory, it throws an <FONT FACE="Courier New">OutOfMemoryError</FONT>.</P>
<P><EM>Step 2e. Check Access Permission</EM></P>
<P>Lastly, after loading, linking, and initialization are complete, the virtual machine checks for access permission. If the referencing type does not have permission to access the referenced type, the virtual machine throws a <FONT FACE="Courier New">IllegalAccessError</FONT>. Step 2e is another activity that is logically part of verification, but that is performed at some other time than the official verification phase of Step 2a. In this case, the check for access permission is delayed to just after initialization. (Actually, the error can be detected at some other time, such as in Step 2a. But regardless of when or how it is detected, an access violation must be reported only after the Steps 1 and 2a through 2d have been successfully completed. As mentioned in Chapter 7, "The Lifetime of a Class," the Java Virtual Machine specification says when errors should be thrown, but doesn韙 dictate exactly when they should be detected.) Once this check is complete, Step 2e--and the entire process of resolving the <FONT FACE="Courier New">CONSTANT_Class_info</FONT> entry--is complete.</P>
<P>If an error occurred in any of Steps 1 through 2e, the resolution of the type fails. But if all went well up until the access permission check of Step 2e, the type is still usable in general, just not usable by the referencing type. If an error occurred before the access permission check, however, the type is unusable and must be marked as such or discarded.</P>
<P>The way a class loader object韘 <FONT FACE="Courier New">loadClass()</FONT> method accomplishes Steps 2a through 2e is by invoking <FONT FACE="Courier New">resolveClass()</FONT>, passing the reference to the <FONT FACE="Courier New">Class</FONT> instance returned by <FONT FACE="Courier New">defineClass()</FONT>. Invoking this method causes all of Steps 2a through 2e to be performed on the type and all its superclasses, starting from the furthest up superclass that hasn韙 yet been linked and initialized and proceeding down the inheritance hierarchy.</P>
<P>Remember that when <FONT FACE="Courier New">defineClass()</FONT> was invoked, the virtual machine brought in the type韘 superclasses by calling <FONT FACE="Courier New">loadClass()</FONT> with the <FONT FACE="Courier New">resolve</FONT> flag set to <FONT FACE="Courier New">false</FONT>. So those superclasses were only loaded. They weren韙 linked or initialized. Only if the superclasses were already linked and initialized before <FONT FACE="Courier New">defineClass()</FONT> was invoked would they be already linked and initialized before <FONT FACE="Courier New">resolveClass()</FONT> is invoked.</P>
<P>Note that the <FONT FACE="Courier New">loadClass()</FONT> method should only invoke <FONT FACE="Courier New">resolveClass()</FONT> on types it imported via calling <FONT FACE="Courier New">defineClass()</FONT>, which loads a type but doesn韙 link or initialize it. (In addition, <FONT FACE="Courier New">loadClass()</FONT> should invoke <FONT FACE="Courier New">resolveClass()</FONT>only if the resolve parameter is <FONT FACE="Courier New">true</FONT>.) As mentioned above, <FONT FACE="Courier New">findSystemClass()</FONT> takes care of linking and initialization as well as loading. You needn韙 invoke <FONT FACE="Courier New">resolveClass()</FONT> on types returned by <FONT FACE="Courier New">findSystemClass()</FONT>.</P>
<H3><P>Resolution of CONSTANT_Fieldref_info Entries</P>
</H3><P>To resolve a constant pool entry of type <FONT FACE="Courier New">CONSTANT_Fieldref_info</FONT>, the virtual machine must first resolve the <FONT FACE="Courier New">CONSTANT_Class_info</FONT> entry specified in the <FONT FACE="Courier New">class_index</FONT> item. Therefore, any error that can be thrown because of the resolution of a <FONT FACE="Courier New">CONSTANT_Class_info</FONT> can be thrown during the resolution of a <FONT FACE="Courier New">CONSTANT_Fieldref_info</FONT>. If resolution of the <FONT FACE="Courier New">CONSTANT_Class_info</FONT> entry succeeds, the virtual machine checks to make sure the field exists and that the current class has permission to access it.</P>
<P>If the virtual machine discovers there is no field with the proper name and type in the referenced class, the virtual machine throws <FONT FACE="Courier New">NoSuchFieldError</FONT>. Otherwise, if the field exists, but the current class doesn韙 have permission to access the field, the virtual machine throws <FONT FACE="Courier New">IllegalAccessError</FONT>.</P>
<P>The virtual machine marks the entry as resolved and places a direct reference to the field in the data for the constant pool entry.</P>
<H3><P>Resolution of CONSTANT_Methodref_info Entries</P>
</H3><P>To resolve a constant pool entry of type <FONT FACE="Courier New">CONSTANT_Methodref_info</FONT>, the virtual machine must first resolve the <FONT FACE="Courier New">CONSTANT_Class_info</FONT> entry specified in the <FONT FACE="Courier New">class_index</FONT> item. Therefore, any error that can be thrown because of the resolution of a <FONT FACE="Courier New">CONSTANT_Class_info</FONT> can be thrown during the resolution of a <FONT FACE="Courier New">CONSTANT_Methodref_info</FONT>. If the resolution of the <FONT FACE="Courier New">CONSTANT_Class_info</FONT> entry succeeds, the virtual machine checks to make sure the method exists and that the current class has permission to access it.</P>
<P>If the virtual machine discovers there is no method with the proper name, return type, and number and types of parameters in the referenced class, the virtual machine throws <FONT FACE="Courier New">NoSuchMethodError</FONT>. Otherwise, if the method exists, but the current class doesn韙 have permission to access the method, the virtual machine throws <FONT FACE="Courier New">IllegalAccessError</FONT>.</P>
<P>The virtual machine marks the entry as resolved and places a direct reference to the method in the data for the constant pool entry.</P>
<H3><P>Resolution of CONSTANT_InterfaceMethodref_info Entries</P>
</H3><P>To resolve a constant pool entry of type <FONT FACE="Courier New">CONSTANT_InterfaceMethodref_info</FONT>, the virtual machine must first resolve the <FONT FACE="Courier New">CONSTANT_Class_info</FONT> entry specified in the <FONT FACE="Courier New">class_index</FONT> item. Therefore, any error that can be thrown because of the resolution of a <FONT FACE="Courier New">CONSTANT_Class_info</FONT> can be thrown during the resolution of a <FONT FACE="Courier New">CONSTANT_InterfaceMethodref_info</FONT>. If the resolution of the <FONT FACE="Courier New">CONSTANT_Class_info</FONT> entry succeeds, the virtual machine checks to make sure the method exists. (The virtual machine need not check to make sure the current class has permission to access the method, because all methods declared in interfaces are implicitly public.)</P>
<P>If the virtual machine discovers there is no method with the proper name, return type, and number and types of parameters in the referenced interface, the virtual machine throws <FONT FACE="Courier New">NoSuchMethodError</FONT>.</P>
<P>The virtual machine marks the entry as resolved and places a direct reference to the method in the data for the constant pool entry.</P>
<H3><P>Resolution of CONSTANT_String_info Entries</P>
</H3><P>To resolve an entry of type <FONT FACE="Courier New">CONSTANT_String_info</FONT>, the virtual machine must place a reference to an <I>interned</I> <FONT FACE="Courier New">String</FONT> object in the data for the constant pool entry being resolved. The <FONT FACE="Courier New">String</FONT> object (an instance of class java.lang.String) must have the character sequence specified by the <FONT FACE="Courier New">CONSTANT_Utf8_info</FONT> entry identified by the <FONT FACE="Courier New">string_index</FONT> item of the <FONT FACE="Courier New">CONSTANT_String_info</FONT>. </P>
<P>Each Java Virtual Machine must maintain an internal list of references to <FONT FACE="Courier New">String</FONT> objects that have been "interned" during the course of running the application. Basically, a <FONT FACE="Courier New">String</FONT> object is said to be interned simply if it appears in the virtual machine韘 internal list of interned <FONT FACE="Courier New">String</FONT> objects. The point of maintaining this list is that any particular sequence of characters is guaranteed to appear in the list no more than once.</P>
<P>To intern a sequence of characters represented by a <FONT FACE="Courier New">CONSTANT_String_info</FONT> entry, the virtual machine checks to see if the sequence of characters is already in the list of interned strings. If so, the virtual machine uses the reference to the existing, previously-interned <FONT FACE="Courier New">String</FONT> object. Otherwise, the virtual machine creates a new <FONT FACE="Courier New">String</FONT> object with the proper character sequence and adds a reference to that <FONT FACE="Courier New">String</FONT> object to the list. To complete the resolution process for a <FONT FACE="Courier New">CONSTANT_String_info</FONT> entry, the virtual machine places the reference to the interned <FONT FACE="Courier New">String</FONT> object in the data of the constant pool entry being resolved.</P>
<P>In your Java programs, you can intern a string by invoking the <FONT FACE="Courier New">intern()</FONT> method of class <FONT FACE="Courier New">String</FONT>. All literal strings are interned via the process of resolving <FONT FACE="Courier New">CONSTANT_String_info</FONT> entries. If a string with the same sequence of Unicode characters has been previously interned, the <FONT FACE="Courier New">intern()</FONT> method returns a reference to the matching already-interned <FONT FACE="Courier New">String</FONT> object. If the <FONT FACE="Courier New">intern()</FONT> method is invoked on a <FONT FACE="Courier New">String</FONT> object that contains a sequence of characters that has not yet been interned, that object itself will be interned. The <FONT FACE="Courier New">intern()</FONT>method will return a reference to the same <FONT FACE="Courier New">String</FONT> object upon which it was invoked .</P>
<P>Here韘 an example:</P>
<P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -