java 内存结构
1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.
一条指令分为 操作+地址
在执行一条指令的时候,先把指令存内存取到DR,然后再取到IR,然后再交给指令译码器来转换指令,再向操作控制器发出对应的信号
为了保证程序的顺利执行,所以才 需要PC来保存 下一条指令的地址,由于大部分指令地址都是连续的,所以+1即可
2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。)
3. 堆:存放所有new出来的对象。
4. 静态域:存放静态成员(static定义的)
5. 常量池:存放字符串常量和基本类型常量(public static final)。
6. 非RAM存储:硬盘等永久存储空间
这里我们主要关心栈,堆和常量池,对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。
对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份
上代码说明
String s1 = "AB";
String s2 = new String("AB");
String s3 = "A";
String s4 = "B";
String s5 = "A" + "B";
String s6 = s3 + s4;
//false new关键字一定会产生一个对象,并且这个对象存储在堆中。所以String s3 = new String(“AB”);产生了两个对象:保存在栈中的s3和保存堆中的String对象 == 比较地址值所以为false
System.out.println(s1 == s2);
//true 由于常量池中不存在两个相同的对象,所以s1和s2都是指向JVM字符串常量池中的"AB"对象 == 比较地址值所以为true
System.out.println(s1 == s5);
//false Java中使用"+"连接字符串对象时,会创建一个StringBuilder()对象,并调用append()方法将数据拼接,最后调用toString()方法返回拼接好的字符串 s6在堆中创建新的对象
System.out.println(s1 == s6);
//true 特殊情况 String.intern() 方法时,如果存在堆中的对象,会直接保存对象的引用,而不会重新创建对象
System.out.println(s1 == s6.intern());
//false == 比较地址值所以为false s2作为对象存在堆中 s6指向字符串常量池
System.out.println(s2 == s2.intern());
图形解释