当前位置: 首页 > news >正文

JVM详细教程

JVM

前言

还在完善中先发布
JVM虚拟机厂家多钟多样,具体实现细节可能不一样,这里主要讲的是虚拟机的规范,以下内容融合了各个平台发布的内容和周志明老师的《深入理解java虚拟机》

JVM概述

如何理解jvm跨平台?

编译成汇编代码的语言,例如C语言,编译后的二进制文件会因为操作系统的CPU和操作位数的不同无法做到通用。编译成.class的语言,不用关注操作系统的异同,不同的平台安装不同的JVM,代码层面不需要考虑操作系统的异同。JVM是解释运行.class文件的虚拟机,不止针对java。

在这里插入图片描述

jvm虚拟机产品

HotSpot VM
KVM(Kilobyte)
JRockit

JVM内存结构规范

下图只是JVM内存结构的规范,具体的JVM产品实现方案可能有所不同
在这里插入图片描述

java代码编译的过程

在这里插入图片描述

通过反射了解类是如何加载的

最终调用一个本地方法库函数forName0,获取Class<?>,同时传入了一个默认的ClassLoader类
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ClassLoader

java的核心组件,所有的class都通过ClassLoader加载进入内存。ClassLoader通过读取字节码的二进制数据流到JVM当中,JVM再进行连接初始化。可以自定义ClassLoader读取指定的字节码文件,在这个过程中我们就可以对这个二进制流做相应的操作。加载的字节码可以在本地,jar包内,远程。

一些核心的ClassLoader类举例:
BootStrapClassLoader:加载核心库java.*
ExtClassLoader:加载扩展库javaX.*
AppClassLoader:加载程序所在目录
自定义ClassLoader:定制化加载
在这里插入图片描述

自定义一个ClassLoader了解双亲委派机制

一句话就是不断去父类找,看那个父类加载过这个字节码,有就从父类返回,没有就从子类读取
好处:系统不用重复加载字节码
在这里插入图片描述

重写ClassLoader的步骤

1.读取二进制流返回给findClass()
2.加载二进制流loadClass()

public class MyClassLoader extends ClassLoader {public static void main(String[] args) throws ClassNotFoundException {MyClassLoader myClassLoader = new MyClassLoader("/Users/alexyuan/Documents/codefile/giteemycode/mylearnrepository/jvmdemo/src/main/java/com/alexyuan/test/");Class<?> aClass = myClassLoader.loadClass("Test");System.out.println(aClass.getClassLoader());System.out.println(aClass.getClassLoader().getParent().getClass().getName());System.out.println(aClass.getClassLoader().getParent().getParent().getClass().getName());System.out.println(aClass.getClassLoader().getParent().getParent().getParent());}private String path;public MyClassLoader(String path) {this.path = path;}public MyClassLoader(String path, ClassLoader parentClassLoader) {super(parentClassLoader);this.path = path;}@Overridepublic Class<?> loadClass(String name) throws ClassNotFoundException {// 先调用父类的loadClass方法Class<?> clazz = super.loadClass(name);// 自定义的类加载逻辑return clazz;}/*** 重写父类的findClass方法,在ClassLoader在执行 loadClass 方法时,* 如果父加载器不会加载类,就会调用当前重写的方法进行加载类*/@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {BufferedInputStream bis = null;ByteArrayOutputStream baos = null;try {bis = new BufferedInputStream(new FileInputStream(path + name + ".class"));baos = new ByteArrayOutputStream();int len;byte[] data = new byte[1024];while ((len = bis.read(data)) != -1) {baos.write(data, 0, len);}//获取内存中的完整的字节数组的数据byte[] classByteArray = baos.toByteArray();//将字节数组转换为Class的实例return defineClass(null, classByteArray, 0, classByteArray.length);} catch (IOException e) {e.printStackTrace();} finally {try {if (null != baos) {baos.close();}} catch (IOException e) {e.printStackTrace();}try {if (null != bis) {bis.close();}} catch (IOException e) {e.printStackTrace();}}return null;}
}

读取字节码文件,查看父类都有哪些

在这里插入图片描述
BootstrapClassLoader:Java的启动类加载器,负责加载JRE的核心类库和启动时需要的类。
ExtensionClassLoader:Java的扩展类加载器,负责加载JRE的扩展类库和用户自定义的扩展类库。
SystemClassLoader:Java的系统类加载器,负责加载用户类路径中的类和资源。
URLClassLoader:基于URL的类加载器,可以从指定的URL列表中加载类和资源。
CustomClassLoader:自定义的类加载器,可以根据自己的需求实现自定义的类加载逻辑。

在这里插入图片描述

类的加载过程

1.加载:此阶段由类加载器从指定的位置加载类的二进制数据,包括从JAR文件、目录、网络等位置加载。在加载阶段,类加载器需要解析类的名称、父类、接口、方法、字段等元素,并将其转换为JVM可以识别的字节码格式。

2.链接:此阶段由JVM对字节码进行验证、准备和解析。验证阶段会验证字节码是否符合JVM的规范,包括验证类的名称、父类、接口、字段、方法等元素;准备阶段会为类变量分配内存,并设置默认初始值;解析阶段会解析类中的静态变量、方法和类的调用关系。

3.初始化:此阶段会初始化类中的静态变量和静态方法,并为类变量分配内存。在初始化阶段,如果类中存在静态代码块,会先执行静态代码块;如果类中存在静态方法,会先执行静态方法。在初始化阶段,JVM会为类变量分配内存,并将其初始化为默认初始值。

加载方式

隐示加载:new一个类初始化到内存中
显示加载:Class.forName(),loadClass()
显示加载的区别:
loadClass()只到加载过程

在这里插入图片描述
forName默认初始化是true,所有使用forName该类已经到初始化阶段,会运行类中的静态代码块
在这里插入图片描述

