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

深入JVM:详解JIT即时编译器

文章目录

  • 深入JVM:详解JIT即时编译器
    • 一、序言
    • 二、基础概念
      • 1、何为JIT即时编译
      • 2、热点代码
    • 三、HotSpot内置的即时编译器
      • 1、C1编译器
      • 2、C2编译器
      • 3、分层编译
        • 3.1 协作流程
    • 四、常见JIT优化技术
      • 1、方法内联
      • 2、逃逸分析
        • (1)同步锁消除
        • (2)栈上分配
        • (3)标量替换
    • 五、后记


深入JVM:详解JIT即时编译器

一、序言

对于Java工程师而言,深入理解JVM(Java虚拟机)不仅是掌握Java程序运行机制的基础,也是提升系统性能、优化应用和解决复杂问题能力的重要一步,更是Java进阶之路的重中之重。

本文小豪将带大家认识JIT即时编译器,介绍主流HotSpot虚拟机内置的几款即时编译器,同时结合代码实例,着重讲解JIT优化手段,话不多说,我们直接进入正题。

二、基础概念

在之前,网上可能经常说Java语言的运行速度不如C或C++,Java运行速度慢主要是因为它是解释执行的,而C或C++是编译执行的,解释执行需要通过JVM虚拟机将字节码实时翻译成机器码(边翻译边执行),才能运行在操作系统上,这个过程会比编译执行慢。

但现在再说这个结论就不太对了,随着JIT即时编译技术的发展,性能差距正在逐步缩小,甚至在某些情况下,执行速度是优于C或C++的。

1、何为JIT即时编译

在Java程序执行过程中,主要依靠字节码指令来进行。这些字节码指令按照顺序逐行被实时翻译成机器码,以便于在操作系统上运行。当某些方法或代码块(它们都对应特定的字节码)被频繁调用时,这部分代码就被视为热点代码

JVM虚拟机会针对性的对这部分热点代码进行优化编译,将它们从字节码转换为本地机器码,然后将优化后的本地机器码缓存起来,后续再执行时可以直接从缓存中获取并运行,无需再次编译。

完成这个过程的编译器,就称为JIT即时编译器(Just In Time Compiler)。JIT即时编译器显著提升了Java的性能,缩小了与其它编译型语言运行速度的差距。

在这里插入图片描述

2、热点代码

热点代码是指在运行过程中被频繁执行的代码,被即时编译的热点代码有两种,分别是:

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

而热点代码由热点探测进行发现,热点探测基于计数器,JVM虚拟机会为每个方法建立对应的计数器,统计方法的执行次数、方法内的循环次数等,如果计数器超过指定阈值,则标识其为热点代码。

方法调用计数器:统计方法被调用的次数

回边计数器:统计方法内循环体代码执行的次数

三、HotSpot内置的即时编译器

主流的HotSpot虚拟机内置了两个JIT编译器:C1(Client Compiler)编译器C2(Server Compiler)编译器,在常用的JDK 8版本中,C1和C2是相互协同工作的。

1、C1编译器

C1编译器注重启动时间和编译时间,编译速度较快,但优化程度相对较低。

C1的优化策略相对简单,也比较轻量级,比如方法内联、公共子表达式消除,C1编译器编译的代码的执行速度通常比C2编译器慢。

2、C2编译器

C2编译器侧重于深度优化,与C1正好相反,C2编译器的编译时间较长,但优化的程度较高。

C2的优化策略比较深度,会进行更高级的优化,比如逃逸分析等,C2编译器编译的代码的执行速度通常比C1编译器快。

C2编译器由于深度优化代码过于复杂,已经很难维护了,从JDK 10开始,Graal编译器已经代替了C2编译器,与C1编译器协同工作

3、分层编译

由于C1和C2编译器在优化方面有不同的侧重点:C1侧重编译速度,C2侧重深度优化。

从JDK 7开始,采用分层编译的方式,C1和C2相互协同,共同发挥作用,HotSpot虚拟机根据代码的运行性能动态的选择具体采用哪个编译器完成优化。

