`
jiangwenfeng762
  • 浏览: 288156 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

jvm常量池

阅读更多

jvm规范中,每个类型都有自己的常量池。常量池是某类型所用常量的一个有序集合,包括直接常量(基本类型,String)和对其他类型、字段、方法的符号引用。之所以是符号引用而不是像c语言那样,编译时直接指定其他类型,是因为java是动态绑定的,只有在运行时根据某些规则才能确定具体依赖的类型实例,这正是java实现多态的基础。

 

为了对常量池有更具体的认识,下面引用几个例子:

1,常量池中对象和堆中的对象

public class Test{

Integer i1=new Integer(1);
   Integer i2=new Integer(1);
//i1,i2分别位于堆中不同的内存空间

   System.out.println(i1==i2);//输出false


   Integer i3=1;
   Integer i4=1;
//i3,i4指向常量池中同一个内存空间

   System.out.println(i3==i4);//输出true

//很显然,i1,i3位于不同的内存空间

System.out.println(i1==i3);//输出false

}

2,8种基本类型的包装类和对象池

java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现。另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127时才可使用对象池,也即对象不负责创建和管理大于127的这些类的对象。以下是一些对应的测试代码:

public class Test{

public static void main(String[] args){

   //5种整形的包装类Byte,Short,Integer,Long,Character的对象,

   //在值小于127时可以使用常量池

   Integer i1=127;

   Integer i2=127;

   System.out.println(i1==i2)//输出true

   //值大于127时,不会从常量池中取对象

   Integer i3=128;

   Integer i4=128;

   System.out.println(i3==i4)//输出false

   //Boolean类也实现了常量池技术

   Boolean bool1=true;

   Boolean bool2=true;

   System.out.println(bool1==bool2);//输出true

   //浮点类型的包装类没有实现常量池技术

   Double d1=1.0;

   Double d2=1.0;

   System.out.println(d1==d2)//输出false

  

}

}

3,String也实现了常量池技术

String类也是java中用得多的类,同样为了创建String对象的方便,也实现了常量池的技术,测试代码如下:

public class Test{

public static void main(String[] args){

//s1,s2分别位于堆中不同空间

String s1=new String("hello");

String s2=new String("hello");

System.out.println(s1==s2)//输出false

//s3,s4位于池中同一空间

String s3="hello";

String s4="hello";

System.out.println(s3==s4);//输出true

}

}

 

4.字符串比较更丰富的一个例子

package testPackage;

class Test {

 public static void main(String[] args) {

  String hello = "Hello", lo = "lo";

  System.out.print((hello == "Hello") + " ");

  System.out.print((Other.hello == hello) + " ");

  System.out.print((other.Other.hello == hello) + " ");

  System.out.print((hello == ("Hel"+"lo")) + " ");

  System.out.print((hello == ("Hel"+lo)) + " ");

  System.out.println(hello == ("Hel"+lo).intern());

 }

}

class Other { static String hello = "Hello"; }

and the compilation unit:

package other;

public class Other { static String hello = "Hello"; }

produces the output:

true true true true false true

 

输出结果的分别解释如下:

在同包同类下,引用自同一String对象.

在同包不同类下,引用自同一String对象.

在不同包不同类下,依然引用自同一String对象

在编译成.class时能够识别为同一字符串的,自动优化成常量,所以也引用自同一String对象

在运行时创建的字符串具有独立的内存地址,所以不引用自同一String对象

String的intern()方法会查找在常量池中是否存在一份equal相等的字符串,如果有则返回一个引用,没有则添加自己的字符串进进入常量池,

注意,只是字符串部分,

所以这时会存在2份拷贝,常量池的部分被String类私有持有并管理,自己的那份按对象生命周期继续使用.

 

分享到:
评论
1 楼 甘艳丽 2012-03-02  
//浮点类型的包装类没有实现常量池技术

   Double d1=1.0;

   Double d2=1.0;

   System.out.println(d1==d2)//输出false

我测试的时候是true.

相关推荐

    JVM常量池教程吐血整理干货.md

    ### JVM常量池详解 #### Class常量池(静态常量池) 在Java程序的编译过程中,每个`.class`文件都会包含一个常量池,这个常量池被称为Class常量池或者静态常量池。它存在于每个`.class`文件的`Constant Pool`部分...

    第4节: 揭秘JVM字符串常量池和Java堆-01

    第4节: 揭秘JVM字符串常量池和Java堆-01第4节: 揭秘JVM字符串常量池和Java堆-01第4节: 揭秘JVM字符串常量池和Java堆-01第4节: 揭秘JVM字符串常量池和Java堆-01第4节: 揭秘JVM字符串常量池和Java堆-01第4节: ...

    JDK8的JVM内存结构,元空间替代永久代成为方法区及常量池的变化1

    常量池分为静态常量池、运行时常量池、字符串常量池和整型常量池。静态常量池存在于每个*.class文件中,包含了字面量和符号引用,这部分在类加载的链接阶段会被解析成直接引用。运行时常量池则是在虚拟机运行时载入...

    java 内存中 堆、栈、常量池、方法区的总结

    `,JVM会在常量池中查找是否存在"abc",如果存在则直接引用该字符串;如果不存在,则创建一个新的字符串对象并将其放入常量池。这种方式创建的字符串,一旦创建便不会改变,且可以共享。 而使用new关键字创建字符串...

    06-VIP-JVM调优实战及常量池详解(1)1

    当一个新字符串被创建时,JVM会检查常量池中是否存在相同的字符串,如果存在,就直接返回其引用,否则会在堆中创建一个新的实例并添加到常量池。 垃圾收集(Garbage Collection, GC)是JVM管理内存的重要机制。GC...

    06-VIP-JVM调优实战及常量池详解(预习)1

    《JVM调优实战与常量池详解》 在Java开发中,JVM(Java虚拟机)的性能优化是一项至关重要的任务。通过对JVM进行调优,我们可以显著提升应用程序的运行效率,减少内存消耗,避免不必要的垃圾回收(GC)带来的性能...

    JVM 50道面试题和答案.docx

    2. **JVM常量池**: - JDK 1.8之前,字符串常量池位于方法区(也称为永久代)。1.8之后,字符串常量池被移到堆中,包括intern()方法后的结果和双引号直接创建的字符串。 - 运行时常量池(Runtime Constant Pool)...

    JVM大厂必备面试题八股文

    JVM常量池中存储的是对象,尤其是JDK 1.8后,String常量池位于堆中。 Java中的对象不一定都在堆上分配,逃逸分析技术可以使某些对象在栈上分配,从而优化内存使用。内存溢出(OOM)和内存泄漏是两种不同的问题,...

    RodJohn#jvm#内存区域_运行时常量池1

    常量池静态常量池即*.class文件中的常量池,用于存放字面量和符号引用运行时常量池是jvm运行期间,存储常量的数据结构运行时常量池概念运行时常量池(Runti

    java11-jvm白皮书_java_govwe_

    此外,JEP 315(JVM Constants API)为开发者提供了一种更简单的方式访问和操作JVM常量池,简化了反射和类加载器的实现。 总的来说,Java 11的JVM在很多方面都有所改进,包括垃圾收集、模块化、HTTP客户端、性能...

    java内存分配之常量池,栈,堆1

    在Java中,内存主要分为四个区域:寄存器、栈、堆和方法区(包括常量池)。以下是这四个区域的详细说明: 1. **寄存器**: 这是计算机硬件的一部分,用于存储非常快速访问的数据。在Java中,寄存器主要由JVM直接管理...

    java常量池分析.pdf

    Java常量池是Java编程语言中的一个重要概念,它在JVM(Java虚拟机)的运行时数据区中占据着核心地位。常量池是每个类或接口在编译时都会生成的一部分,它存储了各种类型的常量,包括字面量(如字符串、整数、浮点数...

    深入探索Java常量池

    Java常量池是Java虚拟机(JVM)中一个非常重要的概念,它主要分为两种:静态常量池和运行时常量池。静态常量池是class文件中的常量池,包括字符串(数字)字面值、类和方法的信息,占用了class文件的大部分空间。...

    什么是字符串常量池?Java开发Java经验技巧共6页.p

    字符串常量池是Java虚拟机(JVM)在运行时为字符串常量创建的一个特殊的存储区域,它的主要作用是为了提高内存效率和字符串的复用。 首先,我们来明确一下什么是字符串常量。在Java中,字符串是不可变的对象,一旦...

    java入门教程:数据类型_运行时常量池.docx

    数据类型决定了变量可以存储的值的种类和大小,而运行时常量池则是Java虚拟机(JVM)内存模型中的一个重要组成部分。 首先,让我们详细讨论Java的数据类型。Java的数据类型分为两大类:基本数据类型和引用数据类型...

    java中常量以及常量池

    1、举例说明 变量 常量 字面量  1 int a=10;  2 float b=1.234f;  3 String c="abc";  4 final long d=10L;  a,b,c为变量,d为常量 两者都是左值;...  运行时常量池:是jvm虚拟机在完成类装

    详解JAVA 常量池

    在JVM中,常量池是Class文件中的一个重要组成部分,主要用于存储类的常量信息。常量池可以分为以下几部分: 1. Class文件常量池:用于存储类的常量信息,例如类的名称、字段、方法等。 2. 运行时常量池:用于存储...

    字符数组的存储方式 字符串常量池.docx

    为了提高效率和内存管理,Java虚拟机(JVM)引入了字符串常量池这一概念。字符串常量池是一个特殊的区域,它存储了程序中所有的字符串常量,避免了多次创建相同的字符串对象。本文将详细探讨字符串常量池的存储方式...

    java堆、栈和常量池

    - **结构形式**:在JVM中,常量池是以表的形式存在的。对于String类型,有一张固定的`CONSTANT_String_info`表来存储文字字符串值,该表只存储文字字符串值,而不包含符号引用。 #### 五、总结 Java的内存管理机制...

Global site tag (gtag.js) - Google Analytics