JVM 全面了解

news2024/11/14 17:17:54

    JVM包含两个子系统和两个组件,两个子系统为Class loader(类装载器)、Execution engine(执行引擎);两个组件为Runtime data area(运行时数据区)、Native Interface(本地接口)。

方法区:存储已被虚拟机加载的类元数据信息(元空间)

堆:存放对象实例,几乎所有对象实例都在这里分配内存

Java栈(虚拟机栈):虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息

本地方法栈:为虚拟机使用到的native方法服务

程序计数器:当前线程所执行的字节码的行号指示器

深入理解Java虚拟机(第二版):

类加载器ClassLoader

类加载器分为四种:前三种为虚拟机自带的加载器

  • 启动类加载器(Bootstrap):负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类
  • 扩展类加载器(Extension):由Java语言实现,负责加载java平台中扩展功能的一些jar包,包$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包
  • 应用程序类加载器(AppClassLoader):由Java实现,也叫系统类加载器,负责加载classpath中指定的jar包及目录中class
  • 用户自定义加载器: Java.lang.ClassLoader的子类,用户可以定制类的加载方式

工作过程:

  1. 当AppClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成
  2. 当ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成;
  3. 如果BootStrapClassLoader加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用ExtClassLoader来尝试加载;
  4. 若ExtClassLoader也加载失败,则会使用AppClassLoader来加载
  5. 如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException

以上流畅就是所谓的双亲委派模型:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上请求

优点:从安全性角度来看,双亲委派模型可以防止内存中出现多份同样的字节码

执行引擎ExecutionEngine

Execution Engine执行引擎负责解释命令,提交操作系统执行

本地方法栈Native Method Stack

它的具体做法是Native Method Stack中登记native方法,在Execution Engine 执行时加载本地方法库。

本地接口Native Interface

​ 本地接口的作用是融合不同的编程语言为 Java 所用,它的初衷是融合 C/C++程序,Java 诞生的时候是 C/C++横行的时候,要想立足,必须有调用 C/C++程序(蹭热度),于是就在内存中专门开辟了一块区域处理标记为native的代码,它的具体做法是 Native Method Stack中登记 native方法,在Execution Engine 执行时加载native libraies。

​ 目前该方法使用的越来越少了,除非是与硬件有关的应用,比如通过Java程序驱动打印机或者Java系统管理生产设备,在企业级应用中已经比较少见。因为现在的异构领域间的通信很发达,比如可以使用 Socket通信,也可以使用Web Service等。

PC寄存器Program Counter

即程序计数器

​ 每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向下一条指令的地址,就是将要执行的指令代码),由执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不记。

方法区Method Area

方法区被所有线程共享,所有字段和方法字节码,以及一些特殊方法如构造函数,接口代码也在此定义。

简而言之,所有定义的方法的信息都保存在该区域,此区属于共享区间

静态变量+常量+类信息(构造方法/接口定义)+运行时常量池存在方法区中

但是实例变量存在堆内存中,和方法区无关

栈Stack

栈也叫栈内存,主管Java程序的运行,是在线程创建时创建,它的生命期是跟随线程的生命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束该栈就Over,生命周期和线程一致,是线程私有的。8种基本类型的变量+对象的引用变量+实例方法都是在函数的栈内存中分配。

栈存储什么?

栈帧中主要保存3 类数据:

  • 本地变量(Local Variables):输入参数和输出参数以及方法内的变量。
  • 栈操作(Operand Stack):记录出栈、入栈的操作。
  • 栈帧数据(Frame Data):包括类文件、方法等等。

栈运行原理:

栈中的数据都是以栈帧(Stack Frame)的格式存在,栈帧是一个内存区块,是一个数据集,是一个有关方法(Method)和运行期数据的数据集,当一个方法A被调用时就产生了一个栈帧 F1,并被压入到栈中,

A方法又调用了 B方法,于是产生栈帧 F2 也被压入栈,

B方法又调用了 C方法,于是产生栈帧 F3 也被压入栈,

……

执行完毕后,先弹出F3栈帧,再弹出F2栈帧,再弹出F1栈帧……

遵循“先进后出”或者“后进先出”原则

