其他博友的不同理解方式:  http://hi.baidu.com/boywell/item/d5ee5b0cc0af55c875cd3cfd

我们先来看一个类

  1. public class javaPTest {
  2.  
  3. /**常量池
  4. * @param args
  5. */
  6. public static void main(String[] args) {
  7. // TODO Auto-generated method stub
  8. String i1 = "hello";
  9. String i2="world";
  10. String i3="helloworld";
  11. String i4="hello"+"world";
  12. String i5=new String("helloworld");
  13. String i6=new String("helloworld");
  14.  
  15. System.out.println("helloworld");
  16.  
  17. System.out.println(i5==i6);
  18. System.out.println(i3==i4);
  19. }
  20.  
  21. }

result: helloworld  false  true

why?我们可以通过javap -c    javaPTest  (前提是:先用javac编译通过) 来看该类的反编译结果

注意:  ldc     #2 是将常量池中下标为2的常量加载到栈中

astore_1  将栈顶元素存到到当前fame局部变量数组下标为1的变量中,栈顶元素出栈

  1. invokespecial 调用超类构造方法、实例初始化方法、私有方法
  2. aload:当前frame的局部变量数组中下标为index的引用型局部变量进栈
  3. ldc :将intfloatString型常量值从常量池中推送至栈顶
  4. astore i: 将栈顶数值(objectref)存入当前frame的局部变量数组中指定下标(index)处的变量中,栈顶数值出栈。
  5. new :创建一个对象,并且其引用进栈
  6. dup :复制栈顶数值,并且复制值进栈
  7.  
  8. F:\JAVA\javaIDE\study11.29\src\com\study\main>javap -c javaPTest
  9. Compiled from "javaPTest.java"
  10. public class com.study.main.javaPTest extends java.lang.Object{
  11. public com.study.main.javaPTest();
  12. Code:
  13. 0: aload_0
  14. 1: invokespecial #1; //Method java/lang/Object."<init>":()V
  15. 4: return
  16.  
  17. public static void main(java.lang.String[]);
  18. Code:
  19. 0: ldc #2; //String hello //将string类型常量值(hello)从常量池推送至栈顶
  20. 2: astore_1 //将
  21. 3: ldc #3; //String world
  22. 5: astore_2
  23. 6: ldc #4; //String helloworld
  24. 8: astore_3
  25. 9: ldc #4; //String helloworld
  26. 11: astore 4
  27. 13: new #5; //class java/lang/String //new了一个String对象,并将其引用进栈,
    16: dup
  28. 17: ldc #4; //String helloworld
  29. 19: invokespecial #6; //Method java/lang/String."<init>":(Ljava/lang/Strin
  30. g;)V
  31. 22: astore 5
  32. 24: new #5; //class java/lang/String
  33. 27: dup
  34. 28: ldc #4; //String helloworld
  35. 30: invokespecial #6; //Method java/lang/String."<init>":(Ljava/lang/Strin
  36. g;)V
  37. 33: astore 6
  38. 35: getstatic #7; //Field java/lang/System.out:Ljava/io/PrintStream;
  39. 38: ldc #4; //String helloworld
  40. 40: invokevirtual #8; //Method java/io/PrintStream.println:(Ljava/lang/Str
  41. ing;)V
  42. 43: getstatic #7; //Field java/lang/System.out:Ljava/io/PrintStream;
  43. 46: aload 5 //将常量数组中下边为5和6的变量加载到栈中(其实两个都存放#4 17行和28行分别表示在数组的4,5下标中,存放#4)
    48: aload 6
  44. 50: if_acmpne 57 //比较 如果不相等就跳转
    53: iconst_1
  45. 54: goto 58
  46. 57: iconst_0
  47. 58: invokevirtual #9; //Method java/io/PrintStream.println:(Z)V
  48. 61: getstatic #7; //Field java/lang/System.out:Ljava/io/PrintStream;
  49. 64: aload_3 //将常量数组中下边为3和4的变量加载到栈中(其实两个都存放#4   8行和11行分别表示在数组的3,4下标中,存放#4)
    65: aload 4
  50. 67: if_acmpne 74
  51. 70: iconst_1
  52. 71: goto 75
  53. 74: iconst_0
  54. 75: invokevirtual #9; //Method java/io/PrintStream.println:(Z)V
  55. 78: return
  56.  
  57. }

我们重点看看String i5=new String("helloworld");对应的反编译代码

  1. 13: new #5; //class java/lang/String //new了一个String对象,并将其引用进栈,
  2. 16: dup
  3. 17: ldc #4; //String helloworld
  4. 19: invokespecial #6; //Method java/lang/String."<init>":(Ljava/lang/Strin
  5. g;)V
  6. 22: astore 5

