聊聊java String的intern

栏目: 服务器 · 发布时间: 5年前

内容简介:聊聊java String的intern本文主要研究一下java String的internjava.base/java/lang/String.java

聊聊java String的intern

本文主要研究一下java String的intern

String.intern()

java.base/java/lang/String.java

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence,
               Constable, ConstantDesc {

    //......

    /**
     * Returns a canonical representation for the string object.
     * <p>
     * A pool of strings, initially empty, is maintained privately by the
     * class {@code String}.
     * <p>
     * When the intern method is invoked, if the pool already contains a
     * string equal to this {@code String} object as determined by
     * the {@link #equals(Object)} method, then the string from the pool is
     * returned. Otherwise, this {@code String} object is added to the
     * pool and a reference to this {@code String} object is returned.
     * <p>
     * It follows that for any two strings {@code s} and {@code t},
     * {@code s.intern() == t.intern()} is {@code true}
     * if and only if {@code s.equals(t)} is {@code true}.
     * <p>
     * All literal strings and string-valued constant expressions are
     * interned. String literals are defined in section 3.10.5 of the
     * <cite>The Java™ Language Specification</cite>.
     *
     * @return  a string that has the same contents as this string, but is
     *          guaranteed to be from a pool of unique strings.
     * @jls 3.10.5 String Literals
     */
    public native String intern();

    //......           

}
即intern方法返回指向heap中的此String对象引用

实例

基于jdk12

StringExistInPoolBeforeIntern

public class StringExistInPoolBeforeIntern {

    public static void main(String[] args){
        String stringObject = new String("tomcat");
        //NOTE 在intern之前,string table已经有了tomcat,因而intern返回tomcat,不会指向stringObject
        stringObject.intern();
        String stringLiteral = "tomcat";
        System.out.println(stringObject == stringLiteral); //false
    }
}
  • tomcat这个literal string是interned过的,常量池没有tomcat,因而添加到常量池,常量池有个tomcat;另外由于stringObject是new的,所以heap中也有一个tomcat,而此时它指向heap中的tomcat
  • stringObject.intern()返回的是heap中常量池的tomcat;stringLiteral是tomcat这个literal string,由于常量池已经有该值,因而stringLiteral指向的是heap中常量池的tomcat
  • 此时stringObject指向的是heap中的tomcat,而stringLiteral是heap中常量池的tomcat,因而二者不等,返回false

StringNotExistInPoolBeforeIntern

public class StringNotExistInPoolBeforeIntern {

    public static void main(String[] args){
        String stringObject = new String("tom") + new String("cat");
        //NOTE 在intern之前,string table没有tomcat,因而intern指向stringObject
        stringObject.intern();
        String stringLiteral = "tomcat";
        System.out.println(stringObject == stringLiteral); //true
    }
}
  • tom及cat这两个literal string是interned过的,常量池没有tom及cat,因而添加到常量池,常量池有tom、cat;另外由于stringObject是new出来的,是tom及cat二者concat,因而heap中有一个tomcat
  • stringObject的intern方法执行的时候,由于常量池中没有tomcat,因而添加到常量池,intern()返回的是指向heap中的tomcat的引用;stringLiteral是tomcat这个literal string,由于stringObject.intern()已经将tomcat添加到常量池了并指向heap中的tomcat的引用,所以stringLiteral返回的是指向heap中的tomcat的引用
  • 由于stringLiteral返回的是指向heap中的tomcat的引用,其实就是stringObject,因而二者相等,返回true

javap

基于jdk12

StringExistInPoolBeforeIntern

javac src/main/java/com/example/javac/StringExistInPoolBeforeIntern.java
javap -v src/main/java/com/example/javac/StringExistInPoolBeforeIntern.class

  Last modified 2019年4月6日; size 683 bytes
  MD5 checksum 207635ffd7560f1df24b98607e2ca7db
  Compiled from "StringExistInPoolBeforeIntern.java"
