关闭

JVM-常量池

826人阅读 评论(0) 收藏 举报
分类:
学习JVM之后,发现对常量池的理解又深入了一些。下面就从JVM的层面去理解JAVA程序中那些常见的语句。
读过笔者博客“JVM-类的生命周期“http://yizhenn.iteye.com/blog/2290619的读者都应该已经知道,JVM在加载class文件时经历了装载,连接,初始化的过程,其中连接又包括验证,准备和解析。我们就来说说这个解析。

所谓解析,就是将class文件中的静态常量池中的符号引用解析为直接引用,说白了,就是为class常量池中的一些常量创建对象。比如String str="abc";理论上来讲直接在class静态常量池中存放"abc"即可。但是我们知道,JAVA中除了8种基本类型之外,其他的都是引用。因此,对于静态常量池中的"abc",JVM会在堆中创建一个对象,静态常量池中的str就指向这个刚刚创建的对象。像str这样的常量对象所在的空间,叫做动态常量池。

在JAVA中,String和Integer,Short,Long,Character,Boolean,Byte这六种基本类型的封装类都实现了动态常量池机制。对于六种基本类型的封装类,我们以Integer为代表进行说明。

如下代码:
String a="123";
String b="123";

在解析的时候,发现静态常量池中有a="123",就会在动态常量池中寻找是否有值为"123"的对象,结果没有找到,就会执行new String("123"),然后使静态常量池中的a指向该对象,当发现静态常量池中有b="123",就会在动态常量池中寻找是否有值为"123"的对象,结果找到了之前创建的那个对象,就会把那个对象的地址返回给静态常量池中的b。

上面的过程是在解析的时候做的,当然你也可以认为在执行的时候做的。但不管怎样,一定存在一个常量池,当执行String str="xx";的时候,先到常量池中去寻找值为xx的对象,如果存在,就直接返回该对象地址,否则在动态常量池中创建一个新对象并返回地址。

如下代码:
String a=new String("123");
String b=new String("123");

第一行代码在执行的时候,JVM见到"123",会先到动态常量池中看是否有值为"123"的对象,如果没有,在常量池中创建一个对象String("123").这个过程和a没有半毛钱关系,你可以认为这是JVM常量池自学习的过程。接着,在堆区创建一个对象String("123");并将该对象的引用返回给a;
第二行代码也是这样的过程,所以上面的两行代码可能产生2或3个对象。

对于String类,还存在一个str.intern()方法,他的作用是检查动态常量池中是否存在值与str对象相同的对象,如果存在,直接返回该对象的引用。如果不存在,就在常量池中创建一个对象,然后返回他的引用。
如下代码:
String a="123";
String b="123";
String c=new String("123");
String d=c.intern();

对于上面的代码,你应该能理解,a和b和d都指向的是动态常量池中的那个对象String("123"),而c指向的是堆中的对象String("123");

介绍了String类的常量池,我们来说Integer类的常量池。Integer类型的取值不像String类型那么广泛,String常量池中的对象收集自程序。Integer常量池中的对象是固定的,只有取值为-128~127的这256个对象。当Integer.valueOf(i)中i的值是-128~127时,直接返回常量池中的对象,否则在堆区新建一个对象并返回他的引用。这可以从jdk源码中得到证明,在jdk源码中,Integer有这样的一个方法:
    public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }


这个方法是自动装包时候用的方法,何谓装包?把int这个基本类型转化为Integer这个引用类型就是装包。
代码如下:
Integer a=1;
Integer b=1;
Integer c=1111;
Integer d=1111;

对于上面的代码,实际上如下:
Integer a=Integer.valueOf(1);
Integer b=Integer.valueOf(1);
Integer c=Integer.valueOf(1111);
Integer d=Integer.valueOf(1111);

因此a和b指向Integer常量池中的同一个对象,他们的值相等。c和d指向堆区中的不同对象,他们的值不等。

