程序计数器:记录了方法之间的调用和执行情况,记住下一条jvm指令的执行地址。
每个线程都有一个计数器,是线程私有的。不会存在内存溢出。
栈:也叫栈内存,线程运行需要的内存空间。主管Java程序的运行,是在线程创建时创建,他的生命周期是跟随线程的生命周期,线程结束栈内存也会随之释放。对于栈来说不存在垃圾回收问题,只要线程结束该栈就释放了,是线程私有的。8种基本类型的变量 + 对象的引用变量 + 实例方法都是在函数的占内存中分配。
栈存储什么? 栈帧中主要保存 3 类数据 : (何为栈帧:即Java中的方法,只是在jvm中叫做栈帧)
- ① 本地变量 (Local Variables) : 入参和出参 以及方法内的变量;
- ② 栈操作 (Operand Stack) : 记录出栈 和 入栈的操作;(可理解为pc寄存器的指针)
- ③ 栈帧数据 (Frame Data) : 包括类文件、方法等。
栈的运行原理: 栈中的数据都是以栈帧 (Stack Frame) 的格式存在,栈帧是一个内存区块,是一个有关方法和运行期数据的数据集, 当一个方法A被调用时就产生了栈帧 F1,并被压入到栈中, A方法又调用 B方法,于是产生栈帧F2 ,也被压入栈, B方法又调用 C方法, 于是产生栈帧F3,也被压入栈 …… 执行完毕后,先弹出F3栈帧,再弹出 F2栈帧,再弹出 F1栈帧 …… 遵循 “先进后出” / “后进先出” 原则。
每个方法执行的同时都会创建一个栈帧,用于存储局部变量表,操作数据栈,动态连接、方法出口等信息,每一个方法从调用直至执行完毕的过程,就对应着一个栈帧在虚拟机中入栈到出栈的操作过程 栈的大小和具体jvm的实现有关,通常在 256K ~ 756K 之间,约等于 1Mb左右。
垃圾回收是否涉及栈内存?
不涉及。方法的调用产生栈帧,但当方法执行完毕后,栈帧都弹出了,并且线程结束后,栈内存都自动释放了。
栈内存分配越大越好吗?
栈内存默认分配的内存大小一般为1024KB。栈内存越大可能会导致你的线程数量变小,因为物理内存是固定的。
方法内的局部变量是否线程安全?
判断变量是被线程共享的还是线程私有的。因为是局部变量,每个线程都有这个变量,因此是线程安全的。static静态变量则可能会导致线程安全问题。
栈帧过多。(调用方法过多-方法的递归没有设置结束)
栈帧过大。
通过new关键字,创建对象都会使用到堆内存。
线程共享,堆中对象都需要考虑线程安全的问题。
有垃圾回收机制。
供各线程共享的运行时内存区域。存储了每一个类的结构信息,包括运行时常量池、构造方法、方法数据等。虚拟机启动时创建。
方法区就是一个规范,在不同的虚拟机里实现是不一样的,最典型的就是 永久代(PermGen space) 和 元空间 (Metaspace)
永久代:JDK1.7 元空间:JDK1.8
原文:https://www.cnblogs.com/xxc-Blog/p/12469756.html