通过这篇文章你将了解堆、栈、方法区等以及8种基本类型与引用类型在内存中的区别
栈区:
栈中只存储方法中(不包括对象的成员变量)的基础数据类型和引用数据类型地址,对象都存放在堆区中,每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
堆区:
存储的全部是对象实例,每个对象都包含一个与之对应的class的信息(class信息存放在方法区)。jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身,几乎所有的对象实例和数组都在堆中分配。
方法区:
又叫静态区,跟堆一样,被所有的线程共享。它用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。。
常量池:常量池(constant pool)属于方法区的一部分,指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量(现在是存放在堆中),多个相同的内容在常量池中只存放一份。
内存堆和栈的区别:堆一般用户存储可变长度的数据,如字符串类型;而栈用于存储固定长度的数据,如整型int。堆的读写速度远不及栈,因为堆是程序在运行是动态分配内存,而栈在程序编译时便已经分配好内存,但栈的大小不如堆,所以常出现栈溢出而很少出现堆溢出。
JAVA各个区线程共享图
问题一:
有如下代码:
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
String s4 = new String("abc");
System.out.println(s1 == s2) ;//true
System.out.println(s3 == s4); //false
System.out.println(s1 == s3); //false
为什么 s1==s2是ture而s3==s4与s1==s3却是false呢?
原因:
其实java中有一个“字符数据池”的内存管理机制。
当执行String str="abc"这句话时,会先去“字符数据池”搜索时候有“abc”这个字符串,如果有,
则将字符串的首地址赋值给str,如果没有,生成一个新的字符串“abc”并且将首地址赋值给str;
而执行 String str=new String("abc") 这句话时,不会考虑时候已经存在了“abc”这个字符串,而
是直接生成一个新的字符串“abc”并将首地址赋值给str,注意“abc”并不放在“字符数据池”中;
所以s2的地址其实是由s1给的,而s3,s4是分别new出来的两个不同地址。
问题二:
有如下代码:
int a1=127; int a2=127; Integer a3=127; Integer a4=127; Integer a5 = 128; Integer a6 = 128; Integer a7 = new Integer(127); Integer a8 = new Integer(127); System.out.println(a1 == a2);//true System.out.println(a3 == a4);//true System.out.println(a5 == a6);//false System.out.println(a7 == a8);//false System.out.println(a1 == a3);//true System.out.println(a3 == a7);//false
为什么a3 == a4是true而 a5 == a6却是false呢?
主要原因在JAVA中的Integer方法中如果值在-128-127范围内会将这个值进行缓存,下一次访问它因为127已经存在,所以会将s3的地址直接指向s4。
static final int low = -128; static final int high = 127;
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
引用类型访问对象的两种方式:句柄访问方式和直接指针
1. 如果使用句柄访问方式,Java堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息。
2. 如果通过直接指针方式访问,Java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,reference中直接存储的就是对象的地址。
参考:https://blog.csdn.net/zhangsanfeng2009/article/details/80900963
https://blog.csdn.net/qq_34467922/article/details/80790443
https://blog.csdn.net/OyangYujun/article/details/41173747