public class com.example.javac.StringExistInPoolBeforeIntern
  minor version: 0
  major version: 56
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #8                          // com/example/javac/StringExistInPoolBeforeIntern
  super_class: #9                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #9.#21         // java/lang/Object."<init>":()V
   #2 = Class              #22            // java/lang/String
   #3 = String             #23            // tomcat
   #4 = Methodref          #2.#24         // java/lang/String."<init>":(Ljava/lang/String;)V
   #5 = Methodref          #2.#25         // java/lang/String.intern:()Ljava/lang/String;
   #6 = Fieldref           #26.#27        // java/lang/System.out:Ljava/io/PrintStream;
   #7 = Methodref          #18.#28        // java/io/PrintStream.println:(Z)V
   #8 = Class              #29            // com/example/javac/StringExistInPoolBeforeIntern
   #9 = Class              #30            // java/lang/Object
  #10 = Utf8               <init>
  #11 = Utf8               ()V
  #12 = Utf8               Code
  #13 = Utf8               LineNumberTable
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Utf8               StackMapTable
  #17 = Class              #31            // "[Ljava/lang/String;"
  #18 = Class              #32            // java/io/PrintStream
  #19 = Utf8               SourceFile
  #20 = Utf8               StringExistInPoolBeforeIntern.java
  #21 = NameAndType        #10:#11        // "<init>":()V
  #22 = Utf8               java/lang/String
  #23 = Utf8               tomcat
  #24 = NameAndType        #10:#33        // "<init>":(Ljava/lang/String;)V
  #25 = NameAndType        #34:#35        // intern:()Ljava/lang/String;
  #26 = Class              #36            // java/lang/System
  #27 = NameAndType        #37:#38        // out:Ljava/io/PrintStream;
  #28 = NameAndType        #39:#40        // println:(Z)V
  #29 = Utf8               com/example/javac/StringExistInPoolBeforeIntern
  #30 = Utf8               java/lang/Object
  #31 = Utf8               [Ljava/lang/String;
  #32 = Utf8               java/io/PrintStream
  #33 = Utf8               (Ljava/lang/String;)V
  #34 = Utf8               intern
  #35 = Utf8               ()Ljava/lang/String;
  #36 = Utf8               java/lang/System
  #37 = Utf8               out
  #38 = Utf8               Ljava/io/PrintStream;
  #39 = Utf8               println
  #40 = Utf8               (Z)V
{
  public com.example.javac.StringExistInPoolBeforeIntern();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 8: 0

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=3, args_size=1
         0: new           #2                  // class java/lang/String
         3: dup
         4: ldc           #3                  // String tomcat
         6: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
         9: astore_1
        10: aload_1
        11: invokevirtual #5                  // Method java/lang/String.intern:()Ljava/lang/String;
        14: pop
        15: ldc           #3                  // String tomcat
        17: astore_2
        18: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
        21: aload_1
        22: aload_2
        23: if_acmpne     30
        26: iconst_1
        27: goto          31
        30: iconst_0
        31: invokevirtual #7                  // Method java/io/PrintStream.println:(Z)V
        34: return
      LineNumberTable:
        line 11: 0
        line 13: 10
        line 14: 15
        line 15: 18
        line 16: 34
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 30
          locals = [ class "[Ljava/lang/String;", class java/lang/String, class java/lang/String ]
          stack = [ class java/io/PrintStream ]
        frame_type = 255 /* full_frame */
          offset_delta = 0
          locals = [ class "[Ljava/lang/String;", class java/lang/String, class java/lang/String ]
          stack = [ class java/io/PrintStream, int ]
}
SourceFile: "StringExistInPoolBeforeIntern.java"
  • 可以看到常量池有个tomcat

StringNotExistInPoolBeforeIntern

javac src/main/java/com/example/javac/StringNotExistInPoolBeforeIntern.java
javap -v src/main/java/com/example/javac/StringNotExistInPoolBeforeIntern.class

  Last modified 2019年4月6日; size 1187 bytes
  MD5 checksum 6d173f303b61b8f5826e54bb6ed5157c
  Compiled from "StringNotExistInPoolBeforeIntern.java"
public class com.example.javac.StringNotExistInPoolBeforeIntern
  minor version: 0
  major version: 56
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #11                         // com/example/javac/StringNotExistInPoolBeforeIntern
  super_class: #12                        // java/lang/Object
  interfaces: 0, fields: 0, methods: 2, attributes: 3