        MyClassLoader myClassLoader = new MyClassLoader("/Users/alexyuan/Documents/codefile/giteemycode/mylearnrepository/jvmdemo/src/main/java/com/alexyuan/test/");Class<?> aClass = myClassLoader.loadClass("Test");Class<?> aClass1 = Class.forName("/Users/alexyuan/Documents/codefile/giteemycode/mylearnrepository/jvmdemo/src/main/java/com/alexyuan/test/Teat.class");Object o = aClass1.newInstance();

java的内存模型

计算机内存

内存模型:
计算机的内存模型是指计算机内部存储数据的方式和结构。计算机的内存模型通常分为三个部分:寄存器、主存储器和缓存。

寄存器:寄存器是CPU中的一组高速缓存,用于存储指令、数据和控制信息。寄存器的访问速度非常快,但是容量有限,只能存储少量的数据。
主存储器:主存储器是计算机中的主要存储器,用于存储大量的数据和指令。主存储器的访问速度比寄存器慢,但是容量大,可以存储大量的数据。
缓存:缓存是计算机中的一种高速缓存技术,用于缓存主存储器中的部分数据,以提高访问速度。缓存的容量通常比主存储器小,但是访问速度非常快。
计算机的内存模型是指将数据和指令从主存储器中加载到寄存器和缓存中,并在CPU中进行处理和运算的过程。在计算机的内存模型中,数据和指令的访问速度取决于它们所存储的位置,从寄存器到主存储器再到缓存,访问速度逐渐变慢。因此,在编写高效的程序时,需要考虑如何优化数据和指令的访问方式,以提高程序的执行效率。

计算机内存读取寻址过程:
在这里插入图片描述
操作系统提供的可寻址空间
32位:2^32 4Gb的寻址范围
64位:2^64的寻址范围

计算机地址空间划分:
内核空间和用户空间是计算机操作系统中的两个概念,它们用于划分计算机内存空间的不同部分。

内核空间:内核空间是计算机内存空间的一部分,用于存储操作系统的核心程序和数据。内核空间是计算机操作系统的核心,它负责管理和控制计算机硬件资源,例如处理器、内存、磁盘、网络等。内核空间的访问权限非常高,只有操作系统本身才能访问。

用户空间:用户空间是计算机内存空间的另一部分,用于存储用户程序和数据。用户空间是用户程序的运行环境,它提供了一组基本的系统调用接口,用于用户程序与内核空间进行交互。用户空间的访问权限相对较低,只有用户程序才能访问。

在计算机操作系统中,内核空间和用户空间是通过内存保护机制实现的。内核空间和用户空间之间存在一个内存保护屏障,用于隔离内核空间和用户空间的数据和指令。只有操作系统本身才能通过内存保护屏障,从而访问内核空间和控制硬件资源。而用户程序只能通过系统调用接口,从而访问用户空间和执行操作系统提供的基本服务。

Java在JVM当中运行内存模型

1

私有区域

程序计数器(逻辑)(Program Counter Register

为什么它是线程私有的?当多线程运行,切换线程的时候如何知道线程自己的字节码运行到什么地方,程序计数器的作用就是如此:
1.记录线程自己的字节码运行到哪一行,因此是线程私有的
2.既然记录的行号,那么就可以改变程序计数器中的值让这个线程去选择读取什么地方下一行的数据

java虚拟机栈(Stack)

java方法执行的内存模型,从局部变量表中取数据,在这个栈内存中通过出栈和入栈的方式进行方法的执行
由多个栈帧组成
栈帧包含:局部变量表(local variable),操作栈(Operand Stack),动态链接(Dynamic Linking),返回地址(Return Address)…等组成
在这里插入图片描述

本地方法栈

和虚拟机栈类似,运行的是native本地方法

局部变量表、操作数栈、程序计数器的关系

在这里插入图片描述

java为什么会栈内存溢出?

从上面线程虚拟方法栈就可以看出每调用一个方法就会有一个栈帧压栈,例如递归等方法,如果递归的层数太深,不断压栈,超过了栈的大小就会出现内存溢出

共享区域

堆(heap)

存放几乎所有的对象实例和数组,所有线程的共享区域。垃圾回收机制也就是针对堆内存的回收,因此也被称为GC堆

方法区(Method Area)

存储已被虚拟机加载的类型信息,常量,静态变量,JIT编译后的代码缓存数据等。

运行时常量池(Runtime Constant Pool)

2运行时常量池(Runtime Constant Pool):是方法区的一部分。Class文件中除了有类的版本、字 段、方法、接口等描述信息外,还有一项信息是常量池表(Constant Pool Table),用于存放编译期生 成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
在jvm规范中,方法区除了存储类信息之外,还包含了运行时常量池。这里
首先要来讲一下常量池的分类
常量池可分两类:
1、Class常量池(静态常量池)
2、运行时常量池
3、字符串常量池(没有明确的官方定义,其目的是为了更好的使用
String ,真实的存储位置在堆)

对象

对象内存布局

在这里插入图片描述
在这里插入图片描述

jvm调优

目的

解决生产环境中日志不输出,死锁,cpu占用过高,如何分配线程数等问题,在于让程序跑起来也让程序跑的更快。
请添加图片描述

JVM参数分类

根据jvm参数开头可以区分参数类型,共三类:“-”、“-X”、“-XX”,
标准参数“-”:每种类型的Jvm都会实现,-help,-version
非标准参数“-X”:默认Jvm实现这些功能,但不是一定完全实现,-Xms,-Xmx等
非Stable参数“-XX”:不稳定随着版本的不一致,参数也不一致

-X参数

在这里插入图片描述
■ -Xms20m :设置jvm初始化堆大小为20m,一般与-Xmx相同避免垃圾回收完成后jvm重新分。

■ -Xmx20m:设置jvm最大可用内存大小为20m。

■ -Xmn10m:设置新生代大小为20m。

■ -Xss128k:设置每个线程的栈大小为128k。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LZzqV4eD-1692237885248)(assets/image-20230615150410277.png)]

