JAVA的内存主要分为三个大的区域,栈,堆,方法区
1.栈
1.栈是方法在执行时的内存模型,每个方法被调用时都会创建一个栈帧,栈帧中会存储(变量,操作数,方法等)
2.JVM虚拟机会为每个线程创建一个栈,用于存放该线程执行方法时产生的栈帧
3.栈是属于线程私有的,每个独立的线程不能访问对方的栈
4.栈的存储特性是"先进后出","后进先出"这里指栈帧的进出顺序
5.栈是由系统自动分配的,其速度快切是一个连续的内存空间
2.堆
1.堆是用来存储创建好的对象(如数据,包装类等)
2.JVM虚拟机只有一个堆,是所有线程共享的
3.堆是一个不连续的内存空间,其分配灵活但速度慢
3.方法区
1.在JDK7以前方法区中存在永久代,但JDK7之后部分去除了永久代,将字符变量,常量池,静态变量都移动到了堆内存中
2.JVM虚拟机的方法区和堆是一样的都只有一个,被所有线程共享
3.方法区其实也可以看做是一个堆,不过是用于存储不会发生改变的数据,如类,常量,静态方法等
4.JDK8时方法区就由"元数据空间"与堆相互结合而成
2.程序运行时内存的变化(这里简单讲解一下运行时内存发生变化,帮助大家更好的理解JVM虚拟机的内存)
public class Person {
int ID;//设置变量ID
String NAME;//设置变量名字
public static void main(String[] args) {
Person p = new Person();//创建Person类对象P
p.ID=10;//给P对象的变量ID赋值
p.NAME = "张三";//给P对象的变量NAME赋值
p.show();//调用P对象的show方法进行输出
}
public void show(){
System.out.println(toString());//输出ID和NAME
}
@Override
public String toString() {//重写toString方法 方便后面进行输出
return "Person{" +
"ID=" + ID +
", NAME='" + NAME + '\'' +
'}';
}
}
1.首先运行main()方法在栈中创建出main()方法的栈帧
2.随后运行person p = new person();在堆中创建出地址为00X1的对象,并将对象赋值给P
3.通过P调用00X1对象中的ID和NAME变量给其赋值,NAME将值存放在字符串常量中
4.通过P调用00X1对象中的show()方法,方法执行时在栈中创建p.show()方法的栈帧,堆中00X1对象中的show()方法,到方法区中寻找show()方法并执行
5.程序执行完毕,p.show()的栈帧先退出栈,随后main()方法的栈帧退出栈,堆中的对象被删除