JVM-常量池
来源:互联网 发布:深圳飞扬数码通讯淘宝 编辑:程序博客网 时间:2024/05/29 08:39
学习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为代表进行说明。
如下代码:
在解析的时候,发现静态常量池中有a="123",就会在动态常量池中寻找是否有值为"123"的对象,结果没有找到,就会执行new String("123"),然后使静态常量池中的a指向该对象,当发现静态常量池中有b="123",就会在动态常量池中寻找是否有值为"123"的对象,结果找到了之前创建的那个对象,就会把那个对象的地址返回给静态常量池中的b。
上面的过程是在解析的时候做的,当然你也可以认为在执行的时候做的。但不管怎样,一定存在一个常量池,当执行String str="xx";的时候,先到常量池中去寻找值为xx的对象,如果存在,就直接返回该对象地址,否则在动态常量池中创建一个新对象并返回地址。
如下代码:
第一行代码在执行的时候,JVM见到"123",会先到动态常量池中看是否有值为"123"的对象,如果没有,在常量池中创建一个对象String("123").这个过程和a没有半毛钱关系,你可以认为这是JVM常量池自学习的过程。接着,在堆区创建一个对象String("123");并将该对象的引用返回给a;
第二行代码也是这样的过程,所以上面的两行代码可能产生2或3个对象。
对于String类,还存在一个str.intern()方法,他的作用是检查动态常量池中是否存在值与str对象相同的对象,如果存在,直接返回该对象的引用。如果不存在,就在常量池中创建一个对象,然后返回他的引用。
如下代码:
对于上面的代码,你应该能理解,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有这样的一个方法:
这个方法是自动装包时候用的方法,何谓装包?把int这个基本类型转化为Integer这个引用类型就是装包。
代码如下:
对于上面的代码,实际上如下:
因此a和b指向Integer常量池中的同一个对象,他们的值相等。c和d指向堆区中的不同对象,他们的值不等。
如下代码:
由于使用了new,强制的在堆区创建了两个对象,没用到常量池优化,因此a和b的值不等。
这里顺便提一下装包和拆包,将基本类型转化为对应的封装类的过程叫装包,反之叫拆包。当基本类型和其对应的封装类执行比较的时候,比如Integer对象和int型比较,这会使用拆包,将Integer类型拆包为int,这个过程调用Integer的intValue()方法。
关于上面提到的其余5中包装类的常量池与Integer类似,在此不再赘述。
读过笔者博客“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
- jvm的常量池
- JVM的常量池
- JVM 常量池理解
- JVM常量池
- jvm常量池
- jvm常量池
- JVM 常量池
- JVM常量池
- JVM 常量池理解
- JVM常量池
- java-jvm-常量池
- jvm的常量池
- jvm常量池
- JVM-常量池
- JVM常量池
- jvm-常量池
- jvm常量池
- JVM中的常量池解析
- JVM-对象的生命周期
- predis client class分析
- JVM-线程同步
- JVM-典型的垃圾收集器
- 103. Binary Tree Zigzag Level Order Traversal
- JVM-常量池
- JVM-java字符编码
- 专利
- 如何判断网站被百度降权?
- JS异步执行
- 数据库事务
- Android选取gridview并且标出选择的顺序
- Spring事务处理-编程式事务和声明式事务
- 设计模式之回调模式