-XX参数

Java -XX:+PrintFlagsFinal -version #打印系统XX参数

-XX:+PrintGCDetails:打印GC详情;

-XX:+PrintGCTimeStamps:打印时间戳;

■ -XX:CMSInitiatingOccupancyFraction=80 CMS gc,表示在老年代达到80%使用率时马上进行回收;

■ -verbose:gc:可以输出每次GC的一些信息;

■ -XX:-UseConcMarkSweepGC:使用CMS收集器;

GC信息查看

打印GC简单信息

-verbose:gc

-XX:+PrintGC

打印详细GC信息

-XX:+PrintGCDetails

-XX:+PrintGCTimeStamps

指定GC日志以文件输出

-Xloggc:./gc.log

使用jps和jinfo查看java进程运行状态

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P5a4EsQL-1692237885248)(assets/ wps1.jpg)]

Jvm运行模式设置

Server模式性能强,64位默认为该模式。Client模式性能较弱,32位系统可以使用该模式。

1.7内存模型介绍

在这里插入图片描述

执行过程:eden区域满了将进入survivor去,survivor区未被回收的对象转移到tenured区域,tenured的没有回收的对象进入永久区。

Survivor区结构:两个相同的survivor区构成。运行时候只会使用一个,另外一个用做gc回收机制时复制对象使用。

