面试(01)————JVM篇,最大白话的一集,常见概念的讲解以及GC监控调优等等

news2024/11/26 21:49:27

一、JDK体系结构图

 二、JVM整体架构

三、JVM组成

3.1、JVM内存区域的执行底层原理

​编辑

3.1.1、程序计数器

3.1.2、堆栈关系的发现 

3.1.3、方法去和堆的关系

3.1.4、堆(重点)

 3.1.4.1、可达性分析算法

3.1、内存泄漏测试以及堆区的GC监控

3.2、Visual GC插件的安装

3.3、堆区内存监控

四、JVM调优 

4.1、Centos7安装Arthas

4.2、测试调优工具

4.2.1、jdk环境查看

​编辑 4.2.2、执行ArthasTest.class

4.2.3、问题排查:

4.2.4、执行arthas-boot.jar

4.2.5、Arthas常见的功能命令以及场景分析

4.3、调优案例

4.3.1、亿级流量电商

4.3.2、单机几十万并发案例

五、类加载器分类和核心功能


一、JDK体系结构图

7baec35cb6ee4a7b8a0904fe83839617.png

 二、JVM整体架构

6d23538fa1594379b2c44b8135cef7c4.png

三、JVM组成

说起JVM组成是什么,我们的第一印象就是堆、栈、方法区、程序计数器等等,但是这样是不对的,真实的JVM的组成由类装载子系统运行时数据区字节码执行引擎这三部分组成。而我们之前的回答只是片面的,所以需要留意一下,防止面试被问到。

其中栈、本地方法区和程序计数器是线程独有的,私有的

堆和方法区是线程共享的

0c56bd63cc544130822a4af16c5ffce1.png

其中最重要的部分就是内存区域这部分,也是面试问的最多的地方,后续的调优也是针对内存区域进行调优的。

3.1、JVM内存区域的执行底层原理

以下面的程序为例进行说明并结合class字节码文件进行底层剖析:

中间可能会穿插一些概念和小的思考。。。

0b03a75ac921433fbc0813e6af7ee2de.png

所以为什么java虚拟机的开发人员使用栈这种先进后出的数据结构?(为什么使用这种设计思想)

答:因为它和方法的嵌套调用执行顺序是相吻合的

cab383a3b32a42f1adc4a13812984ab8.png

3.1.1、程序计数器

这里插入一个概念:什么是程序计数器?

概念:是一种特殊的寄存器,用于存储当前线程正在执行的指令的地址或者下一条即将执行的指令的地址。在多线程环境下,每个线程都有自己独立的程序计数器,用于跟踪该线程当前执行的位置。

0e2de1ee05514567b820673d9fe2fbac.png

为什么java虚拟机设计师要设计程序计数器?


主要是因为多线程。。。。。比如当程序正在运行L1这段代码时(线程1),现在来了一个cpu时间变的更高的线程2将cpu抢占,那么当前线程将会挂起,这里的挂起不是这行代码还没执行完成就挂起,而是执行完才会挂起,等到线程2运行结束了,之前的线程1才会恢复,难道这个时候将要从头开始运行吗?如果是这样的话就有问题了,肯定是出bug了,正确的做法应该是接着线程1后面的线程继续执行(比如L2),那程序是怎么知道的呐?这个时候就要用到计数器了,计数器里的值都是记录好的,当L1执行完时,此时的线程程序计数器的值对应的就是L2,所以程序将从L2继续执行

然后继续往下说:

6848c845ee8642cc8aa6bfe6ac83d0a1.png

9d1965aea0ac495681a84164f72cbdd3.png

这里再拓展一下:当程序运行到L2的时候,还没运行完,此时的程序计数器的值是多少?当然是L3了,程序计数器是动态变化修改的,那么问题来了,程序计数器的值是怎样动态修改的????

