本地库接口是操作系统实现的,对应的栈就是本地方法栈
方法区
- 方法区被所有线程共享
- 存储已被虚拟机加载的 类信息 、 常量 (final)、 静态变量 (static)、(构造方法、接口信息)等数据
- 垃圾收集行为在这个区域比较少出现,回收目标主要是针对常量池的回收和对类型的卸载
- 运行时常量池 是方法区的一部分,用于存放 编译期 生成的各种 字面量和符号引用 ,这部分内容在 类加载后 存放到运行时常量池。
PC Register 程序计数器
每个线程都有一个程序计数器,就是一个指针,指向方法区中的方法字节码(下一个要执行的指令代码)
本地方法栈
Native方法的栈
八字箴言:栈管运行,堆管存储
虚拟机栈
当一个方法被调用时就产生了一个栈帧,并被压入到栈中
- 线程私有
- 生命周期和线程相同
- 基本类型变量 (boolean,byte,char,int....)和 对象的引用变量 (引用指针或句柄) 在栈内存中分配(简单理解就是在方法里定义的各种局部变量,自定义类的变量只有指针)
- 栈中存储的是栈帧(对应一个方法), 栈帧保存了 :
1). 本地变量 (输入/输出参数,方法内定义的局部变量)
2). 栈操作(记录出栈、入栈的操作)(以及动态链接、方法出口)
- 局部变量所需要的内存在 编译期间 完成分配
堆内存
堆内存示意图
实例化对象的产生到消亡发生在新生区
新生区又分为两部分:
- Eden Space, 所有的新生对象在这里产生
- Survivor 0 , Survior 1;
- 当Eden Space 用完的时候,程序又需要创建新对象,JVM 垃圾回收器将对Eden Space 进行 Minor GC :将 不再被其他对象引用的对象销毁 ,然后将Eden中 剩余的对象移动到 Survior 0 中。
- 如果Survior 0 也满了, 再对该区进行垃圾回收,然后移动到Survior 1区
- 同样的,如果Survior 1 区也满了,将会把剩余的对象移到老年代。 如果老年代也满了 ,则会发生 Major GC (Full GC) ,对老年代的内存进行清理。如果老年代经过GC后仍无法保存对象,就会产生OOM。
注:
如果出现 OOM :Java heap space的错误,说明JVM的堆内存不够,原因有两点:
(1).堆内存设置的不够大,默认最大是机器内存的1/4,可以通过参数-Xms(初始内存), -Xmx(最大内存)
(2). 代码中创建了大量的大对象,并长时间不能被垃圾收集器收集
可以new出一个很大的对象,这个对象大小需要小于机器最大内存,并调整JVM参数
老年代
用于保存从新生代筛选出的Java对象,一般池对象(如jdbc连接池)都在这个区域活跃,很少发生GC
永久代
- 没有垃圾回收,关闭JVM才会释放所占用的内存
- 常驻内存
- 用于存放JDK自身所携带的Class,Interface的元数据(或者说是存储的是运行环境所必须的类信息)
如果出现 OOM:PermGen space
JAVA7永久代 === JAVA8 元空间
原文
https://segmentfault.com/a/1190000022353721