Perm:永久区一般存储class和file。一段时间tenured没有被回收将会进入这个区域。

1.8内存模型介绍

在这里插入图片描述
1.8版本取消永久区,使用元素区代替,元素区为本机内存不再jvm当中。

1.8版本jvm对内存组成

在这里插入图片描述
Young区:两个survivor区+eden

MetaSpace:ccs+codecache

Jstat查看堆内存使用情况

命令可使用的参数
在这里插入图片描述

命令格式:jstat –{选项} 进程id 间隔时间 查询次数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eD5FEMDn-1692237885249)(assets/wps6.jpg)]

Jmap使用对堆内存进行统计

Jmap参数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-opzIylYq-1692237885249)(assets/截屏2023-06-15 15.27.06.png)]

Mat工具对jdump文件分析

  1. 将内存情况保存为“.dat”文件
  2. 使用mat打开文件

使用Jstack查看当前jvm中运行现场的情况

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LjpkVE6J-1692237885250)(assets/wps8.jpg)]

线程状态介绍

初始态:刚刚启动的状态,也就是刚刚调用start()函数的状态

运行态:在CPU中运行

就绪:等待CPU资源就可执行
阻塞:没有获得资源一直请求,超时后进入阻塞队列,当获取的资源之后进入就绪

等待态:需要获取的启动资源,属于被动等待

超时等待:主动进入等待状态,如sleep函数

终止态:线程运行结束

使用jmx查看内存和线程使用状况

在JDK中bin目录双击打开

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p1mbvham-1692237885250)(assets/wps9.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7aZdoOwH-1692237885250)(assets/wps10.jpg)]

JVM——垃圾回收机制

什么是垃圾回收

程序在运行时需要申请内存,内存使用之后需要归还内存给系统,当一些无效对象一直占用内存就可能导致内存溢出,因此需要对无效对象进行垃圾回收。

垃圾回收算法

垃圾回收算法——引用计数算法

概述:每个对象都设置一个计数器,如果有对象引用它计数器进行加一,引用结束减一,系统对对象的计数器进行判断,如果计数器为0者回收该对象

缺点:无法回收循环引用,也就是只要是改对象被引用,这就不会被回收,无论这个引用是否指向null或者未被使用。

垃圾回收算法——标记清除法

概述:当系统做垃圾回收的时候暂停所有线程,遍历所有对象,标记处对象的引用关系,清楚root对象未被应用到的对象。

缺点:性能低,由于对象可能在不同内存中,回收的内存很可能不连续,也就是内存碎片化严重。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rjrpw0Rh-1692237885250)(assets/wps11.jpg)]

垃圾回收算法——标记压缩算法

概述:由标记清楚法演变而来,在回收之前将有效对象压缩在一个连续的内存再回收,这样解决了回收内存碎片化的问题

缺点:性能比优化之前更低

垃圾回收算法——复制算法

概述:将内存分为两块,一块使用,另一块闲置,当进行垃圾回收的时候将有效对象放在闲置内存当中,在将内存情况,两个内存空间交换角色,然后重复之前的操作

缺点:运行时有一块内存空间没有使用因此有点资源浪费

应用区域:young中的survivor由两块相同的内存空间构成就是使用的复制算法,这样垃圾回收的区域是完整的一块内存空间,没有碎片化。

回收算法总结