其实是我们的字节码文件(Math.class)被加载到内存区域的方法区里的(后面会说),加载到这里,是由字节码执行引擎去执行的,字节码文件是知道我们的代码怎么执行的,以及下一步执行什么代码,说白了,其实就是字节码执行引擎去动态修改程序计数器的值(这只是字节码执行引擎的一个功能,其他功能后面还会再聊)

3.1.2、堆栈关系的发现 

main栈帧和math栈帧有一点点区别: 

首先main栈帧中肯定有一个math局部变量,但是这个局部变量不是个常量,而是new出来的,我们都知道new出来的对象都是放在堆区的,那么问题就来了:


堆中的math对象和math局部变量空间有什么关系:
其实就是,堆中的对象的内存地址存到了math局部变量中了,后续可以根据变量中的地址可以找到堆中的math对象,所以就可以发现栈和堆的关系了,


当栈中有很多不同线程时,每个线程中可能有很多局部变量,其中一部分的局部变量是对象的话,就有一部分指针从栈区指向堆区

0cbb2adcb56d4ff19e0e77ee56c8e6d1.png

3.1.3、方法去和堆的关系

方法区(jdk1.8之后就改成原空间) ,使用的是直接内存

主要放的是:常量,静态变量,类信息

比如:initData这个常量就是放在方法区,然后还有个user这个静态变量也放在方法区,但是,他的结果又是一个对象(new 出来的),当然我们是知道的对象一般都是放在堆中的。


那么方法区中的user和堆中的user是什么关系?

其实和上面的是一样的,方法区中的user存放的是指向堆中的user的指针,所以方法区和堆之间的关系和栈与堆的关系其实是一样的,这样方法区和堆的关系也出来了。

16306c29a91844ac994f45fd25aa7431.png

b96742b6362c4fc2b4766ac012eace8a.png

3.1.4、堆(重点)

b0e6bd1dc8bc4c64a4d6d3e2db3ef593.png

堆内存通常被划分为不同的区域:年轻代和老年代;这种划分主要是为了优化内存管理和垃圾回收效率

年轻代又被划分为:Eden区和Survivor区

大部分new出来的方法堆一般放在Eden区,当Eden空间满时,触发Minor GC(小型垃圾回收)。在Minor GC中,存活的对象会被复制到Survivor空间,而不再存活的对象会被回收。


那么Minor GC的机制是什么?(面试题)
GC整个底层是由字节码执行引擎向后台发起一个垃圾收集线程

回收整个年轻代的垃圾


 

那么Minor GC的机制是什么?(面试题)

GC整个底层是由字节码执行引擎向后台发起一个垃圾收集线程

Full GC回收整个堆内存的垃圾

 3.1.4.1、可达性分析算法

这部分包括OOM的产生,以及堆的内存底层机制

可达性分析算法:GC底层使用到的垃圾收集算法


将“GC Root”对象作为起点,从这些节点开始向下搜索引用的对象,然后继续搜索这些引用的对象下面是否还引用其他对象,直到最后一个对象的成员变量不在引用其他对象,而是一些常量上面的,就不再搜索了,凡是在这引用指针链条上的,对于能够通过这些链访问到的对象的,都会被标记成非垃圾对象, 然后将这些非垃圾对象复制到Survivor其中空的区域(通常是Form区),剩余的存在于Eden区域的对象,没有指针指向他们,就被称为垃圾对象,就会被清理或者回。。。。。。。。。。。。。当Eden再次放满,就会再一次触发Minor GC,存活在From空间的对象将被复制到另一个Survivor空间(通常是一个称为To的Survivor空间),同时,From空间和Eden空间都会被清空,如果一直有引用者,一直存活着非垃圾对象,就是一直触发GC,一直会在Form和To之间来回挪动,每挪动一次分代连理+1,当分代连理达到一定次数,就会将存活的非垃圾对象复制到老年代,当老年代满了之后,就会触发Full GC(或者Major GC)进行垃圾回收,如果此时老年代里面都是存活的非垃圾对象,连Full GC也无法回收了,就是出现一种现象:内存溢出(OOM),当然以上也是OOM的发生过程。

