参考视频
JVM架构总览图
程序计数器
程序计数器,物理上用寄存器实现。
作用: 记住下一条JVM指令的执行地址
栈
介绍
栈:程序运行需要的内存空间
虚拟机栈: 每个线程运行时所需要的内存
数据结构:先进(压栈)后出(出栈)
一个栈可以看成多个栈帧组成,每个栈帧可以看成每个方法的运行时需要的内存(参数,局部变量,返回地址等)
栈内存溢出
- 栈帧过多,即调用的方法过多,最容易产生的:递归调用(测试2w多次递归会报错)
- 栈帧过大,不太容易出现
本地方法栈(native method stacks)
不是由java代码编写的方法,java用本地方法调用底层的c或c++使用的方法
给本地的方法的运行提供内存空间
线程私有
堆(Heap)
介绍
通过new关键字,创建对象都会使用堆内存
特点:
- 它是线程共享的,堆中对象都需要考虑线程安全问题
- 有垃圾回收机制
堆内存溢出
方法区
定义
方法区是一个逻辑上的概念,也被称为非堆(Non-Heap),一般用来存储类加载信息、static变量、JIT实时编译缓存的代码、常量池(Constants Pool)等。不同版本的Java其方法区的实现方式不同,在JDK 8之前,采用的是“永久代”来实现方法区,而在JDK 8之后则是采用MetaSpace(元空间)的方式来实现
- 共享性: 方法区与Java堆一样,是各个线程共享的内存区域。
- 创建和内存空间: 方法区在JVM启动时被创建,实际的物理内存空间和Java堆一样,可以是不连续的。
- 大小和可扩展性: 方法区的大小,就像堆空间一样,可以选择固定大小或可扩展。
- 溢出问题: 方法区的大小决定了系统能够保存多少个类。如果系统定义了太多的类,导致方法区溢出,虚拟机将抛出内存溢出错误,例如
java.lang.OutOfMemoryError: PermGen space
或java.lang.OutOfMemoryError: Metaspace
。 - 释放: 关闭JVM将释放方法区的内存空间。
方法区是用于存储类信息、常量池、静态变量等数据的区域,对于Java虚拟机的正常运行和类加载等都具有重要作用。
jdk8之后 字符串常量和静态变量移到堆中
参考文档:【JVM系列】运行时Java类的内存营地——方法区详解 - 知乎