Constant pool:
   #1 = Methodref          #12.#24        // java/lang/Object."<init>":()V
   #2 = Class              #25            // java/lang/String
   #3 = String             #26            // tom
   #4 = Methodref          #2.#27         // java/lang/String."<init>":(Ljava/lang/String;)V
   #5 = String             #28            // cat
   #6 = InvokeDynamic      #0:#32         // #0:makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
   #7 = Methodref          #2.#33         // java/lang/String.intern:()Ljava/lang/String;
   #8 = String             #34            // tomcat
   #9 = Fieldref           #35.#36        // java/lang/System.out:Ljava/io/PrintStream;
  #10 = Methodref          #21.#37        // java/io/PrintStream.println:(Z)V
  #11 = Class              #38            // com/example/javac/StringNotExistInPoolBeforeIntern
  #12 = Class              #39            // java/lang/Object
  #13 = Utf8               <init>
  #14 = Utf8               ()V
  #15 = Utf8               Code
  #16 = Utf8               LineNumberTable
  #17 = Utf8               main
  #18 = Utf8               ([Ljava/lang/String;)V
  #19 = Utf8               StackMapTable
  #20 = Class              #40            // "[Ljava/lang/String;"
  #21 = Class              #41            // java/io/PrintStream
  #22 = Utf8               SourceFile
  #23 = Utf8               StringNotExistInPoolBeforeIntern.java
  #24 = NameAndType        #13:#14        // "<init>":()V
  #25 = Utf8               java/lang/String
  #26 = Utf8               tom
  #27 = NameAndType        #13:#42        // "<init>":(Ljava/lang/String;)V
  #28 = Utf8               cat
  #29 = Utf8               BootstrapMethods
  #30 = MethodHandle       6:#43          // REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
  #31 = String             #44            // \u0001\u0001
  #32 = NameAndType        #45:#46        // makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
  #33 = NameAndType        #47:#48        // intern:()Ljava/lang/String;
  #34 = Utf8               tomcat
  #35 = Class              #49            // java/lang/System
  #36 = NameAndType        #50:#51        // out:Ljava/io/PrintStream;
  #37 = NameAndType        #52:#53        // println:(Z)V
  #38 = Utf8               com/example/javac/StringNotExistInPoolBeforeIntern
  #39 = Utf8               java/lang/Object
  #40 = Utf8               [Ljava/lang/String;
  #41 = Utf8               java/io/PrintStream
  #42 = Utf8               (Ljava/lang/String;)V
  #43 = Methodref          #54.#55        // java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
  #44 = Utf8               \u0001\u0001
  #45 = Utf8               makeConcatWithConstants
  #46 = Utf8               (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
  #47 = Utf8               intern
  #48 = Utf8               ()Ljava/lang/String;
  #49 = Utf8               java/lang/System
  #50 = Utf8               out
  #51 = Utf8               Ljava/io/PrintStream;
  #52 = Utf8               println
  #53 = Utf8               (Z)V
  #54 = Class              #56            // java/lang/invoke/StringConcatFactory
  #55 = NameAndType        #45:#60        // makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
  #56 = Utf8               java/lang/invoke/StringConcatFactory
  #57 = Class              #62            // java/lang/invoke/MethodHandles$Lookup
  #58 = Utf8               Lookup
  #59 = Utf8               InnerClasses
  #60 = Utf8               (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
  #61 = Class              #63            // java/lang/invoke/MethodHandles
  #62 = Utf8               java/lang/invoke/MethodHandles$Lookup
  #63 = Utf8               java/lang/invoke/MethodHandles
{
  public com.example.javac.StringNotExistInPoolBeforeIntern();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 8: 0

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=4, locals=3, args_size=1
         0: new           #2                  // class java/lang/String
         3: dup
         4: ldc           #3                  // String tom
         6: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
         9: new           #2                  // class java/lang/String
        12: dup
        13: ldc           #5                  // String cat
        15: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V
        18: invokedynamic #6,  0              // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
        23: astore_1
        24: aload_1
        25: invokevirtual #7                  // Method java/lang/String.intern:()Ljava/lang/String;
        28: pop
        29: ldc           #8                  // String tomcat
        31: astore_2
        32: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
        35: aload_1
        36: aload_2
        37: if_acmpne     44
        40: iconst_1
        41: goto          45
        44: iconst_0
        45: invokevirtual #10                 // Method java/io/PrintStream.println:(Z)V
        48: return
      LineNumberTable:
        line 11: 0
        line 13: 24
        line 14: 29
        line 15: 32
        line 16: 48
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 44
          locals = [ class "[Ljava/lang/String;", class java/lang/String, class java/lang/String ]
          stack = [ class java/io/PrintStream ]
        frame_type = 255 /* full_frame */
          offset_delta = 0
          locals = [ class "[Ljava/lang/String;", class java/lang/String, class java/lang/String ]
          stack = [ class java/io/PrintStream, int ]
}
SourceFile: "StringNotExistInPoolBeforeIntern.java"
InnerClasses:
  public static final #58= #57 of #61;    // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
  0: #30 REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
    Method arguments:
      #31 \u0001\u0001
  • 可以看到常量池有tom、cat、tomcat

小结

即intern方法返回指向heap中的此String对象引用

doc


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Sovereign Individual

The Sovereign Individual

James Dale Davidson、William Rees-Mogg / Free Press / 1999-08-26 / USD 16.00

Two renowned investment advisors and authors of the bestseller The Great Reckoning bring to light both currents of disaster and the potential for prosperity and renewal in the face of radical changes ......一起来看看 《The Sovereign Individual》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具