在分层编译中,整个优化过程分为五个层次,对应着不同的优化策略:

  • 第0层:解释器执行,开启Profiling性能监控功能
  • 第1层:C1编译器执行,不开启Profiling,执行不带Profiling功能的C1编译代码
  • 第2层:C1编译器执行,开启Profiling,仅执行带部分Profiling功能的C1编译代码(方法调用次数和循环次数)
  • 第3层:C1编译器执行,开启Profiling,执行带全部Profiling功能的C1编译代码
  • 第4层:C2编译器执行,执行C2编译代码

Profiling性能监控是指在程序执行过程中,收集程序执行的各项数据,包括方法调用次数、循环次数、类型转换等等,收集的数据越多,额外的性能开销越大。

第1层到第3层都是由C1编译器执行的,显然,第1层由于不开启Profiling,执行性能会高于第2层,同时第2层只收集少量数据,第2层的执行性能也会高于第3层(总体性能:第4层 > 第1层 > 第2层 > 第3层 > 第0层)

3.1 协作流程

在分层编译中,C1和C2编译器是相互协作的,它们都由各自独立的线程来处理编译任务,线程内部维护着任务队列,用来存放待编译的热点代码,具体协作流程如下:

  1. 默认情况下,热点方法首先会被第3层的C1编译器执行,当Profiling性能监控收集到的数值达到阈值,JVM会评估C1和C2的优化性能(字节码数较少等)
    • 若判定C1和C2的执行效率相当:交由第1层的C1编译器进行优化,停止Profiling监控,不再收集运行信息
    • 若判定C2执行效率相当优于C1:交由第4层的C2编译器进行深度优化
  2. C1线程忙碌时,会直接交由第4层的C2编译器进行深度优化
  3. C2线程忙碌时,会先交由第2层的C1编译器执行优化,进行信息的初步收集,待C2线程空闲时,再交由第3层的C1编译器执行

在这里插入图片描述

四、常见JIT优化技术

JIT即使编译器主要是通过方法内联逃逸分析两种技术来实现代码的优化。

1、方法内联

方法内联其实就是将被调用方法的字节码直接插入到调用该方法的地方,调用时减少了栈帧的创建销毁开销。

举个例子:

实际上JIT修改的是字节码指令,为便于理解,本文使用代码举例

// 方法内联
public double methodInlining() {double num1 = Math.random();double num2 = Math.random();// 等价于 -> double sum = num1 + num2double sum = add(num1, num2);return sum;
}public double add(double num1, double num2) {return num1 + num1;
}

在代码中,方法内联会将其中的add(num1, num2)方法转换为实际的num1 + num1,直接进行计算操作,避免了方法调用。

这里我们简单测试一下:

public static void main(String[] args) {long startTime = System.currentTimeMillis();JitTest demo = new JitTest();for (int i = 0; i < 1000000; i++) {demo.methodInlining();}long endTime = System.currentTimeMillis();System.out.println("执行耗时:" + (endTime - startTime));
}

测试代码也比较简单,循环调用百万次,统计总耗时。

首先我们测试不启用JIT优化下这段代码的执行耗时,禁用JIT优化只需要添加JVM参数-Xint即可,禁用后,控制台输出:

执行耗时:881

取消掉禁用参数-Xint,启用JIT优化,重新执行这段测试代码:

执行耗时:47

我们进一步验证一下add方法是否进行了方法内联优化,添加三个JVM参数-XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining,打印JVM优化内容:

  • -XX:+PrintCompilation:输出被JIT编译的方法信息
  • -XX:+UnlockDiagnosticVMOptions:解锁用于诊断JVM的选项,默认关闭
  • -XX:+PrintInlining:打印内联方法

在这里插入图片描述

如图,大量方法都被内联,其中也包括我们自己写的methodInliningadd方法,并且同时打印出了方法对应的字节大小,我们发现这些被内联的方法字节数都比较小。

其实这是由于方法内联也有一点的限制,即字节数过大的方法体不会进行内联,具体限制如下:

  • 非热点代码:默认限制字节数小于35,可通过参数调整限制

    // 非热点代码的内联字节大小最大阈值
    -XX:MaxInlineSize=n
    
  • 热点代码:默认限制字节数小于325,可通过参数调整限制

    // 热点代码的内联字节大小最大阈值
    -XX:FreqInlineSize=n
    
  • 接口实现限制:若接口的实现方法数量超过3个,则不会被内联

