JVM学习1:程序计数器、栈

JVM

JVM、JRE、JDK区别

在这里插入图片描述

JVM的作用

面试

理解底层的实现原理:字节码等等

中高级程序员的必备技能

JVM学习路线

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LQWo5Uow-1631876420437)(C:\\Users\\逍遥\\AppData\\Roaming\\Typora\\typora-user-images\\image-20210914123953145.png)\]

程序计数器

Program Counter Register程序计数器(寄存器)

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EowtFlZp-1631876420442)(JVM.assets/image-20210914234554707.png)\]

左边的是二进制字节码,这是跨平台的基础,都是jvm的指令。

还必须经过解释器,变成机器码,然后交给了CPU进行处理。

作用:

程序计数器的作用就是:记住下一条jvm指令 的执行地址。

等第一条指令在解释器解释完之后,3会放入到程序计数器中,解释器就会进去取,然后执行。就是记住下一条jvm指令的执行地址。

物理上,是通过寄存器实现的。寄存器是整个cpu里读取指令速度较快的。读取指令是非常频繁的,所以jvm中就把寄存器当做了程序计数器,进行jvm指令的执行地址的存放。

特点:

1、线程是私有的。

多个线程运行的时候,cpu会有一个调度器组件分配时间片,给线程1分配时间片,如果线程1没有执行完,就会把线程1 的状态暂存然后转到线程2去,开始执行线程2,然后等到线程2的时间片用完了,就开始转回到线程1去。如果恰好线程1执行到10(下一个要10,)记录到了程序计数器里面,要搞清楚程序计数器是私有的,是只属于线程1的,等开始转到线程2之后,就开始运行2的,然后转回1之后,就知道要开始运行10了,每个线程都有自己的程序计数器。

2、唯一一个不会存在内存溢出的区。

其他的一些区,堆栈、方法区等可能会存在内存溢出,而程序计数器不会存在内存溢出问题。

JVM Stacks 虚拟机栈

栈的概念就是类似弹夹,先进后出。

java中线程运行的时候,线程需要栈。栈:线程运行需要的内存空间。

栈是由栈帧组成。一个栈帧就对应一个方法的调用。

每个方法运行时需要的内存就是栈帧。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kMnK0mVV-1631876420447)(JVM.assets/image-20210915000246970.png)\]

方法运行需要的内存:参数、局部变量、返回地址。都是需要占用内存的,所以每次方法运行时,需要预先分配好。

如果调用第一段方法时,把栈帧1放入,栈帧1调用了方法2(栈帧2,)然后栈帧2就放入了栈内。然后以此类推等到所有的调用都结束了,所有的栈帧都逐步出去。

定义

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-db0HymYx-1631876420450)(JVM.assets/image-20210915000626189.png)\]
在这里插入图片描述

问题辨析:线程安全

1、垃圾回收是否涉及栈内存。

不涉及,垃圾回收只涉及堆内存。

2、栈内存分配越大越好吗?

不是,如果大了,会影响线程的数量,因为物理内存是有限的。

3、方法内的局部变量是否线程安全?

是。要观察这个线程是否对每个变量是否是私有的。局部变量是私有的。但如果把变量改成static成为了共享的就需要考虑线程安全,是私有的就不需要考虑线程安全。

一个线程对应一个栈,不同的线程会产生不同的栈帧,所以是安全的。

相当于每个线程都有自己的私有的栈帧。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UIWHdfKD-1631876420455)(JVM.assets/image-20210915162552896.png)\]

这个sb是作为参数传进来,可能会有不同的线程同时在使用这个sb,已经不再是私有的了,所以要改掉。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Myx8DTwQ-1631876420457)(JVM.assets/image-20210915162644417.png)\]

这个sb虽然是局部变量,但是是返回了sb,所以可能会被其他线程并发的执行,所以总的来说,要看一个变量是不是线程安全的,那么就要看清楚是不是逃离了这个方法的作用范围,如果逃离了就不是线程安全的了。方法内局部变量始终在方法内的话,就是线程安全的。

问题辨析:栈内存溢出

第一种情况是:栈帧过多导致栈内存溢出。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ff60DEpS-1631876420458)(JVM.assets/image-20210915163200179.png)\]

方法递归调用没有设置正确的一个调用条件,就容易栈内内存溢出。

第二种情况是栈帧过大导致栈内存溢出。但这种情况比较少出现,一般是栈帧过多导致内存溢出。

错误名字是 stackoverflow。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XZcWVOf5-1631876420460)(JVM.assets/image-20210915174340093.png)\]

可以提前设置好栈的总大小空间。

线程运行诊断

1、CPU占用过多。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b0TlsgUS-1631876420462)(JVM.assets/image-20210916001814956.png)\]

2、程序运行很长时间没有结果

发表评论

表情:
评论列表 (有 0 条评论,69人围观)

还没有评论,来说两句吧...

相关阅读

    相关 jvm程序计数器

    在Java虚拟机(JVM)中,程序计数器(PC寄存器)是一块较小的内存空间,它用于存储当前线程正在执行的Java字节码的指令地址。程序计数器是线程私有的,每个线程都有自己...

    相关 JVM_程序计数器详解

    1、内存管理 2 、运行时数据区域内容 > Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。根据《Java虚拟机规范》的规定,