GC Root根节点:线程栈上的本地变量、静态变量、本地方法栈上的变量等等

比如上面的:math和user

feeafc5eef9746eb8ee88c047775c52b.png

3.1、内存泄漏测试以及堆区的GC监控

针对以上的堆的讲解,写一个案例,可能更直观一些:

下面的代码一定会内存溢出的

import java.util.ArrayList;

public class HeapTest {
    // 分配100KB的堆空间
    byte[] a = new byte[1024 *  100];
    /**
     * 主函数,用于不断创建 HeapTest 实例并加入到列表中,以演示内存占用增长。
     *
     * @param args 命令行参数,未使用。
     * @throws InterruptedException 如果线程在睡眠时被中断则抛出此异常。
     */
    public static void main(String[] args) throws InterruptedException{
        ArrayList<HeapTest> list = new ArrayList<>();
        while (true) {  // 持续添加 HeapTest 实例到列表中
            list.add(new HeapTest());
            Thread.sleep(5);// 线程休眠 5 毫秒
        }
    }
}

jvisualvm是JDK提供给我们的一个功能强大的jvm(java虚拟机)监控客户端,默认其并不包含对垃圾回收的监控,我们可以通过其插件扩展的机制为 jvisualvm 增加 Visual GC 的功能 

打开控制台输入:

jvisualvm

即可打开Java VisualVM

a3fa67070c7e46a48baa57d63bddffc1.png

3.2、Visual GC插件的安装

打开Java VisualVM,上方工具栏选择:工具----->插件

d7b70bba6312490d92ffa94a024b51dc.png

选择可用插件,找到Visual GC勾选,就可以进行安装了,我这里已经安装过了,安装好之后,看看插件是否加载进去

901db8872d6843099c36fcb6978c973c.png

随便带你一个进程进去,看看有没有Visual GC,没有的话重新启动Java VisualVM试试727df90286054b288941947805bcdbab.png

3.3、堆区内存监控

启动程序,打开Java VisualVM,发现进程已经开始了

c2a2cd84d91e4c4eb2a1eec0066ff745.png

双击进入进程:

可以监控cpu、堆、类信息、线程等等

1d28c06e350f432aa4dba4ed810f3ee4.png

下面的图其实就和上面分析的一模一样

e9083e93102741eda5a1fece9d1a3934.png

当内存泄漏的时候,控制台报错:

fade565f739d458291ad9c8e12804fe7.png

四、JVM调优 

4.1、Centos7安装Arthas

wget https://alibaba.github.io/arthas/arthas-boot.jar

c3484e3249f5407ca59a7017b8c6c9b0.png

如果显示没有wget插件就先下载插件:

yum install wget

391b02d216f641699cd508b4e8e1b204.png

4.2、测试调优工具

4.2.1、jdk环境查看

执行一下语句:java com.ysy.ArthasTest

注意:这里的ArthasTest文件时class字节码文件,如果不是的话,你可以先上传java文件,然后使用javac ArthasTest.java命令进行编译为class文件

因为我的jdk安装命令是:

yum install -y java-1.8.0-openjdk.x86_64

 /usr/lib/jvm/java-1.8.0-openjdkbin 目录下没有 javac 可执行文件

如果你的服务器jdk里没有javac,就执行以下的命令:

yum install java-1.8.0-openjdk-devel

95c43f96372e4ca780f525b111daf096.png 4.2.2、执行ArthasTest.class

68c1fa55ba0b46f6a412837b0c986d52.png

4.2.3、问题排查:

dadd31515eef4f508dcf80330573104c.png

出现这个错误的话,可能是文件夹目录和这个java类里的包路径对不上

项目的包路径:

de7f51ea504d44e9b2aedfbdef03f96e.png

centos7下的服务器的路径:

a1b1a96bc4bb4db283554b83cc0ed19d.png