每执行一个方法都会产生一个栈帧,保存到栈(后进先出)的**顶部,顶部栈就是当前的方法,该方法执行完毕
后会自动将此栈帧出栈

常见问题栈溢出:Exception in thread "main" java.lang.StackOverflowError

通常出现在递归调用时或者方法调用过深时。

堆Heap

堆栈方法区的关系:

HotSpot是使用指针的方式来访问对象:

  • Java堆中会存放访问类元数据的地址,
  • reference存储的就是对象的地址

Java栈保存对象的引用地址
堆保存引用地址对应的对象信息
方法区保存对象对应的class类型

Java7之前:

一个JVM实例只存在一个堆内存,堆内存大小是可以调节的。类加载器读取类文件后,把类方法常量变量等信息放入堆内存中,保存所有引用类型的真实信息,以方便执行器执行。

堆内存逻辑分为三部分:

Young Generation Space 年轻代 Young/New

Tenure Generation Space 老年代 Old/Tenure

Permanent Space 永久代 Perm

三种JVM:

•Sun公司的HotSpot

•BEA公司的JRockit

•IBM公司的J9 VM

国内还有阿里巴巴的taobao JVM

其中JVM堆分为新生代和老年代

新生代

新生代是类的诞生、成长、消亡的区域,一个类在这里产生,应用,最后被垃圾回收器回收,结束生命。新生代又分为两部分: 伊甸区(Eden space)和幸存者区(Survivor pace) ,所有的类都是在伊甸区被new出来的。幸存区有两个: 0区(Survivor 0 space)和1区(Survivor 1 space)。当伊甸园的空间用完时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC),将伊甸园区中的不再被其他对象所引用的对象进行销毁。然后将伊甸园中的剩余对象移动到幸存 0区。若幸存 0区也满了,再对该区进行垃圾回收,然后移动到 1 区。那如果1 区也满了呢?再次垃圾回收,满足条件后再移动到老年代。若老年代也满了,那么这个时候将产生MajorGC(FullGC),进行老年代的内存清理。若老年代执行了Full GC之后发现依然无法进行对象的保存,就会产生OOM异常—“OutOfMemoryError”

如果出现java.lang.OutOfMemoryError: Java heap space异常,说明Java虚拟机的堆内存不够。原因有二:

(1)Java虚拟机的堆内存设置不够,可以通过参数-Xms(初始内存)、-Xmx(最大内存)来调整。

(2)代码中创建了大量大对象,并且长时间不能被垃圾收集器收集(存在被引用)。

老年代

默认15次GC后还存在的对象就会放入老年代,老年代对象比较稳定,不会频繁的GC

永久代

永久代是一个常驻内存区域,用于存放JDK自身所携带的Class,Interface的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收的,关闭 JVM 才会释放此区域所占用的内存。

如果出现 java.lang.OutOfMemoryError: PermGen space,说明是Java虚拟机对永久代Perm内存设置不够。一般出现这种情况,都是程序启动需要加载大量的第三方jar包。例如:在一个Tomcat下部署了太多的应用。或者大量动态反射生成的类不断被加载,最终导致Perm区被占满。

Jdk1.6及之前: 有永久代,,常量池1.6在方法区

Jdk1.7: 有永久代,但已经逐步“去永久代”,常量池1.7在堆

Jdk1.8及之后: 无永久代,常量池在元空间(Metaspace)

实际而言,方法区(Method Area)和堆一样,是各个线程共享的内存区域,它用于存储虚拟机加载的:

类信息+普通常量+静态常量+编译器编译后的代码等等,虽然JVM规范将方法区描述为堆的一个逻辑部分,但它却还有一个别名叫做Non-Heap(非堆),目的就是要和堆分开。

对于HotSpot虚拟机,很多开发者习惯将方法区称之为“永久代(Parmanent Gen)” ,但严格本质上说两者不同,或者说使用永久代来实现方法区而已,永久代是方法区(相当于是一个接口interface)的一个实现,jdk1.7的版本中,已经将原本放在永久代的字符串常量池移走。