2、逃逸分析

逃逸分析核心思想是判断方法内创建的对象是否会被外部所引用,当JIT编译器判断到对象在方法外部不会被引用,即该对象的生命周期被限定在当前方法执行期间,编译器就能采取多种优化措施,比如锁消除、标量替换和栈上分配。

(1)同步锁消除

同步锁消除旨在消除代码中的同步操作,若某个对象不会逃逸出当前方法,只在方法内部使用,则不存在线程安全问题,因为每个方法的栈都是私有的,JIT编译器就会消除该同步锁操作,提高程序的执行效率。

举个例子:

public void syncLockEliminate() {// 等价于 -> 不执行该同步锁synchronized (JitTest.class) {// 业务代码逻辑}
}public static void main(String[] args) {long startTime = System.currentTimeMillis();JitTest demo = new JitTest();for (int i = 0; i < 1000000; i++) {demo.syncLockEliminate();}long endTime = System.currentTimeMillis();System.out.println("执行耗时:" + (endTime - startTime));
}

这里启用和禁用JIT锁消除(禁用锁消除参数:-XX:-EliminateLocks)对应控制台输出的执行耗时分别为:

// 启用锁消除
执行耗时:143// 禁用锁消除
执行耗时:203
(2)栈上分配

栈上分配是将被创建的对象内存分配在栈上,而不是堆上,降低GC垃圾回收的频率。

举个例子:

static class UserInfo {// 姓名private String name;// 年龄private int age;public UserInfo() {}public UserInfo(String name, int age) {this.name = name;this.age = age;}
}// 栈上分配,不赋值对象属性
public static void createUser() {UserInfo user = new UserInfo();
}public static void main(String[] args) throws Exception {long startTime = System.currentTimeMillis();for (int i = 0; i < 1000000; i++) {createUser();}long endTime = System.currentTimeMillis();System.out.println("执行耗时:" + (endTime - startTime));
}

这里我们验证一下这个结论,我们在JVM参数上添加-XX:+PrintGC,输出GC日志信息,同时将堆内存空间设小一些:

-Xms10m -Xmn10m -XX:+PrintGC

首先默认启用JIT逃逸分析优化,控制台输出:

执行耗时:72

接着禁用逃逸分析优化,添加参数-XX:-DoEscapeAnalysis关闭逃逸分析,控制台输出:

[GC (Allocation Failure)  7679K->1041K(9216K), 0.0010975 secs]
[GC (Allocation Failure)  8721K->904K(9216K), 0.0006550 secs]
[GC (Allocation Failure)  8584K->840K(9216K), 0.0007822 secs]
执行耗时:103

关闭逃逸分析优化后,JVM执行了几次的GC垃圾回收。

(3)标量替换

标量替换是将需要被创建的对象拆解成独立的标量(对象内部的基本数据类型),方法执行时不创建该对象实例,而是直接创建它的成员变量代替它,这些成员变量作为该方法的局部变量被分配在栈上。

标量替换是针对栈上分配更进一步的优化技术,栈上分配只是将对象从堆上分配到栈上,而标量替换是将对象进行拆解,作为方法的局部变量被分配在栈上。

举个例子:

// 标量替换,赋值对象属性
public static void createUser() {// 等价于 -> String name = user.name = xiaohao;//          int age = user.name = 24UserInfo user = new UserInfo("xiaohao", 24);String userInfo = user.name + ":" + user.age;
}public static void main(String[] args) throws Exception {long startTime = System.currentTimeMillis();for (int i = 0; i < 1000000; i++) {createUser();}long endTime = System.currentTimeMillis();System.out.println("执行耗时:" + (endTime - startTime));
}

若JIT判断到UserInfo对象不会逃逸出当前方法,则会将UserInfo对象的nameage属性替换为两个局部变量,不进行创建UserInfo对象,避免在堆上分配对象实例。

控制台输出的执行耗时分别为:

// 启用逃逸分析
执行耗时:162// 禁用逃逸分析
执行耗时:203

五、后记