4.2.4、执行arthas-boot.jar

940a0fd3da144da3a7504f697cb0e235.png

会列出所有java进程,如果想让arthas帮你诊断的某一个进程的话,就直接输入序列号即可

比如我这个就是输入1,回车,出现logo就成功了。

a9ae56ff843040c18ae2484661e72e03.png

4.2.5、Arthas常见的功能命令以及场景分析

输入dashboard,显示大盘数据,可以很直观的看一些东西

6c6d2afb7ff54624b383f7afe389d1a1.png

细心一点的话,我们就可以看到,这个线程一直占用cpu,arthas可以帮助我们很快的定位出问题的代码位置。

输入命令:00354cd425584a19b717340d0607fadb.png

 去这个类里查看代码:

7a51bf36aa7d4906897ed15ac1c6cf04.png

再次进入大盘数据:dashboard可以查看一些其他的问题:

会发现10和11线程一直处于阻塞状态,这个大屏数据是一只持续刷新的:

引申一个问题,这样的程序会出现上面问题,比如从这个线程状态上来猜一下?

大概率会出现的问题是死锁的情况

f3b85bdf1794443493d10e44278a6d4e.png

再次定位:thread -b  

意思就是线程id为11的需要这个java对象,但是现在这个对象被线程id为10的所占用,说明相互之间有依赖等待,才导致的资源阻塞,代码问题在79行;

6887d6a469f7459fa0e3a89dbfbc49bc.png

d16df2ac698e402696d091339e01c3cc.png

这样就很容易产生死锁

但是arthas的功能远不止于此。。。

场景一:比如线上发布的产品,测试的时候明明没有问题,发布到线上之后就出问题了,开发组成员可能会认为是运维组版本发错了,然后这个时候运维组就可能觉得是开发组的代码没有改好,这样子两边就开始相互僵持,都觉得不是自己的责任


jad com.ysy.ArthasTest 可以将线上正在运行的代码,反编译为源代码,这样就可以直观地看出正在线上运行的代码是不是真的有问题

d714c57ee9974ca5bddacc32d8f609a9.png

场景二:
使用ognl命令可以查看线上系统变量的值,甚至可以修改变量的值


比如双十一,那种的大促活动场景,一般都是代码提前一两周都写好了上线的,后面是不允许修改的,然后再活动开始前一天,你发现有些代码是有一些问题的,比如说开关值,控制程序执行的流程,开关值不对,恰巧数据库中或其他地方设置可以修改的值,就仅仅想修改一下开关值,总不能重新修改之后,打包部署上线吧,一般不是严重的问题是不允许重新打包上线的,但是确实有一个小问题会对业务有影响,这个时候arthas就可以发挥作用,执行上面的命令就可以修改命令;

当然arthas有很多nb的功能。。。

难道使用arthas仅仅只是为了调优吗?解决一些小问题就完事了吗?难道这些就是JVM调优吗?

我们不管是触发Minor GC还是Full GC都会发生STW的,那STW是干什么的,其实就是他会停掉我们的用户线程

举个例子:比如电商网站,凡是由用户行为发生的后端对应的执行线程,比如点击下单,点击购物车等等都是用户发起的行为,这些行为再后台有线程执行,这些线程一般为用户线程,而GC是非用户线程,所以在发生垃圾回收线程的GC操作的时候,就会停掉由用户发起的所有的线程,对于用户来说,现在正在下单点击这个下单按钮,如果这个时候后端发生了垃圾回收线程的GC,用户的这个下单行为就可能会有点卡顿一下,但是一般GC是很快的,如果GC个很慢,那么你点下单按钮,页面就会卡住。。。。所以这个GC在一定程度上对我们网站的性能是有一定的影响的,所以归根到底其实是STW的影响,所以JVM调优的真正的目的是减少STW的发生,那么用户发生卡顿的概率就会降低,网站性能就会上去了。




