Java虚拟机的内存可分为几个区域:栈stack、堆heap、方法区method area、程序计数器
Java虚拟机栈:
1. 栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)
2. JVM为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)
3. 栈属于线程私有,不能实现线程间的共享
4. 栈是由系统自动分配,速度快,栈是一个连续的内存空间
5. 两种异常:线程请求栈深度大于虚拟机所允许的深度,抛出StackOverflowError
如果虚拟机动态扩展时也无法申请到足够内存,抛出 OutOfMemoryError
Java堆:
1. 堆用于存储创建好的对象和数组(数组也是对象)
2. JVM只有一个堆,被所有线程共享
3. 堆是一个不连续的内存空间,分配灵活,速度慢
方法区:
1. JVM只有一个方法区,被所有线程共享
2. 方法区实际也是堆,只是用于存储类、常量相关的信息
3. 用来存放程序中永远是不变或唯一的内容。(类信息【Class对象】、静态变量、字符串常量等)
程序计数器:
是一块用于当做当前线程所执行的字节码的行号指示器的内存,通过改变计数器的值来选取下一条需要执行的字节码指令,java 的 jvm多线程是通过线程轮流切换并非配处理器执行时间来实现的,所以每个线程都都有一个独立的程序计数器,此区域没有outofmemoryerror异常情况。
直接内存和NIO类:
一种基于通道与缓冲区的I/O方式,使用Native函数库直接分配堆外内存,之后通过java堆中DirectByteBuffer对象作为这块内存的 引用来操作,避免Java堆和Native堆中来回复制数据,提高性能。
用一个简单例子 来简单说明:
/**
* 类内存分析
* @author 袁盛桐
*/
public class Student {
String name;
Computer computer;
void doSth()
{
System.out.println("coding");
}
public static void main(String[] args) {
Student student = new Student();
student.name = "yst";
student.doSth();
Computer com = new Computer();
com.style = "macbook air";
student.computer = com;
}
}
class Computer
{
String style;
}
新建一个student类
- 在方法区内把类内的代码,静态变量,静态方法和 类内所用的字符串都加载进堆内的方法区
- 找到类入口-main方法,在栈中入栈一个main()方法的栈帧
- 向下继续执行遇到new student()方法后,在栈中入栈一个student()方法栈帧
- 在堆中开辟一块内存空间表示student类,并把内存块地址赋给new出来的student对象
- 把“yst”赋值给student.name
- 向下执行,new computer(),步骤原理类似student类过程
- 当栈中栈针执行完成后会自动依次出栈直到所有栈空
- 按照 箭头,相互引用,类执行完成
下面是用windows自带画图软件画的示意图,比较粗糙大家见谅~