执行过程中堆栈的变化 

所谓的常量池就是在内存中的一个数组,这个数组中记录的都是直面量,并且在数组中,不会出现相同的直面量。

用jvm指令分析String 常量池的更多相关文章

  1. java基础进阶一:String源码和String常量池

    作者:NiceCui 本文谢绝转载,如需转载需征得作者本人同意,谢谢. 本文链接:http://www.cnblogs.com/NiceCui/p/8046564.html 邮箱:moyi@moyib ...

  2. Java String 常量池理解

    String:字符串常量池 作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么,我们带着以下三个问题,去理解字符串常量池: 字 ...

  3. Java的Integer常量池和String常量池

    1.Integer的常量池 看下面一段代码: package cn.qlq.test; public class ArrayTest { public static void main(String[ ...

  4. java基础知识回顾之---java String final类 容易混淆的java String常量池内存分析

    /** *   栈(Stack) :存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放  在常量池中). 堆(heap):存 ...

  5. jvm堆、栈、String常量池

    原文地址:http://blog.csdn.net/tophawk/article/details/78704074 程序计数器:它的生命周期与线程相同,线程私有.较小的内存区域,用以完成分支.循环. ...

  6. 深入理解JVM内存分配和常量池

    一.虚拟机的构成 虚拟结主要由运行时数据区.执行引擎.类加载器三者构成: 而我们所说的JVM内存模型指的就是运行时数据区,下面具体分析一下运行时数据区: 二.运行时数据区组成和各个区域的作用 我们看到 ...

  7. 字符串String: 常量池

    2.1          String类 String是不可变类, 即一旦一个String对象被创建, 包含在这个对象中的字符序列是不可改变的, 直至该对象被销毁. String类是final类,不能 ...

  8. 资深架构师教你String 常量池、 String.itern()

    什么是常量 用final修饰的成员变量表示常量,值一旦给定就无法改变! final修饰的变量有三种:静态变量.实例变量和局部变量,分别表示三种类型的常量. Class文件中的常量池 在Class文件结 ...

  9. 0024 Java学习笔记-面向对象-包装类、对象的比较、String常量池问题

    包装类 基本类型-->包装类 byte-->Byte short-->Short int-->Integer long-->Long char-->Characte ...

随机推荐

  1. node的close

    在http.ServerResponse对象的end方法被调用之前,如果连接被中断,将触发http.ServerResponse对象的close事件. var http=require("h ...

  2. Imply.io单机安装

    安装 wget https://static.imply.io/release/imply-2.5.15.tar.gz .tar.gz -C /usr/local/ cd imply- nohup b ...

  3. C 语言 - Unicode 解决中文问题

    问题: 打印一句中文 #include <stdio.h> int main() { char str[] = "你好,世界"; printf("%s\n&q ...

  4. eclipse 使用lombok 精简java bean

    前言:             lombok 提供了简单的注解的形式来帮助我们简化消除一些必须有但显得很臃肿的 java 代码.特别是相对于 POJO             lombok 的官方网址 ...

  5. Memcached的过期数据的过期机制及删除机制(LRU)

    Memcached的过期数据的过期机制及删除机制1.当某个值过期后,并没有从内存删除,因此,使用stats命令统计时,curr_item参数有信息(不为0)2.当某个新值去占用他的位置时,当成空chu ...

  6. TCP超时与重传机制

    TCP超时与重传机制    TCP协议是一种面向连接的可靠的传输层协议,它保证了数据的可靠传输,对于一些出错,超时丢包等问题TCP设计的超时与重传机制.其基本原理:在发送一个数据之后,就开启一个定时器 ...

  7. 微信小程序跳转navigateTo与redirectTo

    转自:https://www.cnblogs.com/perfect-yuewei/p/8301761.html 2018-01-16 - 微信中跳转页面方法目前接触到两种 navigateTo与re ...

  8. SPI子系统分析之四:驱动模块

    内核版本:3.9.5 SPI控制器层(平台相关) 上一节讲了SPI核心层的注册和匹配函数,它是平台无关的.正是在核心层抽象了SPI控制器层的相同部分然后提供了统一的API给SPI设备层来使用.我们这一 ...

  9. Java Socket编程之UDP

    UDP编程: 将要传输的数据定义成数据包(Datagram),在数据报中指明所要到达的Socket(主机地址和端口号),然后再将数据报发送出去. 相关操作类:     DatagramPacket   ...

  10. R包安装失败failed to download mirrors file

    在R console中使用install.packages()来安装第三方包时,会出现这样的错误: 即使我们选择的是China的镜像也解决不了问题. 这时候,可以先试试用IE打开上图中黑底部分的URL ...