每一个算法都各有有点,根据不同区域的特性不同使用不同算法,年轻代对象少可以使用复制算法,gen区对象多适合标记清楚和标记压缩算法。

垃圾收集器以及内存分配

算法只是实现方式,在java内部提供了一些垃圾回收器,垃圾回收器去完成垃圾的回收。

串行收集器

只有一个线程执行收集器,一般不用

并行收集器

Parnew收集器

将串行收集器改成并行而来

ParallelGC收集器

在parnew的基础上增加了吞吐量的设置

CMS垃圾收集器

算法:标记清除算法

工作位置:老年带

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZKOPiidj-1692237885251)(assets/wps12.jpg)]

Stw:线程全部暂停,stop world

标记时会触发stw

G1垃圾回收器

概述:取消了老年带,年轻代的概念,清理工作是将对象从一个区复制到另一个区。G1为因为巨形对象在拷贝的时候对回收器性能影响很大,因此具有一个humongous区域。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HbbwAd1N-1692237885251)(assets/wps13.jpg)]

G1垃圾回收器使用流程

第一步:打开G1作为垃圾回收器

第二步:设置最大停顿时间,也就是标记清除的时候

第三步:设置堆最大内存

YoungGC

对年轻带进行GC,eden空间向survivor空间复制转移,也向old区转移

MixGC

主要GCyoung区,也GCold区

G1垃圾回收如何找到根对象

使用remember set方式,就是每个空间初始化的时候生成一个set集合,这个集合记录这片空间被引用的空间,通过这些set集合找到根对象,然后从

使用G1垃圾回收器

1.jvm参数:

-XX:+UseG1GC

-XX:MaxGCPauseMillis=100

-Xmx256m

-XX:+PrintGCDetails

-XX:+PrintGCTimeStamps

-XX:+PrintGCDateStamps

-XX:+PrintHeapAtGC

-Xloggc:E://test//gc.log

GC历史文件在:E://test//gc.log目录下,打开https://gceasy.io/文件查看吞吐量

参考文献


  1. 《深入理解java虚拟机:周志明》 ↩︎

  2. 《深入理解java虚拟机:周志明》 ↩︎

相关文章:

JVM详细教程

JVM 前言 还在完善中先发布 JVM虚拟机厂家多钟多样&#xff0c;具体实现细节可能不一样&#xff0c;这里主要讲的是虚拟机的规范&#xff0c;以下内容融合了各个平台发布的内容和周志明老师的《深入理解java虚拟机》 JVM概述 如何理解jvm跨平台&#xff1f; 编译成汇编代码…...

Smartbi吴华夫:后疫情时代,BI发展趋势的观察与应对

沿着旧地图找不到新大陆&#xff0c;“基于指标体系的可视化分析和增强分析”成为BI发展新阶段。Smartbi V11系列新品与时俱进&#xff0c;以指标为核心&#xff0c;同时融合BI应用&#xff0c;赋能管理者和业务&#xff0c;成为引领数字化运营的新航标&#xff01; ——思迈特…...

软件设计模式系列之三———工厂方法模式

1 模式的定义 工厂方法模式是一种常见的设计模式&#xff0c;属于创建型设计模式之一&#xff0c;它在软件工程中用于对象的创建。该模式的主要思想是将对象的创建过程抽象化&#xff0c;将具体对象的实例化延迟到子类中完成&#xff0c;以便在不同情况下可以创建不同类型的对…...

pytorch 多卡分布式训练 调用all_gather_object 出现阻塞等待死锁的问题

pytorch 多卡分布式训练 torch._C._distributed_c10d中的函数all_gather_object 出现阻塞等待死锁的问题 解决办法就是 在进程通信之前调用torch.cuda.set_device(local_rank) For NCCL-based processed groups, internal tensor representations of objects must be moved …...

SpringMvc增删改查

SpringMvc增删改查 一、前期准备二、逆向生成增删改查2.2.aspect切面层2.3.Mybatis generator逆向生成2.4.根据生成代码编写Biz层与实现类 三、controller层代码编写四、前台代码与分页代码五、案例测试 一、前期准备 1.2.导入pom.xml依赖 <?xml version"1.0" …...