这里就会有另一个问题:java虚拟机的开发人员为什么会设计STW这个机制??不要它不行吗?非要需要它吗?


我们可以反着想一下,如果没有它会怎么样,也就是触发GC的时候,不使用STW,,,,,比如我们正在执行GC,就像上面的可达性分析算法那样,一直往下搜索对象,比如math对象一直往下找,找完了,该user对象往下找,而现在我们没有STW这个机制,那么程序会一直往下执行,因为上面说了嘛,STW会停掉用户的所有线程,,,程序就一直运行,然后这个时候程序可能已经运行结束了,但是GC还没有执行完毕,之前在GC之前做的对象搜索,那些都是非垃圾对象,现在因为线程结束了,上面的局部变量里的内存都没有了,也意味着指针也都没了,那么这批对象现在干嘛?这时候还在GC没有结束的时候,又由你标记的非垃圾对象变成了垃圾对象,肯定是不合适的,难道我GC下次再从头搜索一边吗?肯定是不现实的,因为这个堆里面可能由上百万的对象,所以需要设计一个STW,有了STW,GC在做垃圾手机的过程中,用户线程不会执行,也就是说,堆中的对象是否是垃圾已经定死了,不会随便改变了,如果随便边的话,就不知道怎么做垃圾收集了,那就把GC整不会了,其实就是这个原因。

4.3、调优案例

4.3.1、亿级流量电商

比如说,一个系统昨晚之后发布上线了,平时运行没什么问题,就是系统稍微有一些小小的压力,就会频繁的Full GC,可能几分钟Full GC一次,正常的Full GC一般是几小时,甚至几天几周执行一次算正常,但是现在几分钟执行一次,肯定是有问题的,网站会非常卡顿的,用户体验也不佳。。。。。。

ff4eaf9680d843469af8a297e6b50378.png

大家平时做一个java系统上线的时候,会做JVM的参数设置吗?设置的话,你是怎么设置的?

常做的可能就是内存的划分,比如堆内存三个G,元空间1~2个G,java程序留4~5个G等等,大家肯定由这样分配的,这样来说的话,也不算错,但是就是因为这样的设置才会导致系统频繁的发生Full GC,,,这样就有人说了,这样也可以导致系统频繁Full GC?

首先我们先分析一下,当下这个程序的内存模型到底是怎么样的??


就比如说,我们的程序里肯定会有一个叫createOrder的方法,里面肯定会有一个Order order = new Order()的代码,现在我们每秒钟有300个订单,每个订单的对象大小假设是1kb,因为这个方法里可能还有其他的对象,所以我们就放大20倍,也就是说每秒有6MB的对象产生,期间可能也会有别的操作,所以再放大10倍,也就是每秒产生60MB的对象。

然后就看这个内存模型,每过1秒就会有60MB的对象被放入Eden区,而Eden区也就800MB,所以经过14秒左右Eden区就会被放满,放慢之后,就会触发Minor GC,然后Minor GC也会有STW机制,假设说在13或者14秒的时候。你的Minor GC还在执行的时候,有一部分线程还没有结束,肯定是有这个现象的,这个时候用户的线程全部暂停,还未运行完的线程里的对象还存活着,假设这批存活者的对象大概六七十MB左右,应该从Eden区放到Survivor区,但是,这一批对象不一定会放到S区,而是直接放到老年代,,,,,其实这也是JVM的底层,这个知识点属于,对象什么时候放入老年代,这个情况属于:::长期存活的对象将进入老年代,,,还有一些大对象会放入老奶奶带,,,还有老年代空间分配担保机制,,,还有对象动态年龄判断(当前放对象的S区域里,有一批对象的总大小大于这块S区内存区域的50%,那么此时大于等于这批对象年龄最大值的对象,就可以直接进入老年代,当然这个50%的比例可以自己调),,,,所以每过13或14秒都有60多MB的对象被放入老年代,不够放的,每过几分钟就会放慢2G,就会触发Full GC,但是你也会发现,这些对象根本没有必要放到老年代,因为这些对象大概在一秒之后就会都变成垃圾,后头Full

 GC你会发现大量的垃圾,老年代本来就不是放垃圾的,他一般是存放长期存活的对象。


