编译期吧。就像你定义String s="str";在编译期"str"就是可识别的常量,就能加进常量池中了。

解决方案 »

  1.   

    什么是常量池?每个类都有自己的常量池。常量池类似于数组,通过索引来访问。常量池放了什么东西?放了方法名、方法描述符、类名、字段名,字段描述符,常量String的utf-8编码形式,常量int,常量float,常量double等如:
    anewarray       #14; //class java/net/URL这条指令表示创建一个常量池中索引为14的项所表示的类的数组,javap指令在反编译的时候将索引为14的项的内容注释了下,表示一个类:java.net.URL又如:invokestatic    #18; //Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
    常量池索引为18的项表示一个方法,是Thread类的currentThread方法,返回值是java.lang.Thread再如:ldc     #22; //String main
    从常量池索引为22的项中取值入栈。索引为22的常量池是什么内容?一个String,字面值为"main"
    诸如此类,想反编译一个类(如Test),使用javap -c Test
    想查看类中常量池的内容,使用:javap -verbose -c Test以下是我的一个类中的常量池的内容:
      Constant pool:
    const #1 = Method       #32.#47;        //  java/lang/Object."<init>":()V
    const #2 = Method       #48.#49;        //  java/lang/Runtime.getRuntime:()Ljava/lang/Runtime;
    const #3 = class        #50;    //  ClassLoaderTest$1
    const #4 = Method       #3.#47; //  ClassLoaderTest$1."<init>":()V
    const #5 = Method       #48.#53;        //  java/lang/Runtime.addShutdownHook (Ljava/lang/Thread;)V
    const #6 = class        #54;    //  java/util/ArrayList
    const #7 = Method       #6.#47; //  java/util/ArrayList."<init>":()V
    const #8 = class        #55;    //  java/io/File
    const #9 = String       #56;    //  E:\helloworld.jar/
    const #10 = Method      #8.#57; //  java/io/File."<init>":(Ljava/lang/String;)V
    const #11 = Method      #8.#58; //  java/io/File.toURL:()Ljava/net/URL;
    const #12 = Method      #6.#59; //  java/util/ArrayList.add:(Ljava/lang/Object;)Z
    const #13 = class       #60;    //  java/net/URLClassLoader
    const #14 = class       #61;    //  java/net/URL
    const #15 = Method      #6.#62; //  java/util/ArrayList.toArray:([Ljava/lang/Object;)[Ljava/lang/Object;
    const #16 = class       #63;    //  "[Ljava/net/URL;"
    const #17 = Method      #13.#64;        //  java/net/URLClassLoader."<init>":([Ljava/net/URL;)V
    const #18 = Method      #65.#66;        //  java/lang/Thread.currentThread:()Ljava/lang/Thread;
    const #19 = Method      #65.#67;        //  java/lang/Thread.setContextClassLoader:(Ljava/lang/ClassLoade
    const #20 = String      #68;    //  test.Hello
    const #21 = Method      #23.#69;        //  java/lang/Class.forName:(Ljava/lang/String;ZLjava/lang/ClassL
    const #22 = String      #41;    //  main
    const #23 = class       #70;    //  java/lang/Class
    const #24 = class       #71;    //  java/lang/String
    const #25 = Method      #72.#73;        //  java/lang/reflect/Array.newInstance:(Ljava/lang/Class;I)Ljava
    const #26 = Method      #32.#74;        //  java/lang/Object.getClass:()Ljava/lang/Class;
    const #27 = Method      #23.#75;        //  java/lang/Class.getMethod:(Ljava/lang/String;[Ljava/lang/Clas
    const #28 = Method      #76.#77;        //  java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
    const #29 = InterfaceMethod     #78.#79;        //  java/util/List.subList:(II)Ljava/util/List;
    const #30 = InterfaceMethod     #78.#62;        //  java/util/List.toArray:([Ljava/lang/Object;)[Ljava/la
    const #31 = class       #80;    //  "[Ljava/lang/String;"
    const #32 = class       #81;    //  java/lang/Object
    const #33 = Method      #82.#83;        //  java/lang/reflect/Method.invoke:(Ljava/lang/Object;[Ljava/lan
    const #34 = class       #84;    //  java/lang/reflect/InvocationTargetException
    const #35 = Method      #34.#85;        //  java/lang/reflect/InvocationTargetException.getTargetExceptio
    const #36 = class       #86;    //  ClassLoaderTest
    const #37 = Asciz       <init>;
    const #38 = Asciz       ()V;
    const #39 = Asciz       Code;
    const #40 = Asciz       LineNumberTable;
    const #41 = Asciz       main;
    const #42 = Asciz       ([Ljava/lang/String;)V;
    const #43 = Asciz       Exceptions;
    const #44 = class       #87;    //  java/lang/Throwable
    const #45 = Asciz       SourceFile;
    const #46 = Asciz       ClassLoaderTest.java;
    const #47 = NameAndType #37:#38;//  "<init>":()V
    const #48 = class       #88;    //  java/lang/Runtime
    const #49 = NameAndType #89:#90;//  getRuntime:()Ljava/lang/Runtime;
    const #50 = Asciz       ClassLoaderTest$1;
    const #51 = Asciz       ;
    const #52 = Asciz       InnerClasses;
    const #53 = NameAndType #91:#92;//  addShutdownHook:(Ljava/lang/Thread;)V
    const #54 = Asciz       java/util/ArrayList;
    const #55 = Asciz       java/io/File;
    const #56 = Asciz       E:\helloworld.jar/;
    const #57 = NameAndType #37:#93;//  "<init>":(Ljava/lang/String;)V
    const #58 = NameAndType #94:#95;//  toURL:()Ljava/net/URL;
    const #59 = NameAndType #96:#97;//  add:(Ljava/lang/Object;)Z
    const #60 = Asciz       java/net/URLClassLoader;
    const #61 = Asciz       java/net/URL;
    const #62 = NameAndType #98:#99;//  toArray:([Ljava/lang/Object;)[Ljava/lang/Object;
    const #63 = Asciz       [Ljava/net/URL;;
    const #64 = NameAndType #37:#100;//  "<init>":([Ljava/net/URL;)V
    const #65 = class       #101;   //  java/lang/Thread
    const #66 = NameAndType #102:#103;//  currentThread:()Ljava/lang/Thread;
    const #67 = NameAndType #104:#105;//  setContextClassLoader:(Ljava/lang/ClassLoader;)V
    const #68 = Asciz       test.Hello;
    const #69 = NameAndType #106:#107;//  forName:(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Clas
    const #70 = Asciz       java/lang/Class;
    const #71 = Asciz       java/lang/String;
    const #72 = class       #108;   //  java/lang/reflect/Array
    const #73 = NameAndType #109:#110;//  newInstance:(Ljava/lang/Class;I)Ljava/lang/Object;
    const #74 = NameAndType #111:#112;//  getClass:()Ljava/lang/Class;
    const #75 = NameAndType #113:#114;//  getMethod:(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/
    const #76 = class       #115;   //  java/util/Arrays
    const #77 = NameAndType #116:#117;//  asList:([Ljava/lang/Object;)Ljava/util/List;
    const #78 = class       #118;   //  java/util/List
    const #79 = NameAndType #119:#120;//  subList:(II)Ljava/util/List;
    const #80 = Asciz       [Ljava/lang/String;;
    const #81 = Asciz       java/lang/Object;
    const #82 = class       #121;   //  java/lang/reflect/Method
    const #83 = NameAndType #122:#123;//  invoke:(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
    const #84 = Asciz       java/lang/reflect/InvocationTargetException;
    const #85 = NameAndType #124:#125;//  getTargetException:()Ljava/lang/Throwable;
    const #86 = Asciz       ClassLoaderTest;
    const #87 = Asciz       java/lang/Throwable;
    const #88 = Asciz       java/lang/Runtime;
    const #89 = Asciz       getRuntime;
    const #90 = Asciz       ()Ljava/lang/Runtime;;
    const #91 = Asciz       addShutdownHook;
    const #92 = Asciz       (Ljava/lang/Thread;)V;
    const #93 = Asciz       (Ljava/lang/String;)V;
    const #94 = Asciz       toURL;
    const #95 = Asciz       ()Ljava/net/URL;;
    const #96 = Asciz       add;
    const #97 = Asciz       (Ljava/lang/Object;)Z;
    const #98 = Asciz       toArray;
    const #99 = Asciz       ([Ljava/lang/Object;)[Ljava/lang/Object;;
    const #100 = Asciz      ([Ljava/net/URL;)V;
    const #101 = Asciz      java/lang/Thread;
    const #102 = Asciz      currentThread;
    const #103 = Asciz      ()Ljava/lang/Thread;;
    const #104 = Asciz      setContextClassLoader;
    const #105 = Asciz      (Ljava/lang/ClassLoader;)V;
    const #106 = Asciz      forName;
    const #107 = Asciz      (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;;
    const #108 = Asciz      java/lang/reflect/Array;
    const #109 = Asciz      newInstance;
    const #110 = Asciz      (Ljava/lang/Class;I)Ljava/lang/Object;;
    const #111 = Asciz      getClass;
    const #112 = Asciz      ()Ljava/lang/Class;;
    const #113 = Asciz      getMethod;
    const #114 = Asciz      (Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;;
    const #115 = Asciz      java/util/Arrays;
    const #116 = Asciz      asList;
    const #117 = Asciz      ([Ljava/lang/Object;)Ljava/util/List;;
    const #118 = Asciz      java/util/List;
    const #119 = Asciz      subList;
    const #120 = Asciz      (II)Ljava/util/List;;
    const #121 = Asciz      java/lang/reflect/Method;
    const #122 = Asciz      invoke;
    const #123 = Asciz      (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;;
    const #124 = Asciz      getTargetException;
    const #125 = Asciz      ()Ljava/lang/Throwable;;javap给它的注释很明了了

    const #1 = Method       #32.#47;        //  java/lang/Object."<init>":()V
    常量池索引为1的项,表示的是一个方法,具体的方法是Object的<init>
      

  2.   

    常量池中放入的诸如方法信息、字段信息,类等信息是符号引用,在运行的时候,jvm需要将这些符号引用替换成直接引用,如表示字段的常量池项可能是一个本地指针,指向方法区类元数据中的字段,再如表示方法的项,可能是指向方法表的一个指针还有一些常量池存储的并不是符号引用,如CONSTANT_DOUBLE_INFO,存的就是double值本身,在jvm装载类的解析过程中并不需要对这样的常量池项做什么操作。
      

  3.   

    解析常量池项有个特殊的东西就是CONSTANT_String_info类型的项jvm实例中维护了一张表,就叫它 intern 列表 吧,专门用来存储具有某种特征的字符串的在解析CONSTANT_String_info时,如果在intern 列表没有发现CONSTANT_String_info所表示的字符串对象,就创建一个,并把它的引用加入intern 列表中,同时将CONSTANT_String_info也指向这个对象;如果intern 列表中已经存在CONSTANT_String_info所表示的String对象,就直接将CONSTANT_String_info指向这个对象另外,调用String的intern()方法,若在intern 列表中没有该String对象所表示的字符序列,也就将一个对象加入这个intern 列表,但是加入的是新创建一个相同的字符串对象还是将该字符换本身加进去,不同的jvm做法不同,见:http://www.iteye.com/topic/1112592