https://www.bilibili.com/video/BV1ct411n7oG?p=65该视频观看后的学习笔记
Java虚拟机的内存可以分为栈(stack)、堆(heap)和方法区(method area)这三个区域。
栈区域的特点:(关键字:私有、连续、速度快)
1.栈是描述方法执行的内存模型,每个方法调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)。
2.JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)。
3.栈属于线程私有,不能实现线程之间共享。
4.栈的存储特征是:“先进后出,后进先出”。
5.栈的由系统自动分配,速度快,而且是一个连续的内存空间。
堆区域的特点:(关键字:共享、不连续、速度慢)
1.堆用于存储创建好的对象和数组(数组也是对象)。
2.JVM只有一个堆,被所有线程共享。
3.堆是一个不连续的内存空间,分配灵活,速度慢。
方法区的特点:(关键字:也是堆)
1.JVM只一个方法区,被所有线程共享。
2.方法区实际也是堆,只是用于存储类、常量相关信息。
3.用来存储程序中永远不变或唯一的内容。(类信息、Class对象、静态变量、字符串常量等)。
下面使用一个表格总结上面的知识点:
栈 | 堆 | 方法区 | |
存储内容 | 线程执行方法的信息(实际参数、局部变量等) | 创建好的对象和数组 | 永远不变或唯一的内容(类信息、Class对象、静态变量、字符串常量等) |
是否线程共享 | 否 | 是 | 是 |
内存空间是否连续 | 是 | 否 | 否 |
数量 | 每个线程创建一个(一共多个) | JVM里只有一个 | JVM里只有一个 |
速度 | 快 | 慢 | 慢 |
package com.wen.javaTest;
public class Student {
private String name;
private int age;
private Computer computer;
public Student() {
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setComputer(Computer computer) {
this.computer = computer;
}
void Study(){
System.out.println(this.name+"正在努力学习");
}
void Blogging(){
System.out.println(this.name+"正在使用"+this.computer.Brand+"品牌电脑写博客");
}
public static void main(String[] args) {
Student student = new Student();
student.setName("WEN");
student.setAge(18);
Computer computer = new Computer("联想");
student.setComputer(computer);
student.Study();
student.Blogging();
}
}
class Computer{
String Brand;
public Computer(String brand) {
Brand = brand;
}
}
程序运行结果:
以上面的代码为例,理解内存结构:
通过上面的学习,已经了解到方法区是存放永远不变或唯一的内容(类信息、Class对象、静态变量、字符串常量等)。因此方法区里面包含上面代码中的字符串常量。而栈存放的是方法执行信息。因此代码的执行过程如下:
1.首先new出一个内存地址为1b6d3586的Student对象,这个对象是堆中的一个栈帧。然后通过set方法,将方法区的"WEN"字符串常量赋值到name属性中。
2.接着又创建了一个内存地址为3b6d3591的Computer空对象,该对象也是存储在堆中。接着通过Computer的构造方法将常量字符串中的“联想”赋值到brand属性中。
3.接着,将内存地址为3b6d3591的Computer对象赋值到到了student对象的computer属性中。
4.最后,在栈中调用student对象的Study方法和Blogging方法,程序运行结束。