【计算机网络】网络编程接口 Socket API 解读(5)

Socket 是网络协议栈暴露给编程人员的 API&#xff0c;相比复杂的计算机网络协议&#xff0c;API 对关键操作和配置数据进行了抽象&#xff0c;简化了程序编程。 本文讲述的 socket 内容源自 Linux man。本文主要对各 API 进行详细介绍&#xff0c;从而更好的理解 socket 编程。…...

手动实现一个bind函数!

原文地址&#xff1a;手动实现一个bind函数&#xff01; - 知乎 1.bind函数用法 bind()方法用于创建一个新的函数&#xff0c;这个新函数接收的第一个参数代表的就是this&#xff0c;利用bind()函数我就就可以任意改变函数内部的this指向了。 官网的解释&#xff1a; bind()…...

数据结构-时间复杂度/空间复杂度

Hello&#xff0c;好久没有更新了哦&#xff0c;已经开始学习数据结构了&#xff0c;这篇文章呢就是对刚学数据结构所接触到的时间复杂度进行一个分享哦&#xff0c;如果有错误之处&#xff0c;大家记得拍拍我哦~ 既然要讨论时间/空间复杂度&#xff0c;那我们就得知道时间/空…...

英语写作中“展示”、“表明”demonstrate、show、indicate、illustrate的用法

一、demonstrate、show、indicate在论文写作中主要用法是&#xff1a;demonstrate/show/indicate 从句&#xff1a; Sb./Sth. demonstrates/shows/indicates that ……从句中一般表达事实、观点和结论等。 例句&#xff1a; The authors demonstrated/showed/indicated that…...

Redis的java客户端

在Redis官网中提供了各种语言的客户端&#xff0c;地址&#xff1a;https://redis.io/resources/clients/ redis的java客户端 https://redis.io/resources/clients/#java 1.jedis使用 引入依赖 <dependency><groupId>redis.clients</groupId><artifac…...

Android环境配置笔记

文章目录 一、各环境文档二、参考 一、各环境文档 Gradle官方的兼容性文档&#xff1a;Java Compatibility 更新日期&#xff1a;2023.9.12 Android Gradle插件版本&#xff1a;Android Gradle Plugin 二、参考 参考文章&#xff1a;Android问题记录...