面试题:能否对JVM调优,让其几乎不发生Full GC

比如说,将年轻代调大一点,老年代没必要那么大,比例调一调,,比如Eden区改为600MB S0和S1都改为200MB,那么之前的60MB对象进入S区,就不如触发动态年龄判断机制,之后再过14秒,触发Minor GC,这60MB早就变成垃圾了,即使最后一两秒Eden区又有一部分对象存活着,就会放入S区的另一个区域,其实S0区域的那60MB早过了14秒,变成垃圾了,下次Minor GC一定会把这60MB干掉,,这样调整一下内存区域的比例,只要系统并发压力不太发生变化的情况下,基本上不会有那种垃圾被放到老年代,老年代就会很久发生一次Full GC甚至不发生(其中一种),这个是通用的方法
463e904a0e04420da81216f6cb7ba11f.png

24fab8a8e25d44f0958f2a0366513789.png

4.3.2、单机几十万并发案例

上面的案例配置根本顶不住这么高的并发,比如一秒钟处理20万并发,一条消息假设1kb,那么就有200MB内存要放到Eden区,但现在600MB根本顶不住,一两秒就放满了,就会触发Minor  GC比如那最后一两秒的消息,还没来得及存盘,就还存活者,不会被回收掉的,肯定还会有引用指向着的,一下子放到S0,肯定是放不下的,那就放到老年代,而老年代就2G,没几秒就会被放满,Full GC就会非常频繁 所以单机几十万并发,你的物理设备啊,配置啊要非常高,内存搞得很大,cou核数也要很高,,,,,,,比如说这时候年轻代有一二十个G,之前因为Minor GC挺快的,那是因为之前的年轻代内存比较小,你可以忽略他,但是你现在年轻代要做垃圾回收,可能要遍历几十个G,不会很快,其中的STW可能就有几秒钟或者几十秒钟,你一定是需要做优化的,,,,比如说你现在有10秒的STW,客户端现在发送一条消息,突然发生了Minor GC了,我的消息半天没有返回,对于客户端来说还以为你的消息没发成功,就会重复去发,这时候就有大量重复消息,肯定是有问题的,需要去优化的,,,,,那么针对这种高并发的场景,如何去调优,,这时候就要借助垃圾收集器了,JDK1.8默认使用的是Parallel垃圾收集器,但是这种是收集器一点也不适合这种高并发的情况,这就需要其他的垃圾收集器,,,这里先不说垃圾收集器,,,,,

先想一个问题,能不能对垃圾收集的方法做一些优化,让他的停顿时间减少一点????

五、类加载器分类和核心功能

  • 引导类加载器:负责加载支撑JVM运行的位于JRE的lib目录下的核心类库,比如rt.jar、charsets.jar等
  • 扩展类加载器:负责加载支撑JVM运行的位于JRE的lib目录下的ext扩展目录中的JAR类包
  • 应用程序类加载器:负责加载ClassPath路径下的类包,主要就是加载你自己写的那些类
  • 自定义加载器:负责加载用户自定义路径下的类包

后续会继续写,因为JVM东西太多了,需要深入理解底层东西~~

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

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

相关文章

MiniApp SDK 是什么?

介绍 MiniApp SDK 是提供开发、部署、产品体验分析、上线全流程各种需求的解决方案。接入此 SDK&#xff0c;您就可以只关注于代码开发本身&#xff0c;剩余的所有事情都可以交由 SDK 及其依赖方解决。另外&#xff0c;能够有效降低多端开发的技术门槛和研发成本&#xff0c;提…

EYOU网站迁移提示数据库版本不一致(已解决)