为什么移除永久代?

  • 内存是启动时固定好的,调优困难,太小容易出现永久代溢出,太大则容易导致老年代溢出
  • 字符串存在永久代中,容易出现性能问题和内存溢出
  • 永久代会为 GC 带来不必要的复杂度,并且回收效率偏低

常量池(Constant Pool)是方法区的一部分,Class文件除了有类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池,这部分内容将在类加载后进入方法区的运行时常量池中存放。

元空间并不在虚拟机中,而是使用本地内存,默认情况下,元空间的大小仅受本地内存限制,可以通过以下参数调优:
​ -XX:MetaspaceSize,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。
​ -XX:MaxMetaspaceSize,最大空间,默认是没有限制的。

除了上面两个指定大小的选项以外,还有两个与 GC 相关的属性:

​ -XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集
​ -XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集

堆参数调优

常用JVM参数

参数备注
-Xms初始堆大小。只要启动,就占用的堆大小,默认是内存的1/64
-Xmx最大堆大小。默认是内存的1/4
-Xmn新生区堆大小
-XX:+PrintGCDetails输出详细的GC处理日志
Java代码查看jvm堆的默认值大小:
Runtime.getRuntime().maxMemory()   // 堆的最大值,默认是内存的1/4
Runtime.getRuntime().totalMemory()  // 堆的当前总大小,默认是内存的1/64

设置JVM参数

程序运行时,可以给该程序设置jvm参数,不同的工具设置方式不同。

命令行:

java -Xmx50m -Xms10m HeapDemo

eclipse、IDEA:
在 Run Configuration 的 VM Options 中设置。

查看堆内存详情

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

        System.out.print("最大堆大小:");
        System.out.println(Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M");
        System.out.print("当前堆大小:");
        System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");
        System.out.println("==================================================");

        byte[] b = null;
        for (int i = 0; i < 10; i++) {
            b = new byte[1 * 1024 * 1024];
        }
    }
}

执行前配置参数:-Xmx50m -Xms30m -XX:+PrintGCDetails

执行:看到如下信息

新生代和老年代的堆大小之和是Runtime.getRuntime().totalMemory()

开发中,eclipse使用MAT工具、IDEA分析Dump文件来定位OOM位置。

GC垃圾回收

JVM垃圾判定算法:

  • 引用计数法(Reference-Counting)
  • 可达性分析算法(根搜索算法)

GC垃圾回收算法:

  • 复制算法(Copying)
  • 标记清除(Mark-Sweep)
  • 标记压缩(Mark-Compact),又称标记整理
  • 分代回收算法(Generational-Collection)

垃圾判定

引用计数法(Reference-Counting)

引用计数算法是通过判断对象的引用数量来决定对象是否可以被回收

给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的

优点:

  • 简单,高效,现在的objective-c、python等用的就是这种算法。

缺点:

  • 引用和去引用伴随着加减算法,影响性能
  • 很难处理循环引用,相互引用的两个对象则无法释放

因此目前主流的Java虚拟机都摒弃掉了这种算法

可达性分析算法

这个算法的基本思想就是通过一系列的称为 “GC Roots” 的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话,则证明此对象是不可用的。

在Java中,可以作为GC Roots的对象包括下面几种:

  • 虚拟机栈(栈帧中的本地变量表)中的引用对象。
  • 方法区中的类静态属性引用的对象。
  • 方法区中的常量引用的对象。
  • 本地方法栈中JNI(Native方法)的引用对象

垃圾回收算法

复制算法(Copying)

该算法将内存平均分成两部分,然后每次只使用其中的一部分,当这部分内存满的时候,将内存中所有存活的对象复制到另一个内存中,然后将之前的内存清空,只使用这部分内存,循环下去。

优点:

  • 实现简单
  • 不产生内存碎片

缺点:

  • 将内存缩小为原来的一半,浪费了一半的内存空间,代价太高;如果不想浪费一半的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都100%存活的极端情况,所以在老年代一般不能直接选用这种算法。
  • 如果对象的存活率很高,我们可以极端一点,假设是100%存活,那么我们需要将所有对象都复制一遍,并将所有引用地址重置一遍。复制这一工作所花费的时间,在对象存活率达到一定程度时,将会变的不可忽视。 所以从以上描述不难看出,复制算法要想使用,最起码对象的存活率要非常低才行,而且最重要的是,我们必须要克服50%内存的浪费。

