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

JVM之虚拟机运行

虚拟机运行快速复习

try-catch:catch-异常表+栈展开,finally-代码复制+异常表兜底

类的生命周期:加载,连接(验证,准备,解析),初始化,使用,卸载

类加载器:加载字节码.Class到JVM中生成一个Class对象

大部分类在具体用到的时候才会去加载(懒加载机制),已经加载的类会被放在 ClassLoader

对于一个类加载器来说,相同二进制名称的类只会被加载一次

类加载过程:

加载:通过类的全限定名获取该类的二进制字节流,存到类常量池,内存中生成Class对象

连接:

  1. 验证:验证Class二进制字节流合规
  2. 准备:为类对象分配内存
  3. 解析:符号引用转为直接引用

初始化:执行初始化方法

对象创建过程:类加载检查+分配内存+初始化零值+设置对象头+执行对象初始化方法

类加载器:

启动类加载器|
拓展类加载器|
应用程序类加载器|
自定义类加载器

因为启动类加载器是C++做的,所以获取到ClassLoader为NULL的时候就是启动类加载器

自定义类加载器:

需要继承 ClassLoader抽象类

不打破双亲委派机制:重写 ClassLoader 类中的 findClass()

打破双亲委派机制:重写 loadClass() 方法

类卸载:类无用的时候卸载

无用的类:所有实例被回收,类加载器被回收,Class对象没有任何引用

双亲委派机制:从下往上判断类是否被加载,从上往下尝试加载类

JVM 判定两个 Java 类是否相同的具体规则:全限定类名+类加载器

为什么要用双亲委派机制:可以避免类被重复加载,同时保证我们的核心API不被修改

如何实现热部署:自定义类加载器,并重写 ClassLoader 的 loadClass() ⽅法

热部署三步:

1)销毁原来的⾃定义 ClassLoader

2)更新 class 类⽂件

3)创建新的 ClassLoader 去加载更新后的 class 类⽂件


try-catch在jvm层面是怎么做的?

java中的try-catch通过异常表栈展开来实现

异常表(exception-table)

每个方法的字节码中都有一个异常表,用于记录try-catch块的作用范围对应的异常处理逻辑

异常表的每个条目包含以下信息:

起点,终点,处理代码的位置,捕获异常的类型

起点(start_pc):try块的起始指令偏移量

终点(end_pc):try块的结束指令偏移量(不包含该指令)

处理代码位置(handler_pc):catch块的第一条指令偏移量

捕获的异常类型(catch_type):要捕获的异常类(如java/lang/Exception),若为0表示捕获所有异常(finally块)

字节码结构

Exception table:start  end  handler  type0      10   13       java/io/IOException0      10   20       java/lang/Exception

异常处理流程

抛出异常,从异常表判断异常是否在处理逻辑内(也就是是否被try-catch{}包围),

代码中抛出异常时,JVM会执行以下步骤:

创建异常对象:实例化抛出的异常(如new IOException()

查找异常表:从当前方法的异常表中,按顺序匹配以下条件:

异常抛出的位置是否在某个条目的[start_pc, end_pc)范围内。

抛出的异常是否是catch_type的子类(或自身)

跳转到处理代码

若找到匹配条目,跳转到handler_pc执行catch

若未找到,触发栈展开:弹出当前栈帧,回到调用者方法重复上述过程。栈展开确保异常沿调用链向上传播,直到被处理或终止线程

未捕获异常:若所有栈帧均未处理异常,线程终止并打印堆栈跟踪


finally块的实现

finally 块的核心是:无论 try 或 catch 块中是否抛出异常或提前返回,finally 中的代码必须执行

为了实现这一点,JVM 的编译器(如 javac)在生成字节码时,会通过两种机制来确保 finally 的执行

finally块通过两种方式实现:

代码复制:编译器将finally代码复制到trycatch块的所有退出路径(包括return或异常抛出之后)。

异常表条目兜底:若finally需要处理异常退出,会生成一个catch_type=0的条目,捕获所有异常并执行finally代码,之后重新抛出异常


代码复制

编译器会将 finally 块中的代码复制到所有可能的退出路径,包括:

try 块正常结束后的退出路径。

catch 块处理完异常后的退出路径。

try 或 catch 块中的 return、break、continue 语句之前

java代码

public void example() {try {System.out.println("try");} catch (Exception e) {System.out.println("catch");} finally {System.out.println("finally");}
}

编译后的字节码逻辑

// try 块
L0:System.out.println("try");// 复制 finally 代码到 try 块末尾System.out.println("finally");return;// catch 块
L1:System.out.println("catch");// 复制 finally 代码到 catch 块末尾System.out.println("finally");return;// 异常表条目(自动处理异常后的 finally)
Exception table:start=L0, end=L0, handler=L1, type=Exception

关键点:

finally 的代码会被复制到 try 和 catch 的末尾,确保正常流程下一定会执行

如果 try 或 catch 中有 return,编译器会先执行 finally 代码,再执行 return


异常表兜底(处理未捕获的异常)

如果 try 或 catch 块中抛出了未被捕获的异常,或者有 throw 语句,JVM 会通过异常表跳转到 finally 代码,执行后再重新抛出异常。

异常表条目

编译器会生成一个特殊的异常表条目用于捕获所有类型的异常(catch_type=0)

确保任何未处理的异常都会先执行 finally,再继续传播异常

java代码

public void example() {try {throw new IOException();} finally {System.out.println("finally");}
}

字节码的异常表会生成如下头目

Exception table:start=L0, end=L1, handler=L2, type=0  // type=0 表示捕获所有异常

对应的执行流程:

  1. try 块抛出 IOException
  2. JVM 查找异常表,发现 type=0 的条目(匹配所有异常)。
  3. 跳转到 handler=L2finally 代码的位置)执行 System.out.println("finally")
  4. 重新抛出异常,继续栈展开

假设代码中有 try 和 finally,但没有 catch:

try {throw new Exception();
} finally {System.out.println("finally");
}

执行步骤:

  1. try 块抛出异常,JVM 创建异常对象。
  2. 直接查找当前方法的异常表,找到 catch_type=0 的条目,跳转到 finally 代码。
  3. 执行 finally 块中的代码。
  4. 重新抛出异常,由外层调用者处理

简单总结

异常处理:异常表+栈展开

每个方法的字节码中都有一个异常表,用于记录try-catch块的作用范围对应的异常处理逻辑

记录

try的起点

try的终点

catch的位置(处理代码的位置)

捕获的异常类型

当出现异常的时候查找异常表,查看异常出现的位置,如果有try-catch,就跳转到catch进行处理

没有的话就进行栈展开,栈展开确保异常沿调用链向上传播,直到被处理或终止线程

finally块通过代码复制和异常表兜底,保证finally块必须执行

代码复制:

编译器将finally代码复制到trycatch块的所有退出路径(包括return或异常抛出之后)

异常表兜底:

如果 try 或 catch 块中抛出了未被捕获的异常,或者有 throw 语句,JVM 会通过异常表跳转到 finally 代码,执行后再重新抛出异常

编译器会生成一个特殊的异常表条目用于捕获所有类型的异常(catch_type=0)

确保任何未处理的异常都会先执行 finally,再继续传播异常


能说一下类的生命周期吗

⼀个类从被加载到虚拟机内存中开始,到从内存中卸载,整个⽣命周期需要经过七个阶段

加载 (Loading)

连接:{

验证(Verification)、

准备(Preparation)、

解析(Resolution)、

}

初始化 (Initialization)

使⽤(Using)

卸载(Unloading)


什么是类加载器

类加载器是一个负责加载类的对象,用于实现类加载过程中的加载这一步
1.每个 Java 类都有一个引用指向加载它的 ClassLoader
2.数组类不是通过 ClassLoader 创建的(数组类没有对应的二进制字节流),是由 JVM 直接生成

简单来说,类加载器的主要作用就是加载 Java 类的字节码( .class 文件)到 JVM 中(在内存中生成一个代表该类的 Class 对象)

字节码可以是 Java 源程序(.java文件)经过 javac 编译得来,也可以是通过工具动态生成或者通过网络下载得来
其实除了加载类之外,类加载器还可以加载 Java 应用所需的资源如文本、图像、配置文件、视频等等文件资源。本文只讨论其核心功能:加载类


类加载器是动态加载还是静态加载

JVM 启动的时候,并不会一次性加载所有的类,而是根据需要去动态加载

也就是说,大部分类在具体用到的时候才会去加载(懒加载机制),这样对内存更加友好

对于已经加载的类会被放在 ClassLoader

在类加载的时候,系统会首先判断当前类是否被加载过,已经被加载的类会直接返回,否则才会尝试加载

也就是说,对于一个类加载器来说,相同二进制名称的类只会被加载一次


类加载的过程知道吗

 

加载是 JVM 加载的起点,具体什么时候开始加载,《Java 虚拟机规范》中并没有进⾏强制约束,可以交给虚拟机 的具体实现来⾃由把握。

类加载过程:加载,连接{验证,准备,解析},初始化


加载

加载过程JVM 要做三件事情:

1)通过⼀个类的全限定名来获取定义此类的⼆进制字节流

2)将这个字节流所代表的静态存储结构转化为方法区(因为包含类常量池)的运行时数据结构

3)在内存中⽣成⼀个代表这个类的 java.lang.Class 对象,作为⽅法区这个类的各种数据的访问入口

加载阶段结束后,Java 虚拟机外部的⼆进制字节流就按照虚拟机所设定的格式存储在⽅法区之中了,⽅法区中的数据存储格式完全由虚拟机实现⾃⾏定义,《Java 虚拟机规范》未规定此区域的具体数据结构。

类型数据妥善安置在⽅法区之后,会在 Java 堆内存中实例化⼀个 java.lang.Class 类的对象, 这个对象将作为程序访问⽅法区中的类型数据的外部接口


连接

验证(验证合法)

验证是连接阶段的第一步,这一阶段的目的是确保 Class 文件的字节流中包含的信息符合《Java 虚拟机规范》的全部约束要求,保证这些信息被当作代码运行后不会危害虚拟机自身的安全


准备(分配内存)

准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中分配


解析(符号引用转直接引用)

解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程


初始化

初始化阶段是执行初始化方法 <clinit> ()方法的过程,是类加载的最后一步,这一步 JVM 才开始真正执行类中定义的 Java 程序代码(字节码)


类加载总结

JVM 中内置了三个重要的 ClassLoader

  1. BootstrapClassLoader(启动类加载器):最顶层的加载类,由 C++实现,通常表示为 null,并且没有父级,主要用来加载 JDK 内部的核心类库( %JAVA_HOME%/lib目录下的 rt.jarresources.jarcharsets.jar等 jar 包和类)以及被 -Xbootclasspath参数指定的路径下的所有类。
  2. ExtensionClassLoader(扩展类加载器):主要负责加载 %JRE_HOME%/lib/ext 目录下的 jar 包和类以及被 java.ext.dirs 系统变量所指定的路径下的所有类。
  3. AppClassLoader(应用程序类加载器):面向我们用户的加载器,负责加载当前应用 classpath 下的所有 jar 包和类

除了这三种类加载器之外,用户还可以加入自定义的类加载器来进行拓展,以满足自己的特殊需求。就比如说,我们可以对 Java 类的字节码( .class 文件)进行加密,加载时再利用自定义的类加载器对其解密

除了 BootstrapClassLoader 是 JVM 自身的一部分之外,其他所有的类加载器都是在 JVM 外部实现的,并且全都继承自 ClassLoader抽象类。这样做的好处是用户可以自定义类加载器,以便让应用程序自己决定如何去获取所需的类

为什么 获取到 ClassLoadernull就是 BootstrapClassLoader 加载的呢?

这是因为BootstrapClassLoader 由 C++ 实现,由于这个 C++ 实现的类加载器在 Java 中是没有与之对应的类的,所以拿到的结果是 null


类加载器有哪些 

主要有四种类加载器:

  1. 启动类加载器(Bootstrap ClassLoader)⽤来加载 java 核⼼类库,⽆法被 java 程序直接引⽤。
  2. 扩展类加载器(extensions class loader):它⽤来加载 Java 的扩展库。Java 虚拟机的实现会提供⼀个扩展库⽬录。该类加载器在此⽬录⾥⾯查找并加载 Java 类。
  3. 系统类加载器(system class loader):它根据 Java 应⽤的类路径(CLASSPATH)来加载 Java 类。⼀般来说,Java 应⽤的类都是由它来完成加载的。可以通ClassLoader.getSystemClassLoader()来获取它。
  4. 用户自定义类加载器 (user class loader),⽤户通过继承 java.lang.ClassLoader 类的⽅式⾃⾏实现的类加载器


如何自定义类加载器 

我们前面也说说了,除了 BootstrapClassLoader 其他类加载器均由 Java 实现且全部继承自java.lang.ClassLoader。如果我们要自定义自己的类加载器,很明显需要继承 ClassLoader抽象类

ClassLoader 类有两个关键的方法:

  • protected Class loadClass(String name, boolean resolve):加载指定二进制名称的类,实现了双亲委派机制 name 为类的二进制名称,resolve 如果为 true,在加载时调用 resolveClass(Class<?> c) 方法解析该类。
  • protected Class findClass(String name):根据类的二进制名称来查找类,默认实现是空方法。

官方 API 文档中写到:

Subclasses of ClassLoader are encouraged to override findClass(String name), rather than this method.

建议 ClassLoader子类重写 findClass(String name)方法而不是loadClass(String name, boolean resolve) 方法

如果我们不想打破双亲委派模型

需要重写 ClassLoader 类中的 findClass() 方法即可,无法被父类加载器加载的类最终会通过这个方法被加载

如果我们想打破双亲委派模型

需要重写 loadClass() 方法


说一下类卸载

卸载类即该类的 Class 对象被 GC。

卸载类需要满足 3 个要求:

  1. 该类的所有的实例对象都已被 GC,也就是说堆不存在该类的实例对象。
  2. 该类没有在其他任何地方被引用
  3. 该类的类加载器的实例已被 GC

所以,在 JVM 生命周期内,由 jvm 自带的类加载器加载的类是不会被卸载的

但是由我们自定义的类加载器加载的类是可能被卸载的

只要想通一点就好了,JDK 自带的 BootstrapClassLoader, ExtClassLoader, AppClassLoader 负责加载 JDK 提供的类,所以它们(类加载器的实例)肯定不会被回收。而我们自定义的类加载器的实例是可以被回收的,所以使用我们自定义加载器加载的类是可以被卸载掉的


什么是双亲委派机制?

双亲委派模型的工作过程

双亲委派模型的⼯作过程:如果⼀个类加载器收到了类加载的请求,它⾸先不会⾃⼰去尝试加载这个类,⽽是把这个请求委派给父类加载器去完成,每⼀个层次的类加载器都是如此

因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去完成加载


双亲委派模型介绍

类加载器有很多种,当我们想要加载一个类的时候,具体是哪个类加载器加载呢?这就需要提到双亲委派模型了

  • ClassLoader 类使用委托模型来搜索类和资源
  • 双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应有自己的父类加载器
  • ClassLoader 实例会在试图亲自查找类或资源之前,将搜索类或资源的任务委托给其父类加载器

下图展示的各种类加载器之间的层次关系被称为类加载器的“双亲委派模型(Parents Delegation Model)

从下往上判断类是否被加载

从上往下尝试加载类

 


说一下双亲委派模型的执行流程 

简单总结一下双亲委派模型的执行流程:

1.在类加载的时候,系统会首先判断当前类是否被加载过。已经被加载的类会直接返回,否则才会尝试加载(每个父类加载器都会走一遍这个流程)。

2.类加载器在进行类加载的时候,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成(调用父加载器 loadClass()方法来加载类)。这样的话,所有的请求最终都会传送到顶层的启动类加载器 BootstrapClassLoader

3.只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载(调用自己的 findClass() 方法来加载类)。

4.如果子类加载器也无法加载这个类,那么它会抛出一个 ClassNotFoundException 异常

拓展一下:

JVM 判定两个 Java 类是否相同的具体规则:JVM 不仅要看类的全名是否相同,还要看加载此类的类加载器是否一样。只有两者都相同的情况,才认为两个类是相同的。即使两个类来源于同一个 Class 文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相同


为什么要用双亲委派机制

 

答案是为了保证应⽤程序的稳定有序

例如类 java.lang.Object,它存放在 rt.jar 之中,通过双亲委派机制,保证最终都是委派给处于模型最顶端的启动类加载器进⾏加载保证 Object 的⼀致

反之,都由各个类加载器⾃⾏去加载的话,如果⽤户⾃⼰也编写了⼀个名为 java.lang.Object 的类,并放在程序的 ClassPath 中,那系统中就会出现多个不同的 Object 类

可以避免类被重复加载,同时保证我们的核心API不被修改


说一下双亲委派模型的好处

双亲委派模型保证了 Java 程序的稳定运行,可以避免类的重复加载(JVM 区分不同类的方式不仅仅根据类名,相同的类文件被不同的类加载器加载产生的是两个不同的类)

保证了 Java 的核心 API 不被篡改

如果没有使用双亲委派模型,而是每个类加载器加载自己的话就会出现一些问题:

比如我们编写一个称为 java.lang.Object 类的话,那么程序运行的时候,系统就会出现两个不同的 Object 类。双亲委派模型可以保证加载的是 JRE 里的那个 Object 类,而不是你写的 Object

这是因为 AppClassLoader 在加载你的 Object 类时,会委托给 ExtClassLoader 去加载,而 ExtClassLoader 又会委托给 BootstrapClassLoaderBootstrapClassLoader 发现自己已经加载过了 Object 类,会直接返回,不会去加载你写的 Object

可以避免类被重复加载,同时保证我们的核心API不被修改


如何破打破双亲委派机制 

 

自定义加载器的话,需要继承 ClassLoader

如果我们不想打破双亲委派模型,就重写 ClassLoader 类中的 findClass() 方法即可,无法被父类加载器加载的类最终会通过这个方法被加载。

但是,如果想打破双亲委派模型则需要重写 loadClass() 方法

 


我们有什么场景需要破坏我们的双亲委派机制

 

自定义类场景

破坏双亲委派机制的场景
1. 动态加载和热更新:

在某些开发环境中,可能需要动态加载新的类或更新现有类。为了实现热更新,可能需要创建一个自定义的类加载器,绕过双亲委派机制,以便直接加载新的类定义。

2. 插件架构:

在插件系统中,可能需要允许插件直接使用特定的类,而这些类可能与主应用程序中的类同名。通过自定义类加载器,可以避免加载主应用程序中的同名类,从而实现插件的独立性。

3. 隔离不同版本的库:

有时,应用程序可能需要同时使用同一库的不同版本。通过创建不同的类加载器,可以加载不同版本的库而不发生冲突,从而破坏双亲委派机制。

4. 安全性需求:

在某些安全敏感的应用场景中,可能需要自定义类加载器以实现更严格的安全控制。例如,可以限制某些类的加载,或加载特定来源的类。

5. 测试和调试:

在单元测试或调试过程中,可能需要加载特定版本的类或模拟某些类的行为。自定义类加载器可以帮助实现这种需求


你觉得应该怎么实现一个热部署功能

 

Java类的加载过程

我们已经知道了 Java 类的加载过程。⼀个 Java 类⽂件到虚拟机⾥的对象,要经过如下过程:

⾸先通过 Java 编译器,将 Java ⽂件编译成 class 字节码,

类加载器读取 class 字节码,再将类转化为实例,

对实例 newInstance 就可以⽣成对象。

类加载器 ClassLoader 的功能

也就是将 class 字节码转换到类的实例。在 Java 应⽤中,所有的实例都是由类加载器加载而来

⼀般在系统中,类的加载都是由系统⾃带的类加载器完成,

⽽且对于同⼀个全限定名的 java 类(如 com.csiar.soc.HelloWorld)

只能被加载⼀次,而且无法被卸载

这个时候问题就来了,如果我们希望将 java 类卸载,并且替换更新版本的 java 类,该怎么做呢?

既然在类加载器中,Java 类只能被加载⼀次,并且⽆法卸载。

那么我们是不是可以直接把 Java 类加载器干掉呢?

答案是可以的

自定义类加载器

我们可以⾃定义类加载器,并重写 ClassLoader 的 findClass ⽅法。

想要实现热部署可以分以下三个步骤:

1)销毁原来的⾃定义 ClassLoader

2)更新 class 类⽂件

3)创建新的 ClassLoader 去加载更新后的 class 类⽂件。

到此,⼀个热部署的功能就这样实现了


Tomcat 的类加载机制了解吗

Tomcat 是主流的 Java Web 服务器之⼀,为了实现⼀些特殊的功能需求,⾃定义了⼀些类加载器。

Tomcat 类加载器如下:

Tomcat 实际上也是破坏了双亲委派模型的

Tomact 是 web 容器,可能需要部署多个应⽤程序。不同的应⽤程序可能会依赖同⼀个第三⽅类库的不同版本,但是不同版本的类库中某⼀个类的全路径名可能是⼀样的。如多个应⽤都要依赖 hollis.jar,但是 A 应⽤需要依赖1.0.0 版本,但是 B 应⽤需要依赖 1.0.1 版本。这两个版本中都有⼀个类是 com.hollis.Test.class。如果采⽤默认的双亲委派类加载机制,那么⽆法加载多个相同的类

所以,Tomcat 破坏了双亲委派原则,提供隔离的机制,为每个 web 容器单独提供⼀个 WebAppClassLoader 加载器。每⼀个 WebAppClassLoader 负责加载本身的⽬录下的 class ⽂件,加载不到时再交 CommonClassLoader加载,这和双亲委派刚好相反

相关文章:

JVM之虚拟机运行

虚拟机运行快速复习 try-catch&#xff1a;catch-异常表栈展开&#xff0c;finally-代码复制异常表兜底 类的生命周期&#xff1a;加载&#xff0c;连接&#xff08;验证&#xff0c;准备&#xff0c;解析&#xff09;&#xff0c;初始化&#xff0c;使用&#xff0c;卸载 类…...

玩转ChatGPT:DeepSeek实战(统一所在地格式)

一、写在前面 前段时间去交流&#xff0c;又被问到一个实际问题&#xff1a; 在组织全区活动时&#xff0c;我们设计了一份签到表&#xff0c;其中包含“所在单位地区”一列&#xff0c;目的是希望按地级市&#xff08;如南宁市、柳州市等&#xff09;对参与者进行分组&#…...

蓝桥杯题库经典题型

1、数列排序&#xff08;数组 排序&#xff09; 问题描述 给定一个长度为n的数列&#xff0c;将这个数列按从小到大的顺序排列。1<n<200 输入格式 第一行为一个整数n。 第二行包含n个整数&#xff0c;为待排序的数&#xff0c;每个整数的绝对值小于10000。 输出格式 输出…...

极限学习机进行电厂相关数据预测

使用极限学习机&#xff08;Extreme Learning Machine, ELM&#xff09;进行电厂相关数据预测的详细步骤和MATLAB代码示例。假设任务是预测电厂发电量或设备状态&#xff08;如温度、压力&#xff09;&#xff0c;代码包含数据预处理、ELM模型构建、训练与预测全过程。 1. 数据…...

【Axure视频教程】中继器表格间批量控制和传值

今天教大家在Axure中制作中继器表格间批量控制和传值的原型模板&#xff0c;效果包括&#xff1a; 选中和取消选中——点击表格中的多选按钮可以选中或取消选中该行内容&#xff1b; 全选和全部取消选中——点击表头左上角的多选按钮可以选中或取消选中表格的所有内容&#xf…...

Axure高级交互设计:文本框循环赋值实现新增、修改和查看

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢!本文如有帮助请订阅本专栏! Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 课程主题:文本框循环赋值 主要内容:使用设置文本动作实现文本框、文字标签的读取与赋值 应…...

Springboot之类路径扫描

SpringBoot框架中默认提供的扫描类为&#xff1a;ClassPathBeanDefinitionScanner。 webFlux框架中借助RepositoryComponentProvider扫描符合条件的Repository。 public class ClassPathScanningCandidateComponentProvider{private final List<TypeFilter> includeFilt…...

是 OpenCV 的 CUDA 模块中用于在 GPU 上对图像或矩阵进行转置操作函数cv::cuda::transpose

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::cuda::transpose 是 OpenCV 的 CUDA 模块中的一个函数&#xff0c;用于在 GPU 上对图像或矩阵进行转置操作&#xff08;Transpose&#xff0…...

2025B卷 - 华为OD机试七日集训第1期 - 按算法分类,由易到难,循序渐进,玩转OD

目录 推荐刷题方法&#xff1a; 一、适合人群二、本期训练时间三、如何参加四、七日集训第1期五、精心挑选21道高频100分经典题目&#xff0c;作为入门。第1天、逻辑分析第2天、逻辑分析第3天、逻辑分析第4天第5天第6天第7天 六、集训总结国内直接使用最新o3、o4-mini-high、GP…...

从数据中台到数据飞轮:数字化转型的演进之路

从数据中台到数据飞轮&#xff1a;数字化转型的演进之路 数据中台 数据中台是企业为整合内部和外部数据资源而构建的中介层&#xff0c;实现数据的统一管理、共享和高效利用&#xff0c;目标是打破信息孤岛&#xff0c;提高数据使用效率&#xff0c;支持业务决策和创新 实施成本…...

【Linux网络】HTTPS

HTTPS协议原理 定义 HTTPS 也是一个应用层协议.是在HTTP协议的基础上引入了一个加密层. HTTP 协议内容都是按照文本的方式明文传输的.这就导致在传输过程中会出现一些被篡改的情况。 加密 加密就是把明文(要传输的信息)进行一系列变换,生成密文. 解密就是把密文再进行一系…...

UE5中制作动态数字Decal

在进行城市道路编辑时&#xff0c;经常需要绘制人行道、交通标志、停车线等路面元素。如果能够使用具有动态修改功能的 Decal&#xff08;贴花&#xff09;&#xff0c;将大大提升编辑效率和灵活性。接下来讲解如何制作。 1.首先准备一张包含所需元素的Texture&#xff0c;这里…...

销量预测评估指标

销量预测评估指标 一、背景 在零售、供应链等场景中&#xff0c;销量预测的准确性直接影响库存管理、成本控制和客户满意度&#xff1a; 预测偏低&#xff1a;可能导致缺货&#xff08;损失销售额和客户信任&#xff09;。预测偏高&#xff1a;导致库存积压&#xff08;增加…...

Unity3d 打包安卓平台(Android apk)报错Gradle build failed解决方法

问题 Unity3d 版本为2022.3.*版本&#xff0c;而且工程内部没有包含比较特殊的插件&#xff0c;安卓模块(module)也是随编辑一起安装&#xff0c;JDK、Android SDK Tools、Android NDK和Gradle都是默认安装。打包设置Project Settings也是默认设置&#xff0c;打包的工程不包含…...

STM32 启动文件分析

一、启动文件的核心作用 STM32启动文件&#xff08;如startup_stm32f10x_hd.s&#xff09;是芯片上电后执行的第一段代码&#xff0c;用汇编语言编写&#xff0c;主要完成以下关键任务&#xff1a; ​初始化堆栈指针&#xff08;SP&#xff09;​​ 设置主堆栈指针&#xff08…...

OSCP备战-Kioptrix4详细教程

目录 配置靶机 目标IP探测 ​编辑端口扫描 139/445端口 Samba 80端口获取shell 绕过lshell 方法一 ​编辑 方法二 ​编辑提权 内核漏洞 mysql udf提权 配置靶机 使用vm新建虚拟机&#xff0c;选择vmdk文件打开。 目标IP探测 arp-scan -l 得出目标IP&#xff1a;19…...

清华大学开源软件镜像站地址

清华大学开源软件镜像站&#xff1a; https://mirrors.tuna.tsinghua.edu.cn/...

java基础-package关键字、MVC、import关键字

1.package关键字&#xff1a; &#xff08;1&#xff09;为了更好管理类&#xff0c;提供包的概念 &#xff08;2&#xff09;声明类或接口所属的包&#xff0c;声明在源文件首行 &#xff08;3&#xff09;包&#xff0c;属于标识符&#xff0c;用小写字母表示 &#xff0…...

uniapp(vue3)动态计算swiper高度封装自定义hook

// useCalculateSwiperHeight.ts import { ref, onMounted } from vue;export function useCalculateSwiperHeight(headerSelector: string .header-search, tabsWrapperSelector: string .u-tabs .u-tabs__wrapper) {const swiperHeight ref<number>(0);// 封装uni.g…...

Java SpringMVC 和 MyBatis 整合项目的事务管理配置详解

目录 一、事务管理的基本概念二、在 SpringMVC 和 MyBatis 整合项目中配置事务管理1. 配置数据源2. 配置事务管理器3. 使用事务注解4. 配置 MyBatis 的事务支持5. 测试事务管理三、总结在企业级应用开发中,事务管理是确保数据一致性和完整性的重要机制。特别是在整合了 Spring…...

C++的历史与发展

目录 一、C 的诞生与早期发展 &#xff08;一&#xff09;C 语言的兴起与局限 &#xff08;二&#xff09;C 的雏形&#xff1a;C with Classes &#xff08;三&#xff09;C 命名与早期特性丰富 二、C 的主要发展历程 &#xff08;一&#xff09;1985 年&#xff1a;经典…...

亚马逊云科技:引领数字时代的云服务先锋

在数字经济浪潮席卷全球的当下&#xff0c;企业和个人面临着数据爆炸、业务快速迭代等诸多挑战&#xff0c;亟需强大且灵活的云计算能力助力发展。亚马逊云科技凭借多年深耕与创新&#xff0c;成为数字时代的云服务先锋&#xff0c;为用户打造全方位、高质量的云计算解决方案。…...

基于Java和PostGIS的AOI面数据球面面积计算实践

目录 前言 一、计算方法简介 二、球面面积计算 1、AOI数据转Polygon 2、Geotools面积计算 3、GeographicLib面积计算 4、PostGIS面积计算 三、结果分析 1、不同算法结果对比 2、与互联网AOI对比 3、与天地图测面对比 四、总结 前言 在现代地理信息系统&#xff08;G…...

新建一个reactnative 0.72.0的项目

npx react-native0.72.0 init ProjectName --version 0.72.0 下面是初始化&#xff0c;并且添加了对应路由的库依赖&#xff0c;Android项目能run起来的版本号 { "name": "ProjectName", "version": "0.0.1", "private&quo…...

计算机网络网络层(下)

一、互联的路由选择协议&#xff08;网络层控制层面内容&#xff09; &#xff08;一&#xff09;有关路由选择协议的几个概念 1.理想的路由算法 &#xff08;1&#xff09;理想路由算法应具备的特点&#xff1a;算法必须正确和完整的&#xff0c;算法在计算上应简单&#x…...

Visual studio 打包方法

1.扩展->搜索“”install“->下载 2.安装&#xff08;安装后重新启动visual studio&#xff09; 3.在已有的解决方案上右键 添加 ** 新建项目 4.在该模板下有三个文件夹 第一个文件夹&#xff08;Application Folder&#xff09;添加 你已有c#的releas 的程序exe 所在…...

ubuntu---100条常用命令

目录 一、文件与目录管理二、系统信息与管理三、用户与权限管理四、网络配置与管理五、软件包管理六、其他常用命令 在 Ubuntu 系统中&#xff0c;掌握常用命令能显著提升操作效率。以下是 100 条常用命令&#xff0c;涵盖文件管理、系统信息、用户权限、网络配置、软件包管理等…...

UI-TARS Desktop:用自然语言操控电脑,AI 重新定义人机交互

在人工智能技术飞速发展的今天,从文本生成到图像识别,AI 的能力边界不断被打破。而字节跳动近期开源的 UI-TARS Desktop,则将这一技术推向了更复杂的交互场景——通过自然语言直接控制计算机界面,实现了图形用户界面(GUI)的智能化自动化。这款工具不仅降低了操作门槛,更…...

Linux精确列出非法 UTF-8 字符的路径或文件名

Docker构建的时候报错:failed to solve: Internal: rpc error: code = Internal desc = grpc: error while marshaling: string field contains invalid UTF-8 1、创建一个test.sh文件 find . -print0 | while IFS= read -r -d file;...

ubuntu部署supabase

安装supabse https://supabase.com/docs/guides/local-development/cli/getting-started?queryGroupsplatform&platformlinux brew install supabase/tap/supabase supabase init supabase start需要使用brewuser进行安装&#xff1a; brew安装参考链接&#xff1a; ht…...

《Effective Python》第1章 Pythonic 思维总结——编写优雅、高效的 Python 代码

《Effective Python》第1章 Pythonic 思维总结——编写优雅、高效的 Python 代码 在编程的世界里&#xff0c;每个语言都有其独特的风格和最佳实践。对于 Python 而言&#xff0c;“Pythonic”已经成为描述遵循 Python 特定风格的代码的代名词。这种风格不仅让代码更易读、更简…...

线代第二章矩阵第八节逆矩阵、解矩阵方程

文章目录 逆矩阵定义推论可逆性质 解矩阵方程 逆矩阵 定义 设A为n阶方阵&#xff0c;若存在n阶方阵B,使ABBAE,那么A就是可逆阵&#xff0c; 只有方阵有资格讨论可逆还是不可逆 若A可逆&#xff0c;逆阵是唯一的 未必所有方阵都可逆&#xff01;&#xff01; 比方说&#…...

Java SE(12)——异常(Exception)

1.概念 在Java中&#xff0c;异常(Exception)是指程序在运行过程中发生的不正常情况 例如&#xff1a; 算数异常(ArithmeticException) 空指针异常(NullPointerException) 数组越界异常(ArrayIndexOutOfBoundsException) 根据上述的异常信息可以看出&#xff1a;每个具体的异…...

力扣算法---总结篇

5.13 数组总结 数组是存放在连续内存空间上的相同类型数据的集合。 数组可以方便的通过下标索引的方式获取到下标对应的数据。 正是因为数组在内存空间的地址是连续的&#xff0c;所以我们在删除或者增添元素的时候&#xff0c;就难免要移动其他元素的地址。 数组的元素是不…...

空指针检测方法

空指针检测有以下几种常见方法&#xff1a; 静态代码分析 工具检测 &#xff1a;利用专业的静态代码分析工具&#xff0c;如 国产的库博静态代码检测工具&#xff08;COBOT&#xff09;、Checkmarx、Fortify、PVS-Studio 等&#xff0c;这些工具可以在不实际运行程序的情况下…...

Kubernetes Horizontal Pod Autosscaler(HPA)核心机制解析

一、HPA设计目标 弹性伸缩&#xff1a;根据实时负载动态调整Pod副本&#xff0c;平衡资源利用率与服务可用性声明式管理&#xff1a;通过目标指标阈值定义扩缩容规则&#xff0c;而非手动干预多云兼容&#xff1a;无缝集成云原生监控体系&#xff0c;支持混合云场景 二、核心…...

现代化QML组件开发教程

现代化QML组件开发教程 目录 QML基础介绍QML项目结构基本组件详解自定义组件开发状态与过渡高级主题最佳实践 QML基础介绍 什么是QML QML (Qt Meta Language) 是一种声明式语言&#xff0c;专为用户界面设计而创建。它是Qt框架的一部分&#xff0c;让开发者能够创建流畅、…...

DeepBook 与 CEX 的不同

如果你曾经使用过像币安或 Coinbase 这样的中心化交易所&#xff08;CEX&#xff09;&#xff0c;你可能已经熟悉了订单簿系统 — — 这是一种撮合买卖双方进行交易的机制。而 DeepBook 是 Sui 上首个完全链上的中央限价订单簿。 那么&#xff0c;是什么让 DeepBook 如此独特&…...

《构建社交应用的安全结界:双框架对接审核API的底层逻辑与实践》

用户生成内容如潮水般涌来。从日常的生活分享&#xff0c;到激烈的观点碰撞&#xff0c;这些内容赋予社交应用活力&#xff0c;也带来管理难题。虚假信息、暴力言论、侵权内容等不良信息&#xff0c;如同潜藏的暗礁&#xff0c;威胁着社交平台的健康生态。内容审核机制&#xf…...

hashicorp vault机密管理系统的国产化替代:安当SMS凭据管理系统,量子安全赋能企业密钥管理

引言&#xff1a;国产化替代浪潮下的密钥管理新机遇 在数字化转型与信息安全自主可控的双重驱动下&#xff0c;企业级密钥管理市场正迎来前所未有的变革。传统海外解决方案如HashiCorp Vault虽功能强大&#xff0c;但在国产化适配、量子安全前瞻性布局等方面逐渐显现局限性。与…...

详解注意力机制

## 1. 引言 注意力机制&#xff08;Attention Mechanism&#xff09;是深度学习领域中的一项关键技术&#xff0c;最初源于人类视觉注意力的启发。在人类视觉系统中&#xff0c;我们能够快速识别图像中的重要区域&#xff0c;同时忽略不相关的部分。注意力机制将这种能力引入到…...

从 Vue3 回望 Vue2:响应式的内核革命

从 Vue3 回望 Vue2 02 | 响应式的内核革命&#xff1a;从 defineProperty 到 Proxy一、Vue2 的响应式系统&#xff1a;defineProperty 的极限边界1.1 基础实现机制1.2 Vue2 的典型痛点❌ 无法侦测新增属性❌ 无法拦截数组索引❌ 深层递归导致性能问题❌ 对象粒度低、不可统一代…...

[Java实战]Spring Boot 3构建 RESTful 风格服务(二十)

[Java实战]Spring Boot 3构建 RESTful 风格服务&#xff08;二十&#xff09; 一. 环境准备 openJDK 17&#xff1a;Spring Boot 3 要求 Java 17 及以上。Spring Boot 3.4.5&#xff1a;使用最新稳定版。Ehcache 3.10&#xff1a;支持 JSR-107 标准&#xff0c;兼容 Spring C…...

--openssl-legacy-provider is not allowed in NODE_OPTIONS 报错的处理方式

解决方案 Node.js 应用&#xff1a; 从 Node.js v17 开始&#xff0c;底层升级到 OpenSSL 3.0&#xff0c;可能导致旧代码报错&#xff08;如 ERR_OSSL_EVP_UNSUPPORTED&#xff09;。 通过以下命令启用旧算法支持&#xff1a; node --openssl-legacy-provider your_script.js…...

【MySQL】第三弹——表的CRUD进阶(一)数据库约束

文章目录 &#x1f680;数据库的约束<font color #FF0000 size3>约束类型:&#x1fa90;<font color #FF0000 size3>①.NOT NULL非空约束&#x1fa90;<font color #FF0000 size3>②.UNIQUE唯一性约束&#x1fa90;<font color #FF0000 size3>③.DEFAU…...

python通过curl访问deepseek的API调用案例

废话少说&#xff0c;开干&#xff01; API申请和充值 下面是deepeek的API网站 https://platform.deepseek.com/ 进去先注册&#xff0c;是不是手机账号密码都不重要&#xff0c;都一样&#xff0c;完事充值打米&#xff0c;主要是打米后左侧API Keys里面创建一个API Keys&am…...

哈希表:数据世界的超级索引

在数据的浩瀚宇宙中&#xff0c;哈希表就像是一座超级图书馆的索引系统&#xff0c;能够让我们瞬间找到所需的信息。作为 C 算法小白&#xff0c;今天我就带大家一起探索这座神奇的图书馆&#xff0c;揭开哈希表的神秘面纱。 什么是哈希表&#xff1f; 哈希表&#xff08;Has…...

RDMA网络通信技术、NCCL集合通讯(GPU)

在高性能计算&#xff08;HPC&#xff09;、人工智能训练和数据密集型场景中&#xff0c;RDMA&#xff08;远程直接内存访问&#xff09; 和 NCCL&#xff08;NVIDIA Collective Communications Library&#xff09;是两项关键技术&#xff0c;用于优化节点间数据传输效率和大规…...

无人机失联保护模块技术解析!

一、技术要点 1. 信号监测与状态判断 实时信号质量评估&#xff1a;通过监测信号强度&#xff08;RSSI&#xff09;、误码率、信道质量等参数&#xff0c;动态判断是否触发失联保护。 多源冗余设计&#xff1a;结合GPS、视觉定位&#xff08;如底部光学/红外传感器&#x…...

用自写的jQuery库+Ajax实现了省市联动

1. 省市联动&#xff1a;在网页上&#xff0c;选择对应的省份之后&#xff0c;动态的关联出该省份对应的市。选择对应的市之后&#xff0c;动态地关联出城市对应的区。 2. 设计数据库表 t_area &#xff08;区域表&#xff09; id(PK-自增) code name pcode ------------…...