网站迁移过程中一般出现数据库版本就是因为这个原因&#xff0c;下面我们一起来看具体怎么操作吧&#xff01; 第一步&#xff0c;进入网站后台把数据库文件备份 第二步&#xff0c;下载数据文件上传至install目录文件里面 第三步&#xff0c;将新上传数据库文件改名为“eyoucm…

HarmonyOS 开发-使用SideBarContainer侧边栏淡入淡出动效实现案例

介绍 在2in1或平板上&#xff0c;群聊侧边栏是一种较为常用的功能&#xff0c;虽然HarmonyOS已经具备了基本的动效&#xff0c;但是部分情况下开发者可能有定制侧边栏动效的需求&#xff0c;本例主要介绍了如何基于显式动画实现侧边栏的淡入淡出动效。 效果图预览 使用说明&a…

秋招算法刷题6

20240408 1.两数之和 &#xff08;时间复杂度是O&#xff08;n的平方&#xff09;&#xff09; public int[] twoSum(int[] nums, int target){int nnums.length; for(int i0;i<n;i){ for(int j1;j<n;j){ if(nums[i][j]target){ …

基于逻辑回归和支持向量机的前馈网络进行乳腺癌组织病理学图像分类

CNN&#xff08;卷积神经网络&#xff09;通过使用反向传播方法来学习特征&#xff0c;这种方法需要大量的训练数据&#xff0c;并且存在梯度消失问题&#xff0c;从而恶化了特征学习。 CNN卷积神经网络 CNN由一个多层神经网络组成&#xff0c;该网络从标记的训练数据集中学习…

数据仓库实践

什么是数据仓库&#xff1f; 数据仓库是一个用于存储大量数据并支持数据分析与报告的系统。它通常用于集成来自不同来源的数据&#xff0c;提供一个统一的视图&#xff0c;以便进行更深入的分析和决策。 数据仓库的主要优势&#xff1f; 决策支持&#xff1a;为企业决策提供可靠…

Javascript进阶内容

1. 作用域 1.1 局部作用域 局部作用域分为函数作用域 和 块级作用域 块级作用域就是用 {} 包起来的&#xff0c;let、const声明的变量就是产生块作用域&#xff0c;var不会&#xff1b;不同代码块之间的变量无法互相访问&#xff0c;里面的变量外部无法访问 1.2 全局作用域…

【神经网络】循环神经网络RNN和长短期记忆神经网络LSTM

循环神经网络RNN和长短期记忆神经网络LSTM 欢迎访问Blog总目录&#xff01; 文章目录 循环神经网络RNN和长短期记忆神经网络LSTM1.循环神经网络RNN&#xff08;Recurrent Neural Network&#xff09;1.1.学习链接1.2.RNN结构1.3.RNN缺点 2.长短期记忆递归神经网络LSTM&#x…

本地MinIO存储服务通过Java程序结合cpolar实现远程连接上传文件

文章目录 前言1. 创建Buckets和Access Keys2. Linux 安装Cpolar3. 创建连接MinIO服务公网地址4. 远程调用MinIO服务小结5. 固定连接TCP公网地址6. 固定地址连接测试 前言 MinIO是一款高性能、分布式的对象存储系统&#xff0c;它可以100%的运行在标准硬件上&#xff0c;即X86等…

回归测试覆盖率指的是什么?

定义 回归测试是指修改了旧代码后&#xff0c;重新进行测试以确认修改没有引入新的错误或导致其他代码产生错误。 在软件开发过程当中&#xff0c;一旦软件代码做了修改&#xff0c;就有可能引入新的问题&#xff0c;所以这个时候就需要把已经完成了的验证用例重新跑一下&…

智能工业-方案优势

节省成本 ─键修改所有仓储物料信息&#xff0c;无需人工打印、更换仓位卡&#xff0c;降低人力成本;全程无纸化操作&#xff0c;节约材料成本;网络融合方案&#xff0c;降低硬件成本。 高效运营 优化信息变更、陈列、拣货等工作流程&#xff0c;全程APP管理&#xff0c;流程…