年轻代中使用的是Minor GC,这种GC算法采用的是复制算法(Copying)。

​ HotSpot JVM把年轻代分为了三部分:1个Eden区和2个Survivor区(分别叫from和to)。默认比例为8:1:1,一般情况下,新创建的对象都会被分配到Eden区。因为年轻代中的对象基本都是朝生夕死的(90%以上),所以在年轻代的垃圾回收算法使用的是复制算法。

​ 在GC开始的时候,对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会根据他们的年龄值来决定去向。对象在Survivor区中每熬过一次Minor GC,年龄就会增加1岁。年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中,没有达到阈值的对象会被复制到“To”区域。经过这次GC后,Eden区和From区已经被清空。这个时候,“From”和“To”会交换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保证名为To的Survivor区域是空的。Minor GC会一直重复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象移动到年老代中。


因为Eden区对象一般存活率较低,一般的,使用两块10%的内存作为空闲和活动区间,而另外80%的内存是用来给新建对象分配内存的。一旦发生GC,将10%的from活动区间与另外80%中存活的eden对象转移到10%的to空闲区间,接下来,将之前90%的内存全部释放,以此类推。

标记清除(Mark-Sweep)

“标记-清除”(Mark Sweep)算法是几种GC算法中最基础的算法,是因为后续的收集算法都是基于这种思路并对其不足进行改进而得到的。正如名字一样,算法分为2个阶段:

  1. 标记出需要回收的对象,使用的标记算法均为可达性分析算法
  2. 回收被标记的对象。

缺点:

  • 效率问题(两次遍历)
  • 空间问题(标记清除后会产生大量不连续的碎片。JVM就不得不维持一个内存的空闲列表,这又是一种开销。而且在分配数组对象的时候,寻找连续的内存空间会不太好找。)

标记压缩(Mark-Compact)

标记-整理法是标记-清除法的一个改进版。同样,在标记阶段,该算法也将所有对象标记为存活和死亡两种状态;不同的是,在第二个阶段,该算法并没有直接对死亡的对象进行清理,而是通过所有存活对像都向一端移动,然后直接清除边界以外的内存。

优点:

​ 标记/整理算法不仅可以弥补标记/清除算法当中,内存区域分散的缺点,也消除了复制算法当中,内存减半的高额代价。

缺点:

​ 如果存活的对象过多,整理阶段将会执行较多复制操作,导致算法效率降低。

老年代一般是由标记清除或者是标记清除与标记整理的混合实现。

分代回收算法(Generational-Collection)

从简单情况的时间复杂度来看:

内存效率:复制算法 > 标记清除算法 > 标记整理算法
内存整齐度:复制算法 = 标记整理算法 > 标记清除算法
内存利用率:标记整理算法 = 标记清除算法 > 复制算法

可以看出,效率上来说,复制算法是当之无愧的老大,但是却浪费了太多内存,而为了尽量兼顾上面所提到的三个指标,标记整理算法相对来说更平滑一些,但效率上依然不尽如人意,它比复制算法多了一个标记的阶段,又比标记清除多了一个整理内存的过程

分代回收算法实际上是把复制算法和标记整理法的结合,并不是真正一个新的算法,一般分为:老年代和年轻代,老年代就是很少垃圾需要进行回收的,新生代就是有很多的内存空间需要回收,所以不同代就采用不同的回收算法,以此来达到高效的回收算法。

年轻代(Young Gen)

年轻代特点是区域相对老年代较小,对像存活率低。

这种情况复制算法的回收整理,速度是最快的。复制算法的效率只和当前存活对像大小有关,因而很适用于年轻代的回收。而复制算法内存利用率不高的问题,通过hotspot中的两个survivor的设计得到缓解。

老年代(Tenure Gen)

老年代的特点是区域较大,对像存活率高。

这种情况,存在大量存活率高的对像,复制算法明显变得不合适。一般是由标记清除或者是标记清除与标记整理的混合实现。

垃圾收集器

垃圾回收的具体实现:Serial收集器、 Parallel收集器、 CMS收集器、G1收集器。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据分析-深度学习 NLP Day3句法分析