本文从JIT即时编译器基础概念开始介绍,着重讲解了常见的JIT优化技术,包括方法内联与逃逸分析,额外拓展了HotSpot虚拟机内置的C1、C2编译器及分层编译协作流程。

JIT即时编译器在运行时对Java字节码进行优化,极大地提升了Java程序的执行效率。不过也要求我们日常编写代码要注意一定的规范,让JIT发挥最大效果。比如控制方法的代码行数,避免写过长的代码方法,可以将复杂的逻辑拆分成多个小方法,提升方法内联的生效几率;另外也可以控制接口的实现数量,尽量不超过两个,降低方法内联的复杂度;以及注意在方法内创建对象时,尽量不让对象逃逸。

如果大家觉得内容有价值,不妨考虑点点赞,关注关注小豪,后续小豪将会继续更新其它Java相关文章,大家共同进步~

相关文章:

深入JVM:详解JIT即时编译器

文章目录 深入JVM&#xff1a;详解JIT即时编译器一、序言二、基础概念1、何为JIT即时编译2、热点代码 三、HotSpot内置的即时编译器1、C1编译器2、C2编译器3、分层编译3.1 协作流程 四、常见JIT优化技术1、方法内联2、逃逸分析&#xff08;1&#xff09;同步锁消除&#xff08;…...

ORBSLAM3_ROS_Ubuntu18_04环境搭建安装

orbslam3安装 ORB-SLAM3配置及安装教程&#xff08;2023.3&#xff09;_orbslam3安装-CSDN博客 换源&#xff0c;换成国内的 搜索software 安装工具 sudo apt install git sudo apt update sudo apt install gcc g cmake安装 cmake安装新版本 ubuntu20.04安装cmake详细…...

【opencv - C++ - Ubuntu】putText 显示中文最快方法

话不多说&#xff0c;直接上代码 #include <iostream> #include <opencv2/opencv.hpp> #include <opencv2/freetype.hpp>using namespace std; using namespace cv;int main(void) {Mat image(1000, 1800, CV_8UC3, Scalar(200,162,33));Ptr<freetype::F…...

百度网盘下载速度慢的解决办法

目录 一、背景 二、解决办法 1、点击三个竖点&#xff0c;再点设置 2、点击传输&#xff0c;再点击去开启该功能 3、点击同意&#xff0c;开启优化速率 三、结果 四、备注 一、背景 当你不是百度网盘会员时&#xff0c;你在使用百度网盘下载时&#xff0c;是否下载速度太…...

Python api接口 异步

Python API接口异步编程简介 在现代的软件开发中&#xff0c;大多数应用都需要通过API接口与其他系统进行交互。Python是一种非常流行的编程语言&#xff0c;因此许多开发者选择使用Python来构建他们的API接口。在一些情况下&#xff0c;API接口需要进行异步编程&#xff0c;以…...

Java 和 Kotlin 单例模式写法对比

目录 1、饿汉模式 Java 写法&#xff1a; Kotlin 写法&#xff1a; Kotlin 这段代码反编译&简化后如下&#xff1a; 2、懒汉模式&#xff0c;静态同步方法 Java 写法&#xff1a; Kotlin 写法&#xff1a; Kotlin 这段代码反编译&简化后如下&#xff1a; 3、懒…...

解析connectionReset异常的原因与解决方案

解析connectionReset异常的原因与解决方案 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将深入探讨Java中connectionReset异常的原因及其解决方案。这…...

mindspore打卡第9天 transformer的encoder和decoder部分

mindspore打卡第9天 transformer的encoder和decoder部分 import mindspore from mindspore import nn from mindspore import ops from mindspore import Tensor from mindspore import dtype as mstypeclass ScaledDotProductAttention(nn.Cell):def __init__(self, dropout_…...

Python实现IPv4地址和16进制互相转换

Python实现IPv4地址和16进制互相转换 import socketdef ip_to_hex16(ipaddr):# 使用 socket 库中的方法将IP地址转换为网络字节序的二进制表示hex_bytes socket.inet_aton(ipaddr)# 将二进制数据转换为整数, 其中byteorderbig 表示使用大端字节序&#xff08;从高位到低位&…...

计算机视觉 | 基于图像处理和边缘检测算法的黄豆计数实验

目录 一、实验原理二、实验步骤1. 图像读取与预处理2. 边缘检测3. 轮廓检测4. 标记轮廓序号 三、实验结果四、完整代码 Hi&#xff0c;大家好&#xff0c;我是半亩花海。 本实验旨在利用 Python 和 OpenCV 库&#xff0c;通过图像处理和边缘检测算法实现黄豆图像的自动识别和计…...

深入分析 Android BroadcastReceiver (七)

文章目录 深入分析 Android BroadcastReceiver (七)1. 高级应用场景1.1 示例&#xff1a;动态权限请求1.2 示例&#xff1a;应用内通知更新 2. 安全性与性能优化2.1 示例&#xff1a;设置权限防止广播攻击2.2 示例&#xff1a;使用 LocalBroadcastManager2.3 示例&#xff1a;在…...

C++中的数据结构

一.STL标准库 结构:STL中有六大组件&#xff0c;分别是&#xff1a;容器&#xff0c;算法&#xff0c;迭代器&#xff0c;仿函数&#xff0c;配接器&#xff0c;配置器&#xff1b;以下分别介绍这六大组件中的最主要的三个。 1.容器 容器来配置存储空间&#xff0c;算法通过…...

武汉星起航:一站式服务,助力亚马逊卖家高效运营,实现收益飞跃

在跨境电商的浪潮中&#xff0c;武汉星起航电子商务有限公司以其独特的一站式跨境电商服务&#xff0c;为众多亚马逊卖家提供了强有力的支持&#xff0c;助力他们在不断发展的市场中脱颖而出&#xff0c;实现收益的大幅提升。 武汉星起航的一站式跨境电商服务&#xff0c;以其…...

从灵感到实践:Kimi辅助完成学术论文选题的文艺之旅

学境思源&#xff0c;一键生成论文初稿&#xff1a; AcademicIdeas - 学境思源AI论文写作 昨天我们为大家介绍了ChatGPT辅助完成实现设计&#xff08;AI与学术的交响&#xff1a;ChatGPT辅助下的实验设计新篇章&#xff09;。今天我们再来看看Kimi对于论文选题都能提供哪些帮助…...

华为od-C卷200分题目4 -电脑病毒感染

华为od-C卷200分题目4 -电脑病毒感染 一个局域网内有很多台电脑&#xff0c;分别标注为0 - N-1的数字。相连接的电脑距离不一样&#xff0c;所以感染时间不一样&#xff0c;感染时间用t表示。其中网络内一个电脑被病毒感染&#xff0c;其感染网络内所有的电脑需要最少需要多长…...

show-overflow-tooltip 解决elementui el-table标签自动换行的问题

elementui中 el-table中某一行的高度不想因为宽度不够而撑开换行展示的解决方法。可通过show-overflow-tooltip属性解决&#xff0c;如下 代码是这样的 <el-table-column width"80" prop"id" label"ID"></el-table-column> <el…...

数字社交的领航者:解析Facebook的引领作用

在当今数字化社会中&#xff0c;社交网络已经成为了人们日常生活不可或缺的一部分。而在众多社交平台中&#xff0c;Facebook凭借其巨大的用户基础和创新的技术应用&#xff0c;被公认为数字社交领域的领航者之一。本文将深入解析Facebook在数字社交中的引领作用&#xff0c;探…...

深度分析 Apache Flink 窗口机制

什么是 Flink 窗口&#xff1f; Apache Flink 是一个用于处理实时流数据的开源框架&#xff0c;其核心功能之一是窗口&#xff08;Window&#xff09;机制。窗口是 Flink 在处理流数据时用于划分数据流的逻辑概念&#xff0c;它将无限的流数据切割成有限的、可管理的部分&…...

ubuntu 软链接(ubuntu20.04)

ubuntu 软链接&#xff08;ubuntu20.04&#xff09; 在Ubuntu和其他Linux系统中&#xff0c;软链接&#xff08;也称为符号链接&#xff09;是文件系统中的一个特殊类型的文件&#xff0c;它作为一个引用或指针&#xff0c;指向另一个文件或目录。软链接类似于Windows中的快捷…...

如何在LabVIEW中使用FPGA模块

LabVIEW FPGA模块是NI公司推出的一款强大工具&#xff0c;它允许用户使用LabVIEW图形化编程环境来开发FPGA&#xff08;现场可编程门阵列&#xff09;应用程序。与传统的HDL&#xff08;硬件描述语言&#xff09;编程相比&#xff0c;LabVIEW FPGA模块大大简化了FPGA开发的过程…...

FPGA开发技能(7)Vivado设置bit文件加密

文章目录 前言1. AES加密原理2.xilinx的AES方案3.加密流程3.1生成加密的bit流3.2将密钥写入eFUSE寄存器 4.验证结论5.传送门 前言 在FPGA的项目发布的时候需要考虑项目工程加密的问题&#xff0c;一方面防止自己的心血被盗&#xff0c;另一方面也保护公司资产&#xff0c;保护知…...

【算法专题--链表】旋转链表 -- 高频面试题(图文详解,小白一看就懂!!)

目录 一、前言 二、题目描述 三、解题方法 ⭐解题思路---闭合为环 &#x1f34d; 案例图解 四、总结与提炼 五、共勉 一、前言 旋转链表 这道题&#xff0c;可以说是--链表专题--&#xff0c;最经典的一道题&#xff0c;也是在面试中频率最高的一道题目&#x…...

ElasticSearch 和 MySQL的区别

MySQLElasticSearch 数据库&#xff08;database&#xff09;索引&#xff08;index&#xff09;数据表&#xff08;table&#xff09; 类型&#xff08;type&#xff09; 记录文档&#xff08;document&#xff0c;json格式&#xff09; 一、ES基础命令 1. ES cat查询命令 2.…...

Linux部署wordpress站点

先安装宝塔面板 yum install -y wget && wget -O install.sh https://download.bt.cn/install/install_6.0.sh && sh install.sh ed8484bec 因为wordpress需要php&#xff0c;mysql&#xff0c;apache &#xff0c;httpd环境 参考&#xff1a;Linux 安装宝塔…...

实体零售连锁企业如何通过物流接口实现数智化转型升级?

在电子商务浪潮的持续冲击下&#xff0c;传统的实体零售行业面临着巨大的挑战。为了在线上线下融合的新零售时代保持竞争力&#xff0c;众多实体零售企业积极寻求数字化转型的突破。 某中国零售连锁百强企业近年来致力于打造自有品牌的线上销售体系&#xff0c;自2021年8月起接…...

AWS EKS上GPU工作负载自动扩缩容的异常排查指南

在AWS EKS上使用Karpenter和KEDA实现GPU工作负载的自动扩缩容是一个复杂的过程,涉及多个组件的协同工作。当遇到问题时,系统性的排查方法可以帮助我们快速定位和解决问题。本文将详细介绍如何对这个系统进行全面的异常排查。 1. Karpenter相关组件检查 1.1 NodePool检查 N…...

Pytest+Allure+Yaml+Jenkins+Gitlab接口自动化中Jenkins配置

一、背景 Jenkins&#xff08;本地宿主机搭建&#xff09; 拉取GitLab(服务器)代码到在Jenkins工作空间本地运行并生成Allure测试报告 二、框架改动点 框架主运行程序需要先注释掉运行代码&#xff08;可不改&#xff0c;如果运行报allure找不到就直接注释掉&#xff09; …...

应用及安全

目录 一、PAM 安全认证及配置 1.1配置 su 命令的认证 1.2PAM 配置文件结构二、账号和密码安全管理 2.1账号管理 2.2系统账号清理 2.3密码安全控制 2.4密码重设示例 2.5参考命令三、命令历史限制 3.1设置命令历史记录…...

字节流和字符流的相关知识

目录 1. Writer1.1 写两行数据1.2 换一种方式1.3 追加数据1.4 写很多数据&#xff0c;记得要清一下缓存1.5 用数组、字符串写入 2. Reader2.1 读个文件2.2 读取字符2.3 读取数据到数组2.4 复制文件 3. InputStream4. OutputStream5. 参考链接 1. Writer Writer类是Java.io包中…...

LLM意图识别器实践

利用 Ollama 和 LangChain 强化条件判断语句的智能提示分类 ❝ 本文译自Supercharging If-Statements With Prompt Classification Using Ollama and LangChain一文&#xff0c;以Lumos工具为例&#xff0c;讲解了博主在工程实践中&#xff0c;如何基于LangChain框架和本地LLM优…...

常见的反爬手段和解决思路(爬虫与反爬虫)

常见的反爬手段和解决思路&#xff08;爬虫与反爬虫&#xff09; 学习目标1 服务器反爬的原因2 服务器长反什么样的爬虫&#xff08;1&#xff09;十分低级的应届毕业生&#xff08;2&#xff09;十分低级的创业小公司&#xff08;3&#xff09;不小心写错了没人去停止的失控小…...

Stable Diffusion【真人模型】:人像光影摄影极限写实真实感大模型

大家好&#xff0c;我是极客菌 今天和大家分享一个基于SD1.5的真人大模型&#xff1a;人像光影摄影极限写实真实感大模型。 该模型具有以下特点&#xff1a; 真实肤感&#xff08;在面部肌理和皮肤肌理上均有加强学习&#xff0c;拒绝ai出图假的问题&#xff09; 永不脱妆&a…...

java实现图片添加水印

文章目录 前言一、工具类WatermarkUtil二、工具类介绍2.1 图片来源类型2.2 水印类型2.3 读取本地图片2.4 读取网络图片2.5 水印处理2.6 添加水印 三、测试添加水印总结 前言 给图片添加水印是一个很常见的需求&#xff0c;一般是用来防盗用。比如我们csdn上面写的文章中&#…...

CSS规则——font-face

font-face 什么是font-face&#xff1f; 想要让网页文字千变万化&#xff0c;仅靠font-family还不够&#xff0c;还要借助font-face&#xff08;是一个 CSS 规则&#xff0c;它允许你在网页上使用自定义字体&#xff0c;而不仅仅是用户系统中预装的字体。这意味着你可以通过提…...

【单片机毕业设计选题24034】-基于STM32的手机智能充电系统

系统功能: 系统可以设置充电时长&#xff0c;启动充电后按设置的充电时长充电&#xff0c;充电时间到后自动 停止充电&#xff0c;中途检测到温度过高也会结束充电并开启风扇和蜂鸣器报警。 系统上电后&#xff0c;OLED显示“欢迎使用智能充电系统请稍后”&#xff0c;两秒钟…...

[C++][数据结构][图][中][图的遍历][最小生成树]详细讲解

目录 1.图的遍历1.广度优先遍历2.深度优先遍历 2.最小生成树1.Kruskal算法2.Prim算法 1.图的遍历 给定一个图G和其中任意一个顶点 v 0 v_0 v0​&#xff0c;从 v 0 v_0 v0​出发&#xff0c;沿着图中各边访问图中的所有顶点&#xff0c;且每个顶 点仅被遍历一次 “遍历”&…...

退市新规解读—财务类强制退市

一、退市风险警示&#xff1a;第一年触及相关指标 上市公司最近一个会计年度触及下列退市风险指标之一&#xff0c;公司股票或存托凭证被实施退市风险警示(*ST)&#xff1a; 第1项 组合类财务指标 仅发行A股或B股&#xff0c;最近一个会计年度或追溯重述后最近一个会计年度 …...

小程序的生命周期使用方法和应用场景

小程序生命周期 初始化&#xff08;App Launch&#xff09; • 触发时机&#xff1a;小程序首次启动时。 • 主要事件&#xff1a;onLaunch。 • 功能与适用场景&#xff1a; • 全局数据初始化&#xff1a;设置应用的全局状态和变量。 • 登录状态检查&#xff1a;判断用户是…...

什么是C++模块化系统?C++20的模块化系统。

C20引入的模块化系统是一种新的代码组织和编译机制&#xff0c;它旨在替代传统的头文件机制&#xff0c;提供更好的代码组织、更快的编译速度和更强的封装性。模块化系统的主要目标包括&#xff1a; 减少编译时间&#xff1a;通过减少冗余的头文件解析和宏定义传播&#xff0c…...

智慧校园-档案管理系统总体概述

智慧校园档案管理系统&#xff0c;作为教育信息化进程中的重要一环&#xff0c;它运用现代信息技术的力量&#xff0c;彻底改变了传统档案管理的面貌&#xff0c;为学校档案资源的收集、整理、存储、检索与利用开辟了全新的途径。这一系统全面覆盖学生、教职工、教学科研及行政…...

文心一言 VS 讯飞星火 VS chatgpt (290)-- 算法导论21.3 3题

三、给出一个包含 m 个 MAKE-SET 、UNION 和 FINDSET 操作的序列(其中有 n 个是 MAKE-SET 操作)&#xff0c;当仅使用按秩合并时&#xff0c;需要 Ω(mlgn) 的时间。如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 在并查集&#xff08;Union-Find&#xff09;数…...

逻辑回归梯度推导

逻辑回归是一种广泛使用的分类算法&#xff0c;用于估计一个事件发生的概率。它是线性回归的扩展&#xff0c;通过sigmoid函数将线性回归的输出映射到[0, 1]区间&#xff0c;从而用于分类任务。 在逻辑回归中&#xff0c;我们使用对数似然损失函数&#xff08;log-likelihood l…...

Python 使用函数输出一个整数的逆序数

在Python中&#xff0c;你可以定义一个函数来输出一个整数的逆序数。这里有一个简单的实现方法&#xff1a; def reverse_integer(x):# 检查输入是否为整数if not isinstance(x, int):raise ValueError("Input must be an integer")# 将整数转换为字符串&#xff0c…...

【Linux】Wmware Esxi磁盘扩容

目录 一、概述 1.1 磁盘分区概念 1.2 LVM概念 二、扩容步骤 二、报错 一、概述 1.1 磁盘分区概念 在 Linux 中&#xff0c;每一个硬件设备都映射到一个系统的文件&#xff0c;对于硬盘、光驱等 IDE 或 SCSI 设备也不例外。Linux把各种 IDE 设备分配了一个由 hd 前缀组成的文…...

树莓派4B_OpenCv学习笔记15:OpenCv定位物体实时坐标

今日继续学习树莓派4B 4G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 版本是4.5.1&#xff1a; 今日学习 OpenCv定位物体实时位置&#xff0c;代码来源是…...

MySQL之如何定位慢查询

1、如何定位慢查询 1.1、使用开源工具 调试工具&#xff1a;Arthas 运维工具&#xff1a;Promethuss、Skywalking 1.2、MySQL自带慢日志 慢查询日志记录了所有执行时间超过指定参数&#xff08;long_query_time&#xff0c;单位&#xff1a;秒&#xff0c;默认10秒&#x…...

Open3D 删除点云中重复的点

目录 一、算法原理1、重叠点2、主要函数二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法原理 1、重叠点 原始点云克隆一份   构造重叠区域   合并点云获得重叠点 2、主要…...

填报志愿选专业是兴趣重要还是前景重要?

进行专业评估&#xff0c;找到一个适合自己的专业是一件非常困难的事情。在进行专业选择时&#xff0c;身上理想化色彩非常严重的人&#xff0c;会全然不顾及他人的劝阻&#xff0c;义无反顾的以兴趣为主&#xff0c;选择自己热爱的专业。一些较多考虑他人建议&#xff0c;能听…...

python开发基础——day9 函数基础与函数参数

一、初识函数(function) 编程函数!数学函数&#xff0c;里面的是逻辑&#xff0c;功能&#xff0c;而不是套公式 编程函数的作用实现特定操作的一段代码 你现在请客&#xff0c;每个人都点同样的一份吃的&#xff0c;请100个人 1.薯条 2.上校鸡块 3.可乐 那…...

STM32——使用TIM输出比较产生PWM波形控制舵机转角

一、输出比较简介&#xff1a; 只有高级定时器和通用寄存器才有输入捕获/输出比较电路&#xff0c;他们有四个CCR&#xff08;捕获/比较寄存器&#xff09;&#xff0c;共用一个CNT&#xff08;计数器&#xff09;&#xff0c;而输出比较功能是用来输出PWM波形的。 红圈部分…...