Windows Nginx 启动

先解压 nginx安装包&#xff0c;进入到安装目录下(配置环境变量没有用) 解压后的目录结构如上。 #启动服务 默认是80端口&#xff0c; #如果端口被占用&#xff0c;是启动不了的&#xff0c;会生成error log在log目录下 start nginx#停止nginx 服务 nginx -s stop#重新加载配置…

浅析安全传输协议HTTPS之“S”

当前互联网&#xff0c;在各大浏览器厂商和CA厂商的推动下&#xff0c;掀起了一股HTTPS应用浪潮。为了让大家更好的了解HTTPS&#xff0c;本文给大家介绍关于HTTPS 中的S一个整体的认识。从其产生的历史背景、设计目标说起&#xff0c;到分析其协议设计结构、交互流程是如何实现…

linux中查看占用端口的进程方法

1、netstat -tlnp | grep 端口号 netstat -tlnp|grep 3306 其中&#xff1a;95115是进程号&#xff0c;mysqld是进程名称 2、ss -ltnp | grep 端口号 注意&#xff1a;-tlnp和-ltnp ss -ltnp|grep 3306其中&#xff1a;mysqld是进程名称&#xff0c;95115是进程id 3、lsof…

Z变换与传递函数代码化

对于自动控制而言&#xff0c;其关键在于传递函数方程&#xff0c;根据其特性设计出控制器&#xff0c;控制器也是S域的传递函数&#xff0c;那么如何将传递函数用代码的形式表现出来呢&#xff1f;以下将介绍这种工程方法 1、Z变换 对于一个确定的传递函数&#xff0c;如下 …

vue3+高德地图,使用抛物线连接两点,实现线路脉冲和呼吸灯动画效果

最终实现效果 一&#xff1a;版本vue3jsAPI2.0loca2.0.0 二&#xff1a;下载地图加载器 npm i amap/amap-jsapi-loader --save 高德地图jsApi2.0&#xff0c;点击查看官网介绍 三&#xff1a;写成一个组件&#xff0c;哪里使用哪里引入即可&#xff0c;代码如下 <scrip…

深度揭秘:全氟己酮自动灭火毯的原理是什么?

全氟己酮自动灭火毯是近年来很受欢迎的新型消防灭火装置&#xff0c;它不仅高效环保、使用简单、无需安装任何附加设备&#xff0c;还可以主动感应到火灾并自动灭火。为什么它能够做到这一点呢&#xff1f;这要从全氟己酮自动灭火毯的原理说起。 全氟己酮自动灭火毯的原理是什…

JAVA 并发编程之死锁的产生及避免

死锁的产生 死锁可以理解为&#xff0c;在多线程并发竞争资源的环境下&#xff0c;在各自拥有锁的情况下&#xff0c;又去尝试获取对方的锁&#xff0c;从而造成的一种阻塞的现象&#xff0c;若无外力作用&#xff0c;它们都将一直阻塞下去。 代码示例&#xff1a; public cl…

分享|创业老阳推荐的Temu蓝海项目到底怎么样?

在当今竞争激烈的创业市场中&#xff0c;寻找一个具有潜力的蓝海项目成为了众多创业者的梦想。近日&#xff0c;创业老阳推荐的Temu蓝海项目引起了广泛关注。那么&#xff0c;这个项目到底怎么样呢?让我们一起来探讨一下。 首先&#xff0c;Temu蓝海项目在定位上具有显著优势 …

YOLOv8改进 添加大核卷积序列注意力机制LSK

一、Large Separable Kernel Attention论文 论文地址:2309.01439.pdf (arxiv.org) 二、Large Separable Kernel Attention注意力结构 LSK通过使用大型可分离卷积核来提升注意力机制的效果。在传统的注意力机制中,常用的是小型卷积核,如1x1卷积,来计算注意力权重和特征表示…