第六章句法分析在本章中&#xff0c;你将学到与句法分析相关的一些算法和技术 。 很多技术手段可以用来实 现句法分析&#xff0c;包括基于规则的和基于统计的&#xff0c;在本章中读者将会了解其基本原理和使用方法 。本章要点主要如下&#xff1a;句法分析及其难点句法分析相…

高分子PEG,Biotin-PEG-amine,Biotin-PEG-NH2,生物素-聚乙二醇-氨基

Biotin-PEG-amine&#xff0c; Biotin-PEG-NH2 | 生物素-聚乙二醇-氨基 | CAS&#xff1a;N/A | 纯度&#xff1a;95%一、试剂信息&#xff1a;CAS号&#xff1a;N/A外观&#xff1a;固体/粉末分子量&#xff1a;1K、2K、5K、3.4K、10K、20K溶解性&#xff1a;溶于有机溶剂&…

WebRTC GCC拥塞控制算法详解

1、WebRTC版本m742、GCC的概念GCC全称Google Congest Control&#xff0c;所谓拥塞控制&#xff0c;就是控制数据发送的速率避免网络的拥塞。可以对比TCP的拥塞控制算法&#xff0c;由于WebRTC使用基于UDP的RTP来传输媒体数据&#xff0c;需要一个拥塞控制算法来保证基本的Qos。…

SLM27211 集成自举二极管的4A,120V高低边栅极驱动器

SLM27211是一款集成了自举二极管的120V的耐压的&#xff0c;支持高频率大电流&#xff08;4A&#xff09;输出的栅极驱动器。可以缩短栅极电压上升时间、下降时间。它可以在8V至20V下驱动高低MOSFET。产品以集新技术、新工艺、新成果为一体&#xff0c;可安全高效地应用于多类模…

【音视频安卓开发 (十一)】jni基础

要使用jni开发需要包含jni.h头文件JNIEXPORT JNI : 是一个关键字&#xff0c;不能少&#xff08;编译能通过&#xff09;&#xff0c;标记为该方法可以被外部调用jstring : 代表java中的stringJNICALL: 也是一个关键字&#xff0c;可以少的jni callJNIENV : 这是c和java相互调用…

学习笔记-架构的演进之服务容错策略设计模式-3月day02

文章目录前言断路器模式舱壁隔离模式重试模式总结附前言 容错设计模式&#xff0c;指的是“要实现某种容错策略&#xff0c;我们该如何去做”。微服务中常见的设计模式包括断路器模式、舱壁隔离模式和超时重试模式等&#xff0c;另外还有流量控制模式等。 断路器模式 断路器…

VSCode——SSH免密登录

文章目录本地PC端&#xff08;一般为Windows&#xff09;1. 检查自己是否已经生成公钥2. 配置VScode的SSH config远程服务器端1. 服务器新建授权文件2. 赋权限3. 重启远程服务器的ssh服务最全步骤&#xff1a;【设置ssh免密不起作用&#xff1f;彻底搞懂密钥】vscode在remote S…

linux常用命令介绍 05 篇——实际应用篇(用 cut、uniq等统计文档里每个关键词出现的次数)

linux常用命令介绍 05 篇——实际应用篇&#xff08;用 cut、uniq等统计文档里每个关键词出现的次数&#xff09;1. 先导文章——关于行过滤 和 列截取2. 关于单个统计单词个数2.1 grep2.2 wc3. 统计文档中每个关键词出现的次数3.1 先看文档内容 需求3.1.1 文档内容3.1.2 需求…

系列十、锁

一、概述 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中&#xff0c;除传统的计算资源&#xff08;CPU、RAM、I/O&#xff09;的争用以外&#xff0c;数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问…

热烈祝贺|济南市时代酒具盛装亮相2023中国(山东)精酿啤酒产业发展创新论坛暨展览会

济南市时代酒具制造股份有限公司成立于2010年&#xff0c;注册资金600万&#xff0c;员工100余人&#xff0c;占地30余亩&#xff0c;是山东省济南市一家专业的塑料产品生产厂家。主营酒塔、分酒器、混饮塔、果汁塔、橡木桶等系列酒具。经过十余年的发展&#xff0c;公司组建了…

