精华内容
下载资源
问答
  • 首先,比较有名的常量池有两个,分别是运行时常量池和静态常量池,但是目前可以被称为常量池的有三个:字符串常量池、运行时常量池、静态常量池。 这三个常量池的变动的关键时刻是在JDK1.7的时候: (1)...

    在 JAVA 语言中有8中基本类型和一种比较特殊的类型String。这些类型为了使他们在运行过程中速度更快,更节省内存,都提供了一种常量池的概念。常量池就类似一个JAVA系统级别提供的缓存。首先,比较有名的常量池有两个,分别是运行时常量池和静态常量池,但是目前可以被称为常量池的有三个:字符串常量池、运行时常量池、静态常量池。

    这三个常量池的变动的关键时刻是在JDK1.7的时候:

     

    (1) 在JDK1.7之前:运行时常量池逻辑包含字符串常量池存放在方法区,所以此时常量池只分为运行时常量池和静态常量池。

     

    (2)在JDK1.7时: 字符串常量池被从方法区拿到了堆中,只是字符串常量池被单独拿到堆, 而运行时常量池剩下的东西还在方法区。至于为什么移到堆内,可能是由于方法区的内存空间太小。

     

    (3)在JDK1.8时: hotspot移除了永久代改用元空间 这时字符串常量池依然在堆中,运行时常量池依然在方法区, 只不过方法区的实现从永久代变成了元空间

     

    也就是说从JDK1.7开始运行时常量池和静态常量池之外又多了一个字符串常量池,它被放在堆中。

     

    一、字符串常量池(String Constant Pool)

     

    在HotSpot VM里实现的string pool功能的是一个StringTable类,它是一个Hash表,里面存的是驻留字符串(也就是用双引号括起来的)的引用(而不是驻留字符串实例本身),也就是说在堆中的某些字符串实例被这个StringTable引用之后就等同被赋予了”驻留字符串”的身份。这个StringTable在每个HotSpot VM的实例只有一份,被所有的类共享。

    在JDK1.6中,StringTable的长度是固定的,长度就是1009,字符串常量由一个一个字符组成,放在了StringTable上。因此如果放入String Pool中的String非常多,就会造成hash冲突,导致链表过长,当调用String#intern()时会需要到链表上一个一个找,会导致性能大幅度下降。

    所以在JDK1.7中,对String#intern()进行了改变,因此String Pool中也可以存放放于堆内的字符串对象的引用。同时StringTable的长度可以通过参数指定:-XX:StringTableSize。

     

    二、class常量池(Class Constant Pool)

     

    当一个Java类被编译后,就会形成一份class文件,即类被编译后的数据,该文件中除了包含类的版本、字段、方法、接口等类的描述信息外,还有一项信息就是常量池。

    在Class文件结构中,最头的4个字节用于存储魔数Magic Number(用于确定一个文件是否能被JVM接受),再接着4个字节用于存储版本号(前2个字节存储次版本号,后2个存储主版本号),再接着是用于存放常量的常量池,由于常量的数量是不固定的,所以常量池的入口放置一个U2类型的数据(constant_pool_count)来存储常量池容量计数值。每个class文件都有一个class常量池用于存放编译器生成的各种字面量和符号引用:

    字面量包括:字面量相当于Java语言层面常量的概念,1.文本字符串 2.八种基本类型的值 3.被声明为final的常量

    符号引用包括:符号引用则属于编译方面的概念,包括了如下三种类型的常量,1.类和方法的全限定名 2.字段的名称和描述符 3.方法的名称和描述符。

    常量池的每一项常量都是一个表,一共有如下表所示的11种各不相同的表结构数据,这每个表开始的第一位都是一个字节的标志位(取值1-12),代表当前这个常量属于哪种常量类型。 

     

    三、运行时常量池(Runtime Constant Pool)

     

    当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中,这时运行时常量池存在于内存中作为class常量池被加载到内存之后的版本,也就是说运行时常量池也是每个类都有一个,class常量池中存的并不是对象的实例,而是对象的符号引用值,在类的加载过程中会有解析过程,在解析阶段,会把符号引用替换为直接引用,解析的过程会去查询字符串常量池,以保证运行时常量池所引用的字符串与字符串常量池中是一致的。

    在class文件常量池的符号引用会在不同的时候被转变为直接引用,比如说类的静态方法或私有方法,实例构造方法,父类方法,这是因为这些方法不能被重写其他版本,所以能在加载的时候就可以将符号引用转变为直接引用,而其他的一些方法会在这个方法被第一次调用的时候才将符号引用转变为直接引用。

    与class常量池的不同之处除了符号引用会被解析为直接引用,还有关键一点在于运行时常量池相对于CLass文件常量池是具备动态性,并不是常量一定只有编译期才能产生,并非只有预置在Class文件常量池的内容才能进入运行时常量池,运行期间也可能将新的常量放入池中,可以通过String#intern()动态的添加字面量。

     

     

    1.全局常量池在每个VM中只有一份,存放的是字符串常量的引用值。

    2.class常量池是在编译的时候每个class都有的,在编译阶段,存放的是常量的符号引用。

    3.运行时常量池是在类加载完成之后,将每个class常量池中的符号引用值转存到运行时常量池中,也就是说,每个class都有一个运行时常量池,类在解析之后,将符号引用替换成直接引用,与全局常量池中的引用值保持一致。

     

    关于对字符串常量的使用和使用字符串常量时和常量池之间的关系,请看JVM的常量池:String.intern()的理解以及字符串常量池解析

     

    展开全文
  • 写在前面:博主是一位普普通通的19届二本大学生,平时最大的爱好就是听听歌,逛逛B站。博主很喜欢的一句话花开堪折直须折,莫待无花空折枝:博主的理解是头一次为人,就应该做自己想做的...常量池与Class常量池 2.运.

    写在前面:博主是一位普普通通的19届双非软工在读生,平时最大的爱好就是听听歌,逛逛B站。博主很喜欢的一句话花开堪折直须折,莫待无花空折枝:博主的理解是头一次为人,就应该做自己想做的事,做自己不后悔的事,做自己以后不会留有遗憾的事,做自己觉得有意义的事,不浪费这大好的青春年华。博主写博客目的是记录所学到的知识并方便自己复习,在记录知识的同时获得部分浏览量,得到更多人的认可,满足小小的成就感,同时在写博客的途中结交更多志同道合的朋友,让自己在技术的路上并不孤单。>本篇博客由于比较深入的写进JVM底层,所以如果有错误希望可以指出咱们共同讨论

    痛苦对我们来说,究竟意味着什么?司马迁在《报任安书》中一语道破,文王拘而演《周易》,仲尼厄而作《春秋》,屈原放逐乃赋《离骚》,左丘失明厥有《国语》。

    目录:
    1.常量池与Class常量池
    2.运行时常量池
           
    运行时常量池的简介
           
    方法区的Class文件信息,Class常量池和运行时常量池的三者关系
    3.字符串常量池
           
    字符串常量池的简介
           
    采用字面值的方式创建字符串对象
           
    采用new关键字新建一个字符串对象
           
    字符串池的优缺点
    4.字符串常量池和运行时常量池之间的藕断丝连
           
    常量池和字符串常量池的版本变化
           
    String.intern在JDK6和JDK7之后的区别(重难点)
           
    字符串常量池里存放的是引用还是字面量

    在这里插入图片描述

    1.常量池

    常量池,也叫 Class 常量池(常量池==Class常量池)。Java文件被编译成 Class文件,Class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项就是常量池,常量池是当Class文件被Java虚拟机加载进来后存放在方法区 各种字面量 (Literal)和 符号引用

    在Class文件结构中,最头的4个字节用于 存储魔数 (Magic Number),用于确定一个文件是否能被JVM接受,再接着4个字节用于 存储版本号,前2个字节存储次版本号,后2个存储主版本号,再接着是用于存放常量的常量池常量池主要用于存放两大类常量:字面量和符号引用量,字面量相当于Java语言层面常量的概念,如文本字符串,声明为final的常量值等,符号引用则属于编译原理方面的概念。如下

    在这里插入图片描述

    在这里插入图片描述

    2.运行时常量池

    2.1运行时常量池的简介

    运行时常量池是方法区的一部分。运行时常量池是当Class文件被加载到内存后,Java虚拟机会 将Class文件常量池里的内容转移到运行时常量池里(运行时常量池也是每个类都有一个)。运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性,Java语言并不要求常量一定只有编译期才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中

    2.2方法区的Class文件信息,Class常量池和运行时常量池的三者关系

    在这里插入图片描述

    字符串常量池

    3.1字符串常量池的简介

    字符串常量池又称为:字符串池,全局字符串池,英文也叫String Pool。 在工作中,String类是我们使用频率非常高的一种对象类型。JVM为了提升性能和减少内存开销,避免字符串的重复创建,其维护了一块特殊的内存空间,这就是我们今天要讨论的核心:字符串常量池。字符串常量池由String类私有的维护

    我们理清几个概念:

    在JDK7之前字符串常量池是在永久代里边的,但是在JDK7之后,把字符串常量池分进了堆里边。看下面两张图:

    在这里插入图片描述

    在堆中的字符串常量池: **堆里边的字符串常量池存放的是字符串的引用或者字符串(两者都有)**下面例子会有具体的讲解

    在这里插入图片描述

    符号引用表会在下面讲

    我们知道,在Java中有两种创建字符串对象的方式:

    1. 采用字面值的方式赋值
    2. 采用new关键字新建一个字符串对象。这两种方式在性能和内存占用方面存在着差别。

    3.2采用字面值的方式创建字符串对象

    package Oneday;
    public class a {
        public static void main(String[] args) {
            String str1="aaa";
            String str2="aaa";
            System.out.println(str1==str2);   
        }
    }
    运行结果:
    true
    

    采用字面值的方式创建一个字符串时,JVM首先会去字符串池中查找是否存在"aaa"这个对象,如果不存在,则在字符串池中创建"aaa"这个对象,然后将池中"aaa"这个对象的引用地址返回给字符串常量str,这样str会指向池中"aaa"这个字符串对象;如果存在,则不创建任何对象,直接将池中"aaa"这个对象的地址返回,赋给字符串常量。

    对于上述的例子:这是因为,创建字符串对象str2时,字符串池中已经存在"aaa"这个对象,直接把对象"aaa"的引用地址返回给str2,这样str2指向了池中"aaa"这个对象,也就是说str1和str2指向了同一个对象,因此语句System.out.println(str1== str2)输出:true

    3.3采用new关键字新建一个字符串对象

    package Oneday;
    public class a {
        public static void main(String[] args) {
            String str1=new String("aaa");
            String str2=new String("aaa");
            System.out.println(str1==str2);
        }
    }
    运行结果:
    false
    

    采用new关键字新建一个字符串对象时,JVM首先在字符串常量池中查找有没有"aaa"这个字符串对象,如果有,则不在池中再去创建"aaa"这个对象了,直接在堆中创建一个"aaa"字符串对象,然后将堆中的这个"aaa"对象的地址返回赋给引用str1,这样,str1就指向了堆中创建的这个"aaa"字符串对象;如果没有,则首先在字符串常量池池中创建一个"aaa"字符串对象,然后再在堆中创建一个"aaa"字符串对象,然后将堆中这个"aaa"字符串对象的地址返回赋给str1引用,这样,str1指向了堆中创建的这个"aaa"字符串对象。

    对于上述的例子:
    因为,采用new关键字创建对象时,每次new出来的都是一个新的对象,也即是说引用str1和str2指向的是两个不同的对象,因此语句
    System.out.println(str1 == str2)输出:false

    字符串池的实现有一个前提条件:String对象是不可变的。因为这样可以保证多个引用可以同时指向字符串池中的同一个对象。如果字符串是可变的,那么一个引用操作改变了对象的值,对其他引用会有影响,这样显然是不合理的。

    3.4字符串池的优缺点

    字符串池的优点就是避免了相同内容的字符串的创建,节省了内存,省去了创建相同字符串的时间,同时提升了性能;另一方面,字符串池的缺点就是牺牲了JVM在常量池中遍历对象所需要的时间,不过其时间成本相比而言比较低。

    4字符串常量池和运行时常量池之间的藕断丝连

    博主为啥要把他俩放在一起讲呢,主要是随着JDK的改朝换代,字符串常量池有很大的变动,和运行时常量池有关。而且网上众说纷纭,我真的在看的时候ctm了,所以博主花很长时间把这一块讲明白,如果有错误或者异议可以通知博主。博主一定会在第一时间参与讨论

    在这里插入图片描述

    4.1常量池和字符串常量池的版本变化

    • 在JDK1.7之前运行时常量池逻辑包含字符串常量池存放在方法区, 此时hotspot虚拟机对方法区的实现为永久代
    • 在JDK1.7 字符串常量池被从方法区拿到了堆中, 这里没有提到运行时常量池,也就是说 字符串常量池被单独拿到堆,运行时常量池剩下的东西还在方法区, 也就是hotspot中的永久代
    • 在JDK1.8 hotspot移除了永久代用元空间(Metaspace)取而代之, 这时候字符串常量池还在堆, 运行时常量池还在方法区, 只不过方法区的实现从永久代变成了元空间(Metaspace)

    4.2String.intern在JDK6和JDK7之后的区别(重点)

    JDK6和JDK7中该方法的功能是一致的,不同的是常量池位置的改变(JDK7将常量池放在了堆空间中),下面会具体说明。intern的方法返回字符串对象的规范表示形式。其中它做的事情是:首先去判断该字符串是否在常量池中存在,如果存在返回常量池中的字符串,如果在字符串常量池中不存在,先在字符串常量池中添加该字符串,然后返回引用地址

    例子1:

    String s1 = new String("1");
    s1.intern();
    String s2 = "1";
    System.out.println(s1 == s2);
    
    运行结果:
    JDK6运行结果:false
    JDK7运行结果:false
    

    我们首先看一张图:

    在这里插入图片描述上边例子中s1是new出来对象存放的位置的引用,s2是存放在字符串常量池的字符串的引用,所以两者不同

    例子2:

    String s1 = new String("1");
    System.out.println(s1.intern() == s1);
    
    运行结果:
    JDK6运行结果:false
    JDK7运行结果:false
    

    上边例子中s1是new出来对象存放的位置的引用,s1.intern()返回的是字符串常量池里字符串的引用

    例子3:

    String s1 = new String("1") + new String("1");
    s1.intern();
    String s2 = "11";
    System.out.println(s1 == s2);
    
    运行结果:
    JDK6运行结果:false
    JDK7运行结果:true
    

    JDK6中,s1.intern()运行时,首先去常量池查找,发现没有该常量,则在常量池中开辟空间存储"11",返回常量池中的值(注意这里也没有使用该返回值),第三行中,s2直接指向常量池里边的字符串,所以s1和s2不相等。有可能会有小伙伴问为啥s1.intern()发现没有该常量呢,那是因为:

    String s1 = new String(“1”) + new String(“1”);这行代码实际操作是,创建了一个StringBuilder对象,然后一路append,最后toString,而toString其实是又重新new了一个String对象,然后把对象给s1,此时并没有在字符串常量池中添加常量

    JDK7中,由于字符串常量池在堆空间中,所以在s1.intern()运行时,发现字符串 常量池没有常量,则添加堆中“11”对象的引用到字符串常量池,这个引用返回堆空间“11”地址(注意这里也没有使用该返回值),这时s2通过查找字符串常量池中的常量,查到的是s1.intern()存在字符串常量池里的“11”对象的引用,既然都是指向堆上的“11”对象,所以s1和s2相等。

    例子4:

    String s1 = new String("1") + new String("1");
    System.out.println(s1.intern() == s1);
    

    JDK6中,常量池在永久代中,s1.intern()去常量池中查找"11",发现没有该常量,则在常量池中开辟空间存储"11",返回常量池中的值,s1指向堆空间地址,所以二者不相等。

    JDK7中,常量池在堆空间,s1.intern()去常量池中查找"11",发现没有该常量,则在字符串常量池中开辟空间,指向堆空间地址,则返回字符串常量池指向的堆空间地址,s1也是堆空间地址,所以二者相等。

    另外美团的团队写了一篇关于intern()的博客,我觉得很好可以参考一下
    深入解析String#intern

    4.3字符串常量池里存放的是引用还是字面量

    我在例子3中讲了在JDK7中字符串常量池在堆上,仔细看看例3啥时候会放引用

    那么啥时候会放字面量在字符串常量池呢,那就是在我们new一个String对象的时候如果字符串常量池里边有字面量那么就不会放,如果字符串常量池没有就会放字面量。看一个例子:

    package Oneday;
    import java.util.HashSet;
    import java.util.Set;
    public class a {
        public static void main(String[] args) {
            String str1= new String("123");
            String str2=new String("123");
            System.out.println(str1==str2);
            System.out.println(str1.intern()==str2.intern());    
        }
    }
    

    运行结果:
    在这里插入图片描述
    首先 String str1= new String("123");会在堆中创建一个对象,返回这个对象的引用给str1,同时它还会在字符串常量池中检查有没有有没有123这个对象,如果没有就==再创建一个对象(也就是123这个字面量)==在字符串常量池中

    注意这里是创建了两个对象

    但是当我们字符串常量池里边有123这个对象,那么就不用继续创建了

    上面例子的false那是因为堆中的123对象不是同一个对象,但是第二个str1.intern和s2.intern指的都是字符串常量池里的123对象所以是true

    展开全文
  • 这几天在看Java虚拟机方面的知识时,看到了有几种不同常量池的说法,然后我就去CSDN、博客园等上找资料,里面说的内容真是百花齐放,各自争艳,因此,我好好整理了一下,将我自认为对的理解写下来与大家共同探讨: ...

    简介:

    这几天在看Java虚拟机方面的知识时,看到了有几种不同常量池的说法,然后我就去CSDN、博客园等上找资料,里面说的内容真是百花齐放,各自争艳,因此,我好好整理了一下,将我自认为对的理解写下来与大家共同探讨:

    在Java的内存分配中,总共3种常量池:

    1.字符串常量池(String Constant Pool):

    1.1:字符串常量池在Java内存区域的哪个位置?

    • 在JDK6.0及之前版本,字符串常量池是放在Perm Gen区(也就是方法区)中;
    • 在JDK7.0版本,字符串常量池被移到了堆中了。至于为什么移到堆内,大概是由于方法区的内存空间太小了。

    1.2:字符串常量池是什么?

    • 在HotSpot VM里实现的string pool功能的是一个StringTable类,它是一个Hash表,默认值大小长度是1009;这个StringTable在每个HotSpot VM的实例只有一份,被所有的类共享。字符串常量由一个一个字符组成,放在了StringTable上。
    • 在JDK6.0中,StringTable的长度是固定的,长度就是1009,因此如果放入String Pool中的String非常多,就会造成hash冲突,导致链表过长,当调用String#intern()时会需要到链表上一个一个找,从而导致性能大幅度下降;
    • 在JDK7.0中,StringTable的长度可以通过参数指定:
    -XX:StringTableSize=66666

    1.3:字符串常量池里放的是什么?

    • 在JDK6.0及之前版本中,String Pool里放的都是字符串常量;
    • 在JDK7.0中,由于String#intern()发生了改变,因此String Pool中也可以存放放于堆内的字符串对象的引用。关于String在内存中的存储和String#intern()方法的说明,可以参考我的另外一篇博客:

    需要说明的是:字符串常量池中的字符串只存在一份!
    如:

    String s1 = "hello,world!";
    String s2 = "hello,world!";

    即执行完第一行代码后,常量池中已存在 “hello,world!”,那么 s2不会在常量池中申请新的空间,而是直接把已存在的字符串内存地址返回给s2。(这里具体的字符串如何分配就不细说了,可以看我的另一篇博客)

    2.class常量池(Class Constant Pool):

    2.1:class常量池简介:

    • 我们写的每一个Java类被编译后,就会形成一份class文件;class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池(constant pool table),用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References);
    • 每个class文件都有一个class常量池。

    2.2:什么是字面量和符号引用:

    • 字面量包括:1.文本字符串 2.八种基本类型的值 3.被声明为final的常量等;
    • 符号引用包括:1.类和方法的全限定名 2.字段的名称和描述符 3.方法的名称和描述符。

    3.运行时常量池(Runtime Constant Pool):

    • 运行时常量池存在于内存中,也就是class常量池被加载到内存之后的版本,不同之处是:它的字面量可以动态的添加(String#intern()),符号引用可以被解析为直接引用
    • JVM在执行某个类的时候,必须经过加载、连接、初始化,而连接又包括验证、准备、解析三个阶段。而当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中,由此可知,运行时常量池也是每个类都有一个。在解析阶段,会把符号引用替换为直接引用,解析的过程会去查询字符串常量池,也就是我们上面所说的StringTable,以保证运行时常量池所引用的字符串与字符串常量池中是一致的。
    展开全文
  • 本文先简述下常量池随JDK版本更替而产生的变化,后介绍三种常量池的区别,可按需观看. JDK版本迭代造成的变化 首先,众所周知,“常量池属于方法区的一部分”,...而在JDK7中,Hotspot将原本存储于永久代中的字符串常量池和静

    本文先简述下常量池随JDK版本更替而产生的变化,后介绍三种常量池的区别,可按需观看.

    JDK版本迭代造成的变化

    首先,众所周知,“常量池属于方法区的一部分”,这句话对于JDK6之前可能完全准确,但在JDK7之后就会有人有不同的理解了.
    这里以Hotspot虚拟机来进行说明.
    JDK6及其之前,方法区通过永久代进行实现,而常量池属于方法区的一部分也存在于永久代中,此时方法区甚至可以等同于永久代,因此说常量池是方法区的一部分是完全没有问题的.
    而在JDK7中,Hotspot将原本存储于永久代中的字符串常量池和静态变量移入堆中存储.但方法区中的其余内容依旧存储于永久代中(ps:永久代也是堆内的一片连续空间,因此此时二者其实也还都在堆中)
    JDK8彻底废除永久代,改用元空间实现方法区,并将方法区中其余内容全部移入元空间(元空间靠堆外内存实现),也就是说,此时常量池和静态变量存储于堆中,而方法区其余内容则是存储于堆外内存
    故在JDK8中,方法区其实已经被拆分了,常量池逻辑上属于方法区,而实际存储则如上所述.

    三大常量池的区别

    1. class常量池:存储类的信息与字面量(和字面量引用区分开,字面量是int a = 1,String str = “abc”里的1和”abc”)
    2. 运行时常量池:当类加载到内存后(详见类加载过程),class常量池中的内容就会全部存放到运行时常量池(因此运行时常量池也是一个类一个),但运行时常量池中的内容可以在运行时动态添加(最明显的就是字符串)
    3. 字符串常量池:存放字符串的引用,实际的值存储在运行时常量池中.
      因此,找字符串就先在字符串常量池中找,找不到再新建然后添加引用到字符串常量池中,而找其余字面量则是去对应类的运行时常量池中找,基础数据类型就直接比较,否则就比较地址.

    证明如下图
    在这里插入图片描述
    运行结果ture,false.
    因为a,b和A.a,A.b属于不同类,也存储于不同的运行时常量池中,故其地址也不同,但根据上述比较关系,a和A.a直接比较值故返回true,而b和A.b则比较地址,二者存储的运行时常量池都不同,地址一定不同,故返回false.

    展开全文
  • Java中的字符串常量池(String Pool)是存储在Java堆内存中的字符串池。我们知道String是java中比较特殊的类,我们可以使用new运算符创建String对象,也可以用双引号(”“)创建字串对象。 Java中的字符串常量池 下...
  • class常量池、字符串常量池和运行时常量池的区别

    千次阅读 多人点赞 2020-04-03 20:42:03
    文章目录一、概念1、Class 常量池(Class Constant Pool)1.1、常量池中数据项类型2、字符串池(String Pool、String Literal Pool)2.1、参考文章:3、运行时常量池(Runtime Constant Pool)4、总结二、方法区的...
  • 常量池、运行时常量池、字符串常量池 intern()方法变化 实例解析 一.常量池、运行时常量池、字符串常量池 1.常量池(即类文件常量池) 常量池是当class字节码文件被Java虚拟机加载后存放在方法区各种字面量(Literal)...
  • 这几天在看Java虚拟机方面的知识时,看到了有几种不同常量池的说法,然后我就去CSDN、博客园等上找资料,里面说的内容真是百花齐放,各自争艳,因此,我好好整理了一下,将我自认为对的理解写下来与大家共同探讨: ...
  • 在JDK1.7 字符串常量池被从方法区拿到了堆中, 这里没有提到运行时常量池,也就是说字符串常量池被单独拿到堆,运行时常量池剩下的东西还在方法区, 也就是hotspot中的永久代 在JDK1.8 hotspot移除了永久代用元空间(Me....
  • 字符串常量池与字符串相加以及final、intern之间的关系 1、字符串相加以及fianl 创建时: (1)s=“1”+“2”+“3”。这种情况会被编译器优化为一个String a=“123"直接放入字符串常量池中。 (2)s=new String(“12...
  • 什么常量池?2.为什么需要常量池? 1.什么常量池? 1.字节码文件中有个constant pool,就是常量池 2.当字节码文件被加载到内存中之后,方法区中会存放字节码文件的constant pool相关信息,这时候就成为了运行时...
  • class常量池 编译期 编译器生成的各种字面量和符号引用 静态文件 每个类独有 运行时常量池 类加载时 将class常量池的内容加载进来 存储在方法区(底层实现:jdk1.8前永久代,之后元空间,...
  • 常量池 是.class文件的常量池,也可以理解为一张表,虚拟机指令根据这...常量池只有类文件在编译的时候才会产生,而且是存储在类文件中的。而运行时常量池是在方法区,而且可在JVM运行期间动态向运行时常量池中写入...
  • 字符串常量池、class常量池和运行时常量池1.全局字符串池(string pool也有叫做string literal pool)2.class文件常量池(class constant pool)3.运行时常量池(runtime constant pool)总结 原文链接 1.全局字符串...
  • jvm 常量池及运行时常量池

    千次阅读 2018-10-25 13:39:22
    常量池存储在静态class文件中主要包含以下内容 字面量: 常量,字符串,基本类型等 符号引用: 类和接口全限定名,字段,方法名称及描述符 运行时常量池 当jvm加载class完成后,会将类的信息如常量池,字段,方法等...
  • 在java的内存分配中,经常听到很多关于常量池的描述,我开始看的时候也是看的很模糊,网上五花八门的说法简直太多了,最后查阅各种资料,终于算是差不多理清了,很多网上说法都有问题,笔者尝试着来区分一下这几个...
  • 常量池,也叫 Class 常量池(常量池==Class常量池)。Java文件被编译成 Class文件,Class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项就是常量池常量池是当Class文件被Java虚拟机加载进来后存放...
  • 文章目录1、引言2、Class常量池3、运行时常量池3.1 基本类型的包装类3.2 String.intern()4、字符串常量池4.1 直接用双引号...jvm的方法区里存放着类的版本,字段,方法,接口和常量池常量池存储着字面量和符号引用

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 104,109
精华内容 41,643
关键字:

常量池存储什么