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

简介: 面试理解底层的实现原理:字节码等等中高级程序员的必备技能

JVM


JVM、JRE、JDK区别

5954921c2268929dda43c25adfb5a8ae_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_14,color_FFFFFF,t_70,g_se,x_16.png


JVM的作用

面试


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


中高级程序员的必备技能


JVM学习路线

44b747c187fadce6f74eb051bd9d03ec_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_13,color_FFFFFF,t_70,g_se,x_16.png


程序计数器

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


cf57de11a64d6392e90375218f8890ee_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_13,color_FFFFFF,t_70,g_se,x_16.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中线程运行的时候,线程需要栈。栈:线程运行需要的内存空间。


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


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

7cb4574579ede320dd85a94f649102bd_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_13,color_FFFFFF,t_70,g_se,x_16.png

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


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


定义

9fdd45f43fbb8553162a6e88e81380d0_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_14,color_FFFFFF,t_70,g_se,x_16.png

问题辨析:线程安全

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


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


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


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


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


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


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


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

a34704834190d414f2cc05a13bc79171_7b4ffaa1a883446cac3ad01bb01e40d4.png


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


83b73af7903d484ed1709c2171df90a7_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_14,color_FFFFFF,t_70,g_se,x_16.png


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


问题辨析:栈内存溢出

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

49f04ddd447c204c013b136acf825655_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_8,color_FFFFFF,t_70,g_se,x_16.png


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


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


错误名字是 stackoverflow。


58df22cf7dfa5c8bb8a29264be88b8b4_watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA572R5LqL6ZqP6aOOMjAxNw==,size_13,color_FFFFFF,t_70,g_se,x_16.png


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


线程运行诊断

1、CPU占用过多。


14aed8661af802782fb70cfffc50f862_14a15e6bc2c8417d869713d591f2b5d3.png


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


相关文章
|
3天前
|
缓存 Java
《JVM由浅入深学习九】 2024-01-15》JVM由简入深学习提升分(生产项目内存飙升分析)
《JVM由浅入深学习九】 2024-01-15》JVM由简入深学习提升分(生产项目内存飙升分析)
10 0
|
3天前
|
存储 缓存 NoSQL
Redis系列学习文章分享---第十三篇(Redis多级缓存--JVM进程缓存+Lua语法)
Redis系列学习文章分享---第十三篇(Redis多级缓存--JVM进程缓存+Lua语法)
8 1
|
7天前
|
存储 Java C++
Java虚拟机(JVM)在执行Java程序时,会将其管理的内存划分为几个不同的区域
【6月更文挑战第24天】Java JVM管理内存分7区:程序计数器记录线程执行位置;虚拟机栈处理方法调用,每个线程有独立栈;本地方法栈服务native方法;Java堆存储所有对象实例,垃圾回收管理;方法区(在Java 8后变为元空间)存储类信息;运行时常量池存储常量;直接内存不属于JVM规范,通过`java.nio`手动管理,不受GC直接影响。
17 5
|
7天前
|
存储 Java C++
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据,如局部变量和操作数;本地方法栈支持native方法;堆存放所有线程的对象实例,由垃圾回收管理;方法区(在Java 8后变为元空间)存储类信息和常量;运行时常量池是方法区一部分,保存符号引用和常量;直接内存非JVM规范定义,手动管理,通过Buffer类使用。Java 8后,永久代被元空间取代,G1成为默认GC。
18 2
|
11天前
|
监控 算法 Java
Java虚拟机(JVM)使用多种垃圾回收算法来管理内存,以确保程序运行时不会因为内存不足而崩溃。
【6月更文挑战第20天】Java JVM运用多种GC算法,如标记-清除、复制、标记-压缩、分代收集、增量收集、并行收集和并发标记,以自动化内存管理,防止因内存耗尽导致的程序崩溃。这些算法各有优劣,适应不同的性能和资源需求。垃圾回收旨在避免手动内存管理,简化编程。当遇到内存泄漏,可以借助VisualVM、JConsole或MAT等工具监测内存、生成堆转储,分析引用链并定位泄漏源,从而解决问题。
24 4
|
18天前
|
存储 缓存 安全
JVM(三)-运行时数据区(栈、程序计数器)
JVM(三)-运行时数据区(栈、程序计数器)
13 2
|
3天前
|
算法 Java
《JVM由浅入深学习【八】 2024-01-12》JVM由简入深学习提升分(JVM的垃圾回收算法)
《JVM由浅入深学习【八】 2024-01-12》JVM由简入深学习提升分(JVM的垃圾回收算法)
5 0
|
3天前
|
算法 Java Apache
《JVM由浅入深学习【七】 2024-01-11》JVM由简入深学习提升分享
《JVM由浅入深学习【七】 2024-01-11》JVM由简入深学习提升分享
6 0
|
3天前
|
存储 Java 开发者
《JVM由浅入深学习【六】 2024-01-10》JVM由简入深学习提升分享
《JVM由浅入深学习【六】 2024-01-10》JVM由简入深学习提升分享
4 0
|
3天前
|
缓存 Java
《JVM由浅入深学习【五】 2024-01-08》JVM由简入深学习提升分享
《JVM由浅入深学习【五】 2024-01-08》JVM由简入深学习提升分享
4 0