201_DMA-BUF简单简介

一、DMA-BUF等概念的介绍 首先需要明确DMA-BUF&#xff0c;Dma buffer&#xff0c;ION和DMA-BUF Heap是不同的概念。 在Android 多媒体系统中为了减少因不同进程之间内存的多次拷贝而产生的不必要的开销&#xff0c;最直接的想法是希望跟硬件设备进行交互的应用能有一个内存能…

离线安装samba与配置(.tar方式安装)

一、samba离线安装【安装并设置成功后&#xff0c;相关文件及其位置&#xff1a;①smbd&#xff1a;/usr/local/samba/sbin/smbd②nmdb&#xff1a;/usr/local/samba/sbin/nmbd③配置文件 smb.conf&#xff1a;/usr/local/samba/lib/smb.conf④添加用户的 smbpasswd 文件&#…

Java并发简介(什么是并发)

文章目录并发概念并发和并行同步和异步阻塞和非阻塞进程和线程竞态条件和临界区管程并发的特点提升资源利用率程序响应更快并发的问题安全性问题缓存导致的可见性问题线程切换带来的原子性问题编译优化带来的有序性问题保证并发安全的思路互斥同步&#xff08;阻塞同步&#xf…

Delphi 中 FireDAC 数据库连接(处理错误)

参见&#xff1a;Delphi 中 FireDAC 数据库连接&#xff08;总览&#xff09;本主题描述了如何用FireDAC处理数据库错误。一、概述EFDDBEngineException类是所有DBMS异常的基类。单个异常对象是一个数据库错误的集合&#xff0c;可以通过EFDDBEngineException.Errors[]属性访问…

第十届蓝桥杯省赛——6旋转(二维数组,找规律)

题目&#xff1a;试题 F: 旋转时间限制: 1.0s 内存限制: 512.0MB 本题总分&#xff1a;15 分【问题描述】图片旋转是对图片最简单的处理方式之一&#xff0c;在本题中&#xff0c;你需要对图片顺时针旋转 90 度。我们用一个 n m 的二维数组来表示一个图片&#xff0c;例如下面…

什么是项目管理资格认证

项目管理资格认证是项目管理协会(PMI)在全球范围内推出的针对项目经理的资格认证体系&#xff0c;包括项目管理专业人士&#xff08;PMP&#xff09;认证、PMI敏捷管理专业人士(PMI-ACP)认证、PMI商业分析专业人士&#xff08;PMI-PBA&#xff09;认证、项目集管理专业人士&…

驱动器,DRV10975ZRHFR原理图DRV83055QPHPRQ1规格参数

DRV10975器件是一款具有集成功率MOSFET的三相无传感器电机驱动器&#xff0c;可提供高达1.5A的持续驱动电流。该器件专为成本敏感型、低噪声、低外部组件数量应用而设计。DRV10975&#xff08;明佳达电子&#xff09;DRV10975ZRHFR IC MTR DRV MULTPHS 6.5-18V 24QFN电机类型 -…

拿下3个大厂offer的软件测试面试宝典,面试一文搞定

我是谁、工作几年、你上家公司做什么、负责什么、你的优势、为什么适合这个职位、我想做什么、在这个职位上想得到什么 【呕心沥血】耗时7天整理的金三银四必看的软件测试频面试题 涵盖 接口自动化测试框架面试题_哔哩哔哩_bilibili【呕心沥血】耗时7天整理的金三银四必看的软…

day26 员工薪水中位数

569. 员工薪水中位数 写一个SQL查询&#xff0c;找出每个公司的工资中位数。 以 任意顺序 返回结果表。 查询结果格式如下所示。 SQL&#xff1a;方法一 select id, company, salary from (selectid, company, salary,row_number() over(partition by company order by s…

aws batch 理解batch中的任务调度策略

参考资料 https://docs.amazonaws.cn/en_us/batch/latest/userguide/job_queue_parameters.html#job_queue_scheduling_policy https://docs.amazonaws.cn/en_us/batch/latest/userguide/scheduling-policies.html https://catalog.us-east-1.prod.workshops.aws/workshops/c…