Jvm数据储存转载百度文库

先来了解一下JVM运行时数据区的内存模型。 
《深入Java虚拟机》书中是这样描述的:JVM运行时数据区的内存模型由五部分组成:
  1.  方法区(类型信息被存储在一个称为方法区的内存逻辑区中。类型信息是由类加载器在类加载时从类文件中提取出来的。类(静态)变量也存储在方法区中)
2. 堆(存放所有new出来的对象。)
  3. Java栈(存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。))
4. PC寄存器(最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.)
5.  本地方法栈

这里我们主要关心栈,堆和常量池,对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期 是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。  对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的 就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份

常量池
虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集和,包括直接常量(string,integer和 floating point常量)和对其他类型,字段和方法的符号引用。对于string常量,它的值是在常量池中的。而jvm中的常量池在内存当中是以表的形式存在的, 对于string类型,有一张固定长度的constant_string_info表用来存储文字字符串值,注意:该表只存储文字字符串值,不存储符号引 用。 
对于String s = "hello" 
其中"hello"值是在编译的时候就确定下来的,如果改成s = "hello" + 1;将程序编译期,jvm就将常量字符串的"+"连接优化为连接后的值,这里s被优化为"hello1"
而对于String s = new String("hello");
这里"hello"本身就是常量池中的一个对象,而在运行时执行new string()时,将常量池中的对象复制一份放到堆中,并且把堆中的这个对象的引用交给s持有。所以这条语句就创建了2个string对象

posted on 2020-03-02 17:44  苏阔Garrison  阅读(107)  评论(0编辑  收藏  举报

导航