如下代码:
Integer a=new Integer(1);
Integer b=new Integer(1);

由于使用了new,强制的在堆区创建了两个对象,没用到常量池优化,因此a和b的值不等。

这里顺便提一下装包和拆包,将基本类型转化为对应的封装类的过程叫装包,反之叫拆包。当基本类型和其对应的封装类执行比较的时候,比如Integer对象和int型比较,这会使用拆包,将Integer类型拆包为int,这个过程调用Integer的intValue()方法。

关于上面提到的其余5中包装类的常量池与Integer类似,在此不再赘述。
0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

JVM-体系结构

大家都知道,java号称一次编译,处处运行。之所以能够这么强大,jvm功不可没。直接上图: 笔者看过这张图很多次,一直没能理解。一直到最近,觉得能够明白到写博客了。一个java文件通过编译可以得到c...
  • yizhenn
  • yizhenn
  • 2016-08-11 14:09
  • 224

JVM-类加载机制

类加载过程    类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。它们开始的顺序如下图所示:    其中类加载的过程包括了加载...
  • qq924862077
  • qq924862077
  • 2017-11-01 18:39
  • 144

JVM-内存模型

本文转自 http://blog.csdn.net/zhshulin/article/details/50389981 本篇其实就是一个读书笔记,书是《深入理解JAVA虚拟机》,在网上搜索JAVA内存...
  • CodeNoodles
  • CodeNoodles
  • 2016-07-07 16:14
  • 244

JVM-虚拟机内存区域

此篇主要用于记录JVM内存区域学习。首先说明的是堆与栈堆与栈从数据结构的角度说栈是一种后进先出的线性表结构,只允许在一端进行插入与删除操作,也叫做后进先出表( Last in First Out,LI...
  • No_Endless
  • No_Endless
  • 2016-11-13 15:26
  • 211

JVM-垃圾回收算法

跟踪收集器跟踪收集器采用集中式的管理方式,全局记录每个对象的引用状态,执行时,把一系列GC Root对象作为起点,向下搜索引用链,如果一个对象到GC Root之间没有任何引用链,那么这个对象就可以被回...
  • zhangdong2012
  • zhangdong2012
  • 2016-11-19 16:54
  • 120

JVM-垃圾收集器

JVM垃圾收集器
  • qslnierenwang
  • qslnierenwang
  • 2017-02-09 16:30
  • 79

JVM-内存划分

JAVA基础-[JVM内存模型] JVM内存模型图 JVM虚拟机栈 【概念】就是我们常说的堆栈的栈(常常把内存粗略的分为堆和栈) 线程私有,生命周期与线程一样 【优点】内存的...
  • qslnierenwang
  • qslnierenwang
  • 2016-08-26 22:23
  • 69

jvm-之native关键字

native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。Java语言本身不能对操作系统底层进行访问和操作,但是可以通过JNI接口...
  • qq_33926132
  • qq_33926132
  • 2016-12-02 20:26
  • 78

JVM-内存模型

本篇其实就是一个读书笔记,书是《深入理解JAVA虚拟机》,在网上搜索JAVA内存,说的比较好的其实很多都源自这本书,作为一个JAVA程序员,理解虚拟机是通向高级程序员的必经道路。本篇中的图片源自当时网...
  • qq_33762302
  • qq_33762302
  • 2017-02-08 11:20
  • 61

jvm-运行时数据区域

今天我们说到jvm的运行时数据区域。 虚拟机要运行需要存储和修改数据,这一部分也是垃圾回收机制重点照顾的地方。 上图就是jvm运行时数据区域划分,其中 方法区和堆 也就是蓝色的部分是线程共享的,白...
  • wenhao_1992
  • wenhao_1992
  • 2017-01-19 19:06
  • 108
    个人资料
    • 访问:143099次
    • 积分:1698
    • 等级:
    • 排名:千里之外
    • 原创:139篇
    • 转载:10篇
    • 译文:0篇
    • 评论:37条
    最新评论