element-table 行的拖拽更改顺序(无需下载sortableJs

样例展示&#xff1a;vueelement 通过阅读element文档我们发现element并不提供拖拽相关的api 本博客通过element提供的行类名 注册函数 实现行与行的拖拽 1.设置el-table 的行样式类名 这里是用的是 function <el-table:data"outputData":row-class-name&qu…...

Docker部署jenkins

目录 一、jenkins原理二、Docker部署jenkins1.下载jenkins镜像文件2.查看下载的jenkins镜像3.创建Jenkins挂载目录并授权权限4.创建并启动Jenkins容器5.查看jenkins是否启动成功6.查看docker容器日志7.配置镜像加速8.访问Jenkins页面&#xff0c;输入ip地址加上9000端口9.获取管…...

从0到1学会Git(第三部分):Git的远程仓库链接与操作

写在前面:前面两篇文章我们已经学会了git如何在本地进行使用&#xff0c;这篇文章将讲解如何将本地的git仓库和云端的远程仓库链接起来并使用 为什么要使用远程仓库:因为我们需要拷贝我们的代码给别人以及进行协同开发&#xff0c;就需要有一个云端仓库进行代码的存储和同步&a…...

虚拟机Ubuntu操作系统常用终端命令(1)(详细解释+详细演示)

虚拟机Ubuntu操作系统常用终端命令 本篇讲述了Ubuntu操作系统常用的三个功能&#xff0c;即归档&#xff0c;软链接和用户管理方面的相关知识。希望能够得到大家的支持。 文章目录 虚拟机Ubuntu操作系统常用终端命令二、使用步骤1.归档1.1创建档案包1.2还原档案包1.3归档并压缩…...

redis实战-redis实现异步秒杀优化

秒杀优化-异步秒杀思路 未优化的思路 当用户发起请求&#xff0c;此时会请求nginx&#xff0c;nginx会访问到tomcat&#xff0c;而tomcat中的程序&#xff0c;会进行串行操作&#xff0c;分成如下几个步骤 1、查询优惠卷 2、判断秒杀库存是否足够 3、查询订单 4、校验是否是一…...

Python爬虫-IP隐藏技术与代理爬取

前言 在进行爬虫程序开发和运行时&#xff0c;常常会遇到目标网站的反爬虫机制&#xff0c;最常见的就是IP封禁&#xff0c;这时需要使用IP隐藏技术和代理爬取。 一、IP隐藏技术 IP隐藏技术&#xff0c;即伪装IP地址&#xff0c;使得爬虫请求的IP地址不被目标网站识别为爬虫。…...

二刷力扣--链表

链表 链表类型&#xff1a; 单链表&#xff08;可以访问后面的一个节点&#xff09; 双链表&#xff08;可以访问前后节点&#xff09; 循环链表&#xff08;最后一个节点指向首节点&#xff09; 在Python中定义单链表节点&#xff1a; class ListNode:def __init__(self, v…...

返回值加const ,为了不拷贝得到成员的值,但被赋值的左值也要const

1. getA 函数返回值 什么都不加&#xff0c;也改不了c里面a的指针指向 why&#xff1f;返回成员变量时&#xff0c;会复制一下。 返回成员变量时&#xff0c;一般会赋值一下没有RVO_地摊书贩的博客-CSDN博客 2. getA 函数返回值 加了引用&#xff0c; 就没有复制 3. getA 函数…...

本地如何使用HTTPS进行调试

在现代前端开发中&#xff0c;HTTPS已经成为不可或缺的一部分&#xff0c;因为它在保护用户数据和确保网站安全性方面发挥着关键作用。然而&#xff0c;有时在本地开发过程中启用HTTPS可能会变得有些复杂。在本文中&#xff0c;我们将介绍如何轻松地在本地进行HTTPS调试&#x…...

观察者模式:对象之间的订阅机制

欢迎来到设计模式系列的第十三篇文章&#xff01;在之前的文章中&#xff0c;我们学习了许多常用的设计模式&#xff0c;今天我们将介绍观察者模式&#xff0c;它是一种行为型设计模式&#xff0c;用于定义对象之间的一对多依赖关系&#xff0c;当一个对象的状态发生变化时&…...

【1462. 课程表 IV】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 你总共需要上 numCourses 门课&#xff0c;课程编号依次为 0 到 numCourses-1 。你会得到一个数组 prerequisite &#xff0c;其中 prerequisites[i] [ai, bi] 表示如果你想选 bi 课程&#xff0c;你…...

Kerberos 身份验证

简介 Kerberos 是一种由 MIT&#xff08;麻省理工大学&#xff09;提出的一种基于加密 Ticket 的身份认证协议。它旨在通过使用密钥加密技术为客户端/服务器应用程序提供强身份验证&#xff0c;用于验证用户或主机的标识。。 适用范围&#xff1a;Windows Server 2022、Window…...

R语言贝叶斯METROPOLIS-HASTINGS GIBBS 吉布斯采样器估计变点指数分布分析泊松过程车站等待时间...

原文链接&#xff1a;http://tecdat.cn/?p26578 指数分布是泊松过程中事件之间时间的概率分布&#xff0c;因此它用于预测到下一个事件的等待时间&#xff0c;例如&#xff0c;您需要在公共汽车站等待的时间&#xff0c;直到下一班车到了&#xff08;点击文末“阅读原文”获取…...

通付盾入选2023年度“上市苗圃工程”重点企业

近日&#xff0c;2023年度苏州工业园区企业上市苗圃工程认定名单公示&#xff0c;江苏通付盾科技有限公司成功入选园区“上市苗圃工程”重点企业。 2023年第一批次苗圃企业认定结果&#xff1a; 企业上市苗圃工程 上市企业是衡量地方综合经济实力的重要标尺&#xff0c;也是区…...

SpringMVC之文件上传下载

SpringMVC是一个基于Java的Web框架&#xff0c;它提供了一套用于构建Web应用程序的开发模型。在SpringMVC中&#xff0c;文件上传和下载是常见的功能之一。 SpringMVC文件上传和下载的介绍&#xff1a; 介绍文件上传&#xff1a; 在SpringMVC中&#xff0c;文件上传功能可以通…...

嵌入式IDE(2):KEIL中SCF分散加载链接文件详解和实例分析

在上一篇文章IAR中ICF链接文件详解和实例分析中&#xff0c;我通过I.MX RT1170的SDK中的内存映射关系&#xff0c;分析了IAR中的ICF链接文件的语法。对于MCU编程所使用的IDE来说&#xff0c;IAR和Keil用得比较多&#xff0c;所以这一篇文章就来分析一下Keil的分散文件.scf(scat…...

Linux防火墙常用操作及端口开放

Linux防火墙常用操作及端口开放 1.查看防火墙状态 firewall-cmd --state 2.开启防火墙 systemctl start firewalld.service 3.开启指定端口 firewall-cmd --zonepublic --add-port3306/tcp --permanent firewall-cmd --zonepublic --add-port6379/tcp --permanent 显示success表…...

[JAVAee]Linux上的javax.mail报错

我们把在window写的项目部署到Linux上的Tomcat时,如果发现使用不了了,该如何找到错误呢?找到报错的地方在哪呢? 在Linux环境下来到Tomcat目录下的logs目录,输入: tail -f catalina.out -n 500 tail 就是把文件的末尾几行读取到终端上,并会持续刷新 -f 循环读取 catalina.ou…...

开学季|校园迎新哪家强?VR全景来导航

九月开学迎新季&#xff0c;各大高校的迎新活动开展的如火如荼&#xff0c;随着科技的不断进步&#xff0c;高校为了更好的开展迎新活动&#xff0c;让新生们尽快熟悉新的校园和生活&#xff0c;会利用VR全景技术带领着新生进行校园游览&#xff0c;给予新生们巨大便利的同时&a…...

网站建设淘宝客/seo优化网站排名

随时随地阅读更多技术实战干货&#xff0c;获取项目源码、学习资料&#xff0c;请关注源代码社区公众号(ydmsq666)、QQ技术交流群(183198395)。 大家经常遇到运行java程序内存不足 修改内存不足的方法如下&#xff1a; Eclipse报错&#xff1a;gc overhead limit exceeded ec…...

昆明网站建站推广/黑帽seo优化推广

1、新建个文本文件 2、譬如输入: start iexplore.exe del.cnblogs.com 3、保存为 *.bat(保存时从保存类型选择"所有文件"), 譬如保存为 abc.bat 4、运行这个 abc.bat 文件转载于:https://www.cnblogs.com/del/archive/2008/07/26/1252139.html...

商城网站怎么建设/网络营销推广8种方法

文章目录 引言I 文章代码高亮的实现1.1 mp-html的用法1.2 更新支持语言样式库II 自动插入代码块code标签2.1 方式一:在得到文章数据之后使用正则添加code标签2.2 方式二:在发布wp文章时自动插入代码块code标签2.3 小结see also引言 最近发现一些博客类小程序的开发者不懂得处…...

一流的购物网站建设/国际最新新闻

文章目录1 introduction2 evaluation题目&#xff1a;TENET: A Framework for Modeling Tensor Dataflow Based on Relation-centric Notation时间&#xff1a;2021会议&#xff1a;ISCA研究机构&#xff1a;北大 1 introduction 如何描述数据流&#xff1f; 本文总结了三种形…...

福建省建设职业管理中心网站/最新长尾关键词挖掘

本文实例为大家分享了java递归输出树形菜单的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下首先我们要建立树节点的类&#xff1a;package com.tree;public class Node {private Integer id;private Integer parentId;private String name;private String link;publ…...

网站建设pdf 下载/seo优化排名易下拉软件

Hash Identifier可以用来识别各种类型的哈希值。在kali上使用方法很简单 &#xff08;1&#xff09;搜索hash-identifier &#xff08;2&#xff09;在HASH后面输入要识别的hash内容 &#xff08;3&#xff09;识别成功 windows平台上这款工具&#xff0c;效果都差不多。...