JVM(HostPort)
内存结构
-
Method Area 方法区
-
Heap 堆
-
JVM Stacks 虚拟机栈
-
PC Register 程序计数器
-
Native Method Stacks 本地方法栈
执行引擎
-
interpreter 解释器
-
JIT Compiler 即时编译器
-
GC 垃圾回收
JVM内存结构和执行引擎可以通过本地方法接口进行互通
程序计数器(寄存器-整个cpu读取速度最快的)
java源代码翻译成二进制字节码(JVM指令),通过解释器将指令翻译成机器码,然后将机器码交给CPU执行
记录下一条jvm指令的执行地址
特点
-
是线程私有的(每个线程都有自己专属的程序计数器)
-
在java虚拟机中,唯一一个不存在内存溢出
虚拟机栈
先进后出,后进先出
线程运行需要的内存空间,多个线程运行会有多个栈
将数据放入栈内,称之为压栈
将数据从栈内拿出,称之为出栈(弹栈)
每个栈内由多个栈帧组成的,
为什么栈要采用先进后出,后进先出的队列?
因为方法的调用存在嵌套关系,只有当内层的方法执行完毕后,释放线程中的栈内存空间之后,将对应的栈帧出栈,才可以结束内层方法的外层方法,才可以将内层方法对应的栈帧下的栈帧出栈.
栈帧:每个方法运行时需要的内存,内部存储参数,局部变量,返回地址
定义:
-
每个线程运行时所需要的内存,称之为虚拟机栈
-
每个栈由多个栈帧(Frame)组成,对应这每次方法调用时所占用的内存
-
每个线程只能有一个活动栈帧(栈内最顶部的栈帧,正在执行的方法所对应的栈帧),对应着当前正在执行的那个方法
问题
-
垃圾回收是否涉及栈内存?
不需要,因为栈内存只是存放内次方法调用时候所需要的内存空间,随着方法的调用完毕,对应的内存空间栈帧会被出栈,会被自动的回收,所以不需要垃圾回收器来管理栈内存
-
栈内存分配越大越好?
-Xss size对栈内存分配大小的指令
如果不指定的情况下,linux默认是1024kb,macOS默认是1024kb,Oracle Solaris默认是1024kb,windows系统是根据windows虚拟内存决定栈的大小
栈内存是每个线程都都有的一份空间,当线程执行的时候,都会为其指定创建栈内存,如果栈内存空间过大,在内存大小固定的情况下,会导致内存可以容纳的线程数量减少,从而影响效率,栈内存扩大,只是可以进行更多次的递归方法调用,而不会增加执行的效率,反而影响线程的数量
-
方法内的局部变量是否线程安全?
首先查看线程内的局部变量是否为多个线程共享的还是这个变量对每个线程都是私有的,当每个线程访问这个方法时,对应的栈帧都会为其创建一个栈空间,栈帧内存放的数据都是这个方法独有的局部变量,所以方法内的局部变量是线程安全的,而被static所修饰,则是线程不安全的
方法的形参,是线程不安全的,因为他不是线程的局部变量,因为他作为形参的时候,其他线程也可以使用,自己线程也可以使用,所以就成了线程不安全的
如果方法内的局部变量被作为返回值返回,那么证明他也可以被其他线程访问,所以也是线程不安全的
如果方法内局部变量没有逃离方法的作用范围,他是线程安全的
如果局部变量引用了对象,并逃离了方法的作用范围,需要考虑线程安全
栈内存溢出(StackOverflowError) --->第十三集
栈帧过多导致栈内存溢出
栈帧过大导致栈内存溢出