jvm虚拟内存分布:
程序计数器是jvm执行程序的流水线,存放一些跳转指令。
本地方法栈是jvm调用操作系统方法所使用的栈。
虚拟机栈是jvm执行java代码所使用的栈。
方法区存放了一些常量、静态变量、类信息等,可以理解成class文件在内存中的存放位置。(在jdk8中,移除了方法区,转而用Metaspace区域替代)
虚拟机堆是jvm执行java代码所使用的堆。
Java中的常量池,实际上分为两种形态:静态常量池和运行时常量池。
静态常量池:
*.class文件中的常量池,每个class文件都有一个class常量池。这种常量池主要用于存放两大类常量:字面量(Literal)和符号引用量(Symbolic References)
字面量包括:1.文本字符串 2.八种基本类型的值 3.被声明为final的常量等;
符号引用包括:1.类和方法的全限定名 2.字段的名称和描述符 3.方法的名称和描述符。
运行时常量池:
JVM在执行某个类的时候,必须经过加载、连接、初始化,而连接又包括验证、准备、解析三个阶段。而当类加载到内存中后,jvm就会将class文件中的常量池载入到内存中,并保存在方法区中。运行时常量池相对于CLass文件常量池的另外一个重要特征是具备动态性,字面量可以动态的添加(String类的intern()方法),符号引用可以被解析为直接引用。Java语言并不要求常量一定只有编译期才能产生,也就是并非预置入CLass文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用比较多的就是String类的intern()方法。当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并返回此 String 对象的引用。
常量池的好处
常量池是为了避免频繁的创建和销毁对象而影响系统性能,其实现了对象的共享。
例如字符串常量池,在编译阶段就把所有的字符串文字放到一个常量池中。
(1)节省内存空间:常量池中所有相同的字符串常量被合并,只占用一个空间。
(2)节省运行时间:比较字符串时,==比equals()快。对于两个引用变量,只用==判断引用是否相等,也就可以判断实际值是否相等。
==比equals()快的原因:
在java 中,直接使用==操作符,比较的是两个字符串的引用地址。
instanceof 是 Java 的一个二元操作符,类似于 ==,>,< 等操作符。是 Java 的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
通过string类的eeqquals方法的源码可以看出调用equals方法,会先判断字符串和参数是否引用的同一个地址,不是同一对象的话才会比较值。
使用常量池的例子: