【JVM】JVM之执行引擎

文章目录

  • 一、前言
  • 二、名词解释
    • 机器码
    • 指令
    • 指令集
    • 汇编语言
    • 高级语言
    • 字节码
    • 虚拟机&物理机
    • 前端编译器&后端编译器
  • 三、JVM之执行引擎
    • 执行引擎是如何工作的?
    • 解释器
    • 即时编译器(JIT)
    • 分层编译策略
    • 虚拟机执行模式
    • 热点代码&探测方式
      • 1)方法调用计数器
      • 2) 回边计数器
    • Graal编译器&AOT编译器

一、前言

本文我们将讲解JVM中的执行引擎。

问题:我们平时所写的Java程序是如何将其进行编译并转换为计算机能够识别的机器码呢?并且Java程序编译和C/C++程序编译有什么区别呢?我们所说的JIT编译器和平时说的编译器有什么区别呢?…我相信在阅读本文过后,你会有一个清楚的认识的。

  • Java的[前端]编译只会生成字节码文件,而不会生成汇编(更不会到机器语言)。Java程序运行时,字节码文件会装载入java虚拟机,虚拟机将字节码“翻译”成机器指令来运行。java在不同平台上实现虚拟机,针对虚拟机编译就可以实现代码可移植性。
    在这里插入图片描述

  • C/C++程序编译执行过程简单来说,整个过程分为四个阶段:预处理(Pre-Processing)、编译(Compilation)、汇编(Assembling)、链接(Linking)。C/C++语言程序编译成的是机器码,通常不能在不同指令系统的机器上运行。C/C++程序的编译一般是直接针对硬件的。

在这里插入图片描述

二、名词解释

机器码

  • 定义:各种用二进制编码方式表示的指令,叫做机器指令码。

  • 特点

    • 能够被计算机理解和接受,其编写的程序输入到计算机中,CPU可直接读取运行,因此执行速度是最快的;
    • 其与CPU紧密相关,不同类型的CPU对应的机器码也不同;

指令

由于机器码是有0和1组成的二进制序列,可读性太差,于是指令出现了。

  • 定义:指令就是把机器码中特定的0和1序列,简化成相应的指令(一般使用英文简写,如mov,inc等),告诉计算机从事某一特殊运算的代码。如:数据传送指令、算术运算指令、位运算指令、程序流程控制指令、串操作指令、处理器控制指令。

  • 组成形式
    一条指令通常由两个部分组成:操作码+地址码。

    • 操作码:指明该指令要完成的操作的类型或性质,如取数、做加法或输出数据等。
    • 地址码:指明操作对象的内容或所在的存储单元地址。
  • 特点

    • 指令是计算机运行的最小的功能单位
    • 不同的硬件平台的同一种指令(比如mov),对应的机器码也可能不同。

指令集

  • 定义:一台计算机上全部指令的集合,就是这台计算机的指令系统。指令系统也称指令集,是这台计算机全部功能的体现。

  • 特点

    • 不同的硬件平台,各自支持的指令,是有差别的。因此每个平台所支持的指令,称之为对应平台的指令集。

    • 如常见的

      • x86指令集,对应的是x86架构的平台
      • ARM指令集,对应的是ARM架构的平台

汇编语言

  • 概念:汇编语言是一种低级语言,亦称为符号语言。在汇编语言中,用助记符代替机器指令的操作码,用地址符号或标号代替指令或操作数的地址。

  • 特点

    • 在不同的硬件平台中,汇编语言对应着不同的机器语言指令集,通过汇编过程转换成机器指令。
    • 由于计算机只认识指令码,所以用汇编语言编写的程序还必须翻译成机器指令码,计算机才能识别和执行。

高级语言

  • 概念:高级语言是一种独立于机器,面向过程或对象的语言。

  • 特点

    • 用人们更易理解的方式编写程序,编写的程序称之为源程序。
    • 高级语言与计算机的硬件结构及指令系统无关,它有更强的表达能力,可方便地表示数据的运算和程序的控制结构,能更好的描述各种算法,而且容易学习掌握。
    • 当计算机执行高级语言编写程序的时候,仍然需要将程序解释和编译成机器的指令码。完成这个过程的程序就叫做解释程序或者编译程序。

字节码

  • 概念:字节码是一种特殊状态【中间码】的二进制代码文件,比机器码更抽象,需要转译后才能形成机器码。

  • 特点

    • 字节码主要为了实现特定软件运行和软件环境、与硬件环境无关→【跨平台】
    • 字节码的实现方式是通过编译器和虚拟机器。编译器将源码编译成字节码,特定平台上的虚拟机器将字节码转译为可以直接执行的指令。

字节码典型的应用为:Java bytecode

虚拟机&物理机

“虚拟机”是一个相对于“物理机”的概念,这两种机器都有代码执行的能力。

  • 区别:

    • 物理机的执行引擎是建立在处理器、缓存、指令集和操作系统层面上的。
    • 虚拟机的执行引擎则是由软件自行实现的,因此可以不受物理条件的制约指令集和执行引擎的结构体系,能够执行那些不被硬件直接支持的指令集格式。

前端编译器&后端编译器

前端编译器:把*.java文件转变成*.class文件的过程。
后端编译器:把Class文件转换成与本地基础设施(硬件指令集、操作系统)相关的二进制机器码的过程。

三、JVM之执行引擎

执行引擎是Java虚拟机核心组件之一,由于字节码并不能够直接运行在操作系统之上(字节码指令并非等价于本地机器指令,它内部包含的仅仅只是一些能够被JVM所识别的字节码指令、符号表、以及其他信息),因此JVM将字节码加载到其内部之后,执行引擎(Execution Engine)的任务就是将字节码指令解释/编译为对应平台的本地机器指令,简单来说JVM的执行引擎充当了高级语言翻译为机器语言的译者。

执行引擎是如何工作的?

  1. 执行引擎在执行的过程中究竟需要执行什么样的字节码指令完全依赖于PC寄存器;
  2. 每当执行完一项指令操作之后,PC寄存器就会更新下一条需要被执行的指令的地址;
  3. 当然方法在执行的过程中,执行引擎可能会通过存储在局部变量表中的对象引用准确定位到存储在Java堆区中的对象的实例信息,以及通过对象头中的元数据指针定位到目标对象的类型信息;

在这里插入图片描述

JVM执行引擎具体流程图如下图所示

在这里插入图片描述

  • Java虚拟机的执行引擎的输入、输出都是一致的
    输入:字节码二进制流;
    输出:解释器和编译器将字节码”翻译“后的机器指令;

提出问题:为什么说Java是半编译半解释型语言?你会在下面的内容中找到对应的答案

在这里插入图片描述

解释器

  • 概念:当Java虚拟机启动的时候会根据预定义的规范对字节码采用逐行解释的方式执行,将每条字节码文件中的内容“翻译”为对应平台的本地机器指令执行。(一行一行解释字节码指令,立即执行,不需要编译)

  • 如何工作

    • 当一条字节码指令被解释执行完成之后,接着再根据PC寄存器中记录的下一条需要被执行的字节码指令执行解释操作。

    • 在Hotspot VM中,解释器主要由Interpreter模块和Code模块构成

    • Interpreter模块:实现了解释器的核心功能

    • Code模块:用于管理Hotspot VM 在运行时生成的本地机器指令

由于解释器在设计上和实现上非常简单,如今基于解释器执行已经是低效的代名词。为了解决这个问题,即时编译技术出现了。

即时编译器(JIT)

Java语言的“编译器”在没有具体上下文语境的话,是一个很模糊的概念,因为它可能是指

  • 前端编译器(其实也叫 编译器的前端):把 .java 文件转换成 .class 文件的过程

  • 后端编译器(JIT编译器 Just In Time Compiler) :把字节码转换为机器码的过程

  • 静态提前编译器(AOT编译器 Ahead Of Time Compiler):直接把 .java 文件编译成本地机器码的过程

而JVM执行引擎中的即时编译器是属于后端编译器,因此下面我们主要以讲解即时编译器为主。
Hotspot虚拟机采用解释器和即时编译器并存的架构,在其运行的时候,会找到解释器和即时编译器相互合作的节点。基于这个特点,Java的运行性能已经可以和C/C++程序一教高下的地步。

问题来了: 既然Hotspot VM中已经内置了JIT编译器了,那么为啥还需要再使用解释器来“拖累”程序的执行性能呢?

解释器与编译器两者各有优势

  • 当程序需要迅速启动和执行的时候,解释器可以首先发挥作用【响应快】,不必等待即时编译器全部编译完再执行,可以立即运行。

  • 当程序启动后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译为本地代码,这需要一定的时间。但是编译为本地代码后,执行效率高。

综上所述,解释器还可以作为编译器激进优化时后备的“逃生门”,即让编译器根据概率选择一些不能保证所有情况都正确,但大多数时候都能提升运行速度的优化手段,当激进优化的假设不成立时(比如加在了新类以后,类型继承结构出现变化等)可以通过逆优化退回到解释状态继续执行,因此二者经常是相辅相成地配合工作。交互关系如下所示
在这里插入图片描述

HotSpot虚拟机内置了两个(或三个)即时编译器。

  • Client Compiler(客户端编译器/C1编译器)

    • C1编译器会对字节码进行简单和可靠的优化,耗时短以达到更快的编译速度
  • Server Compiler(服务端编译器/C2编译器)

    • C2进行耗时较长的优化,以及激进优化 ,但是优化的代码执行效率高。
  • Graal编译器:JDK10才出现的,目的是代替C2,这里不予讲解。

C1和C2编译器不同的优化策略

  • C1编译器有方法内联,去虚拟化、冗余消除

    • 方法内联:将引用的函数代码编译到引用点处,这样就可减少栈帧的生成,减少参数的传递和跳转过程
    • 去虚拟化:对唯一的实现类进行内联
    • 冗余消除:在运行期间会把一些不会执行的代码折叠掉
  • C2的优化主要是在全局层面,逃逸分析师优化的基础,基于逃逸分析在C2上有如下几种优化

    • 标量替换:用标量替换聚合变量
    • 栈上分配:对于为逃逸的对象分配对象的在栈而不是在堆
    • 同步消除:清除同步动作,通常指的是synchronized

注意:64位版本的JDK只支持"-server"模式,其它版本JDK,用户可以使用"-client"或"-server"参数强制指定虚拟机运行在客户端模式还是服务端模式。

  • 程序解释执行(不开启性能监控)可以触发C1,将字节码编译成机器码,可以进行简单优化,也可加上性能优化,C2编译会根据性能监控信息进行激进优化
  • 不过在Java7版本之后,一旦开发人员在程序中显示指定命令 "-server"时,默认开启,使用c1和c2共同执行

分层编译策略

分层编译工作模式出现以前,HotSpot虚拟机通常是采用解释器和其中一个编译器直接搭配的方式工作。为了在程序启动响应速度与运行效率之间达到最佳平衡,HotSpot虚拟机在编译子系统中加入了分层编译策略:

  • 第 0 层:程序解释执行,默认开启性能监控功能(Profiling),如果不开启,可触发第二层编译;
  • 第 1 层:可称为 C1 编译,将字节码编译为本地代码,进行简单、可靠的优化,不开启 Profiling;
  • 第 2 层:也称为 C1 编译,开启 Profiling,仅执行带方法调用次数和循环回边执行次数 profiling 的 C1 编译;
  • 第 3 层:也称为 C1 编译,执行所有带 Profiling 的 C1 编译;
  • 第 4 层:可称为 C2 编译,也是将字节码编译为本地代码,但是会启用一些编译耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化。

虚拟机执行模式

缺省情况下 Hotspot 虚拟机使用解释器与编译器并存的架构,开发人员也可以对其进行调整,设置为完全采用解释器或者完全采用即时编译器。

  • -Xint:完全采用解释器模式执行程序
  • -Xcomp:完全采用即时编译器模式执行程序,如果编译出现问题,解释器仍然会介入
  • -Xmixed:采用解释器+即时编译器混合模式执行程序
C:\Users\13832>java -version
java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode)

C:\Users\13832>java -Xint -version
java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, interpreted mode)

C:\Users\13832>java -Xcomp -version
java version "1.8.0_162"
Java(TM) SE Runtime Environment (build 1.8.0_162-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, compiled mode)

上面提到了热点代码,什么是热点代码?如何确定代码是热点代码的呢?请继续向下阅读。

热点代码&探测方式

JIT编译器需要根据字节码执行的频率来确定是否要将字节码编译成本地机器指令,执行频率较高的代码就称为热点代码,JIT编译器就针对这些执行频率较高的代码进行深度优化,编译成本地机器指令,在下次执行时就不用再使用解释器解释了,而是直接执行本地机器指令,进而提升JAVA性能。
热点代码主要有两类:

  • 被多次调用的方法
  • 被多次执行的循环体

对于这两种情况,编译的目标对象都是整个方法体。由于这种编译方式发生在方法的执行过程中,因此也被称为栈上替换。或者简称为 OSR(On Stack Replacement),即方法的栈帧还在栈上,方法就被替换了。
上面的描述中,一个方法究竟要调用多少次,或者一个循环体究竟循环多少次,才会达到这个标准?这就依赖热点探测功能(目的是确定某段代码是不是热点代码,是不是需要触发即时编译)。
主流的热点探测判定方式有两种,分别是:

  • 基于采样的热点探测:虚拟机会周期性地检查各个线程地调用栈顶,如果发现某个(或某些)方法经常出现在栈顶,那么该方法即为“热点方法”。这种方法实现简单高效,但很难精确地确认一个方法地热度。
  • 基于计数器的热点探测:虚拟机会为每个方法(甚至是代码块)建立计数器,统计方法的执行次数,如果执行次数超过一定的阈值就认为它是“热点方法”。【HotSpot虚拟机使用的方式】

采用计数器的热点探测,Hotspot VM 将会为每一个方法都建立2个不同类型的计数器,分别为方法调用计数器(Invocation Counter)和回边计数器(Back Edge Counter)

  • 方法调用计数器用于统计方法被调用的次数
  • 回边计数器则用于统计循环体执行的循环次数

1)方法调用计数器

  • 这个计数器就是用于统计方法被调用的次数,它的默认阈值再 Client 模式下是1500次,再Server下是10000次,超过这个阈值,就会触发JIT编译。这个阈值可以通过虚拟机参数 -XX:ComplieThreshold 来设定
  • 当一个方法被调用的时候,会先检查该方法是否存在被JIT编译过的版本,如果存在,则优先使用编译后的本地代码来执行;如果不存在已经被编译的版本,则将此方法的调用计数器值加1,然后判断方法调用计数器和回边调用计数器之和是否超过方法调用计数器的阈值,如果超过,就向编译器提交一个该方法的编译请求

热度衰减概念:方法调用计数器统计的不是被调用的绝对次数,而是一个相对的执行频率。即一段时间之内方法被调用的次数。当超过一定的时间限制,如果方法调用的次数不足以将它转交给即时编译器编译,那这个方法的调用计数器就会减少一半,这个过程就是调用计数器热度的衰减(Counter Decay),而这段时间就称为次方法统计的半衰周期(Counter Half Life Time)。
进行热度衰减的动作,是在虚拟机内部垃圾收集的时候顺便执行的,可以使用虚拟机参数 -XX:-UseCouinterDecay关闭热度衰减,这样只要系统运行时间足够长,程序中绝大部分方法都会被编译成本地代码。

  • 可以使用 -XX:CounterHalfLifeTime 参数设置半衰周期的时间,单位是秒。

在这里插入图片描述

2) 回边计数器

  • 统计方法中循环体代码的执行次数,建立回边计数器统计就是为了触发栈上的替换编译。
  • 当解释器遇到一条回边指令时,会先查找将要执行的代码片段是否有已经编译好的版本,如果有的话,将会优先执行已编译的代码,否则就把回边计数器的值加1,然后判断方法调用计数器与回边计数器值之和是否超过回边计数器的阈值。超过阈值的话,将会提交一个栈上替换编译请求,并把回边计数器的值降低一些。

在这里插入图片描述

代码演示

public class IntCompTest {
    public static void main(String[] args) {

        long start = System.currentTimeMillis();

        testPrimeNumber(1000000);

        long end = System.currentTimeMillis();

        System.out.println("花费的时间为:" + (end - start) + "ms");

    }

    public static void testPrimeNumber(int count){
        for (int i = 0; i < count; i++) {
            //计算100以内的质数
            label:for(int j = 2;j <= 100;j++){
                for(int k = 2;k <= Math.sqrt(j);k++){
                    if(j % k == 0){
                        continue label;
                    }
                }
            }

        }
    }
}

-Xint[纯解释器]:花费的时间为:6184ms
-Xcomp[纯编译器]:花费的时间为:746ms
-Xmixed[默认]:花费的时间为:710ms

Graal编译器&AOT编译器

Graal编译器

  • 在JDK10之后,Hotspot又加入了一个全新的即时编译器:Graal 编译器,目标是在未来替代C2编译器

  • 目前还在实验阶段

    • -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler去激活才能使用

AOT编译器

  • JDK9.0之后加入了AOT编译器(静态提前编译器 Ahead Of Time Compiler)

  • 所谓的AOT编译器时与即时编译器对立的一个概念,即时编译器在程序运行的时候,而AOT编译器是在程序运行之前,便将字节码转换为机器码。

  • 好处:

    • 可以直接执行,不必等程序预热,减少第一次运行慢的体验
  • 缺点:

    • 破坏了Java”一次编译,到处运行“,因为直接编译之后的文件是固定的,必须为每种系统都编译
    • 降低了Java动态链接的动态性,加载的代码在编译器期就必须全部已知
    • 还需要继续优化中,最初只支持Linux x64 java base

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/10639.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何在 Linux 中使用 Chage 命令,修改Linux系统用户密码更改策略

Chage是一个用于修改Linux系统用户密码更改策略的命令行工具。在本文中&#xff0c;我们将介绍如何在Linux系统中使用Chage命令。 检查用户密码过期信息 使用Chage命令可以检查用户密码更改策略和过期信息。要检查特定用户的密码过期信息&#xff0c;可以使用以下命令&#x…

PPT NO.1【用ppt如何做一张海报+字体】

PPT做得好的人&#xff0c;一定是站在观众的角度思考的人。 1、设置幻灯片尺寸大小&#xff1a; 设置完成后如下&#xff1a; 2、加载一张自己喜欢的图片进来&#xff1a;【图片越高清越好】 将图片铺满空白的地方&#xff0c;调整好自己喜欢的区域&#xff1a; 做裁剪&#xf…

数据结构---递归转化为非递归

递归转化为非递归前言快速排序非递归归并排序的非递归前言 为什么要学习非递归写法呢&#xff1f; 当我们在用递归实现一个程序的时候&#xff0c;要考虑一个问题&#xff0c;这个程序用递归去实现&#xff0c;当数据量庞大的时候&#xff0c;会不会造成栈溢出(STACK OVERFLOW…

代码随想录_226翻转二叉树、101对称二叉树

leetcode 226. 翻转二叉树 ​​​226. 翻转二叉树 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#xff1a; 输入&#xff1a;r…

算法训练第五十五天 | 392.判断子序列、115.不同的子序列

动态规划part15392.判断子序列题目描述思路总结115.不同的子序列题目描述思路392.判断子序列 题目链接&#xff1a;392.判断子序列 参考&#xff1a;https://programmercarl.com/0392.%E5%88%A4%E6%96%AD%E5%AD%90%E5%BA%8F%E5%88%97.html 题目描述 给定字符串 s 和 t &…

【CocosCreator入门】CocosCreator组件 | Graphics(绘制)组件

Cocos Creator 是一款流行的游戏开发引擎&#xff0c;具有丰富的组件和工具&#xff0c;其中Graphics组件允许您在游戏中绘制2D图形和几何形状&#xff0c;并通过编写脚本来控制其外观和行为。 目录 一、组件属性 二、组件方法 三、脚本示例 一、组件属性 属性功能说明lineW…

面试篇-Java并发之CAS:掌握原理、优缺点和应用场景分析,避免竞态问题

1、CAS介绍及原理 多线程中的CAS&#xff08;Compare-and-Swap&#xff09;操作是一种常见的并发控制方法&#xff0c;用于实现原子性更新共享变量的值。其核心思想是通过比较内存地址上的值和期望值是否相等来确定是否可以进行更新操作&#xff0c;从而避免多线程条件下的竞态…

用PyTorch构建基于卷积神经网络的手写数字识别模型

本文参加新星计划人工智能(Pytorch)赛道&#xff1a;https://bbs.csdn.net/topics/613989052 目录 一、MINST数据集介绍与分析 二、卷积神经网络 三、基于卷积神经网络的手写数字识别 一、MINST数据集介绍与分析 MINST数据库是机器学习领域非常经典的一个数据集&#xff0c…

动力节点王鹤SpringBoot3笔记——第八章 文章管理模块

目录 第八章 文章管理模块 8.1 配置文件 8.2 视图文件 8.3 Java代码 第八章 文章管理模块 创建新的Spring Boot项目&#xff0c;综合运用视频中的知识点&#xff0c;做一个文章管理的后台应用。 新的Spring Boot项目Lession20-BlogAdmin。Maven构建工具&#xff0c;包…

【UE4】关卡流送的demo

关卡流送功能可以将地图文件加载到内存中&#xff0c;或者从内存中卸载&#xff0c;并在游戏过程中切换地图的可视性。 这样一来&#xff0c;场景便能拆分为较小的地图块&#xff0c;并且只有相关部分才会占用资源并被渲染。 正确设置后&#xff0c;开发者便能创建大型、无缝衔…

开源流媒体服务器ZLMediaKit在Windows上运行、配置、按需拉流拉取摄像头rtsp视频流)并使用http-flv网页播放

场景 目前市面上有很多开源的流媒体服务器解决方案&#xff0c;常见的有SRS、EasyDarwin、ZLMediaKit和Monibuca等。 1、SRS GitHub - ossrs/srs: SRS is a simple, high efficiency and realtime video server, supports RTMP, WebRTC, HLS, HTTP-FLV, SRT, MPEG-DASH and …

ChatGPT批量翻译-ChatGPT批量生成多国语言

ChatGPT翻译的准吗 ChatGPT是一种基于Transformer架构的自然语言处理技术&#xff0c;其翻译准确性取决于所训练的模型和数据集的质量。在特定的语料库和训练数据下&#xff0c;ChatGPT可以实现一定程度的准确翻译。但是&#xff0c;与人工翻译相比&#xff0c;ChatGPT的翻译质…

LeetCode_101

千奇百怪的排序算法 快速排序 采用左闭右开的二分写法 归并排序 插入排序 冒泡排序 选择排序 以上代码的调用方式&#xff1a; 快速选择 在一个未排序的数组中&#xff0c;找到第 k 大的数字 快速选择一般用于求解 k-th Element 问题&#xff0c;可以在 O(n) 时间复杂度&…

Unix、UTC、GPS时间戳及转换

UTC时间 UTC时间的英文全称&#xff1a;Universal Time Coordinated&#xff0c;中文名称&#xff1a;协调世界时。俗的理解为&#xff0c;这个时间是全世界通用的&#xff0c;即全世界都公用的一个时间。可以认为格林威治时间就是时间协调时间&#xff08;GMTUTC&#xff09;&…

测试名词介绍

测试名词介绍一&#xff1a;敏捷测试1. 定义&#xff1a;2. 敏捷测试的核心&#xff1a;3. 敏捷测试的8大原则和传统测试的区别二&#xff1a;测试名词介绍瀑布模型回归测试Alpha测试Beta测试性能测试白盒测试黑盒测试灰盒测试三&#xff1a;测试流程单元测试 (unit test)集成测…

ChatGPT想干掉开发人员,做梦去吧

很多人都发现ChatGPT可以做一些代码相关的工作&#xff0c;不仅可以写一些基础的类似python、java、js的代码段&#xff0c;还可以做一定量的调优&#xff0c;于是就开始担忧起来&#xff0c;到哪天我的开发工作会不会被ChatGPT这个工具给取代了&#xff1f; 目录 1. ChatGPT…

前 K 个高频元素(力扣刷题代码随想录刷题)

给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 思路&#xff1a; 要统计元素出现频率对频率排序找出前K个高频元素首先统计元素出现的频率&#xff0c;这一类的问题可以使用map来进行统计。 然后是对频率…

【血泪建议】软件测试岗位现状,可惜之前没人告诉我,肠子都晦青了....

谈到现状&#xff0c;国内的软件测试行情目前呈现了两极分化的极端情况。 一个是早期的手工测试人员吐槽工作不好做&#xff0c;即使有工作也是外包&#xff0c;而且薪资太低&#xff1b;一方面是很多互联网企业感叹自动化测试人才难找&#xff0c;有技术的自动化测试工程师&a…

批量自动翻译软件-准确的翻译软件

现代社会&#xff0c;在全球化背景下&#xff0c;语言障碍是碍企业发展的主要因素之一。而翻译软件的出现&#xff0c;为人们跨越语言障碍带来了新的解决方案。针对翻译需要大量文字内容的情况&#xff0c;有一些能翻译大量文字的翻译软件&#xff1a; 147CGPT翻译软件特点&…

面试篇-揭开Spring Bean加载的神秘面纱

SpringBean加载完整过程 启动spring容器&#xff08;创建beanfactory&#xff09;->加载配置(注解、xml)->实例化bean(执行构造方法)->注入依赖->初始化bean&#xff08;设置属性值&#xff09;->使用->销毁 解析和读取 XML 配置文件或注解配置类&#xff0…