【JVM系列】- 寻觅·方法区的内容

寻觅·方法区的内容

😄生命不息,写作不止
🔥 继续踏上学习之路,学之分享笔记
👊 总有一天我也能像各位大佬一样
🌝分享学习心得,欢迎指正,大家一起学习成长!

在这里插入图片描述

文章目录

  • 寻觅·方法区的内容
    • 堆、栈、方法区的交互关系
    • 方法区的概念
      • 了解方法区
      • 设置方法区大小
        • jdk1.7及以前
        • jdk1.8及以后
      • OOM问题
    • *方法区的内部结构
      • 类型信息
      • 域(Field)信息
      • 方法(Method)信息
      • 常量池与运行时常量池
        • 常量池(Constant Pool)
        • 运行时常量池(Runtime Constant Pool)
        • 常量池与运行时常量池的区别
      • 通过字节码看结构
      • *方法区的演进
        • JDK1.6之前
        • JDK1.7
        • JDK1.8之后
        • 永久代为何被替换呢?
        • 字符串常量池(StringTable)为什么要做调整呢?
    • 方法区的垃圾回收机制
    • 总结

堆、栈、方法区的交互关系

在学习方法区之前已经是学习了堆和栈,现在我们就来回顾一下,来看看三者的交互关系是怎样的。
栈内存是用于存储方法的局部变量、形参和方法调用的状态信息。当一个方法被调用时,Java虚拟机会在栈内存中为该方法创建一个栈帧,用于存储方法的局部变量、形参等信息。当方法执行完毕后,该栈帧会被销毁。
堆内存是用于存储Java对象和数组。当一个对象被创建的时候,JVM会在堆内存中为该对象分配一块内存空间,用于存储对象的实例变量。对象的引用则会存储在栈内存中。当没有任何引用指向该对象时,该对象所占用的堆内存空间会被垃圾回收器回收。
方法区(Method Area)用于存储被虚拟机加载的类信息、常量池、静态变量等。方法区在JVM启动的时候被创建,并且它的实际的物理内存空间中和Java堆区一样可以是不连续的。方法区的大小,跟堆空间一样,可以选择固定大小或者可拓展。未命名文件 (16).png
在Java栈中的本地变量表中存放的是对象的引用地址,指向的是Java堆中的对象实例数据,在对象实例数据中有个到对象类型数据的指针,这个指针会指向这个类的类型数据,而这个类的类型结构就是被加载到方法区中。

方法区的概念

方法区在逻辑上是属于堆的一部分,但是在一些简单的实现可能不会选择去进行垃圾收集或进行压缩。但是对于HotspotJVM而言,方法区还有一个别名:Non-Heap(非堆),目的就是要和堆分开。方法区看作是一块独立于Java堆的内存空间。

了解方法区

  • 方法区(Method Area)与 Java 堆一样,是所有线程共享的内存区域。
  • 方法区(Method Area)是一块用于存储类信息、常量、静态变量、即时编译器优化后的代码等数据的内存区域。在不同的JVM实现中,方法区也被称为永久代(Permanent Generation,在Java 7及之前的版本中),或者是在Java 8及以后的版本中,被元数据区(Metaspace)取代。
  • 方法区在JVM启动的时候就会被创建,实际物理内存空间和Java堆区是一样都可以不连续。并且方法区的空间大小也是可以选择固定或者可扩展。
  • 方法区也是有内存溢出错误,当定义的类过多,导致方法区溢出,虚拟机会抛出OutOfMemoryError错误。
  • 在关闭JVM就会释放这个方法区的内存。

我们通过Java VisualVM就能看到方法的占用情况
在这里插入图片描述

设置方法区大小

方法区的大小可以通过参数来设置固定大小,不设置就是根据应用的需要动态调整。

jdk1.7及以前
  • 通过-XX:PermSize来设置永久代初始分配空间。默认是20.75M
  • 通过-XX:MaxPermSize来设置永久代最大可分配空间(32位默认64M,64位默认82M)。
  • 当JVM加载的类信息超过了这个值,就会报OutOfMemoryError:PermGen space
jdk1.8及以后
  • 元数据区大小可以使用参数-XX:MetaspaceSize-XX:MaxMetaspaceSize指定,替代上述原有的两个参数。
  • 默认值是与平台有关系,在windows下,-XX:MetaspaceSize是21M,-XX:MaxMetaspaceSize的值是-1,代表没有限制。
  • 与永久代不同,如果不指定大小,默认情况下,虚拟机会耗尽所有的可用系统内存。如果元数据发生溢出,虚拟机一样会抛出异常OutOfMemoryError:Metaspace
  • -XX:MetaspaceSize :设置初始的元空间大小。对于一个 64 位的服务器端 JVM 来说,其默认的 -XX:MetaspaceSize 的值为20.75MB,这就是初始的高水位线,一旦触及这个水位线,Full GC 将会被触发并卸载没用的类(即这些类对应的类加载器不再存活),然后这个高水位线将会重置,新的高水位线的值取决于 GC 后释放了多少元空间。如果释放的空间不足,那么在不超过MaxMetaspaceSize时,适当提高该值。如果释放空间过多,则适当降低该值。
  • 如果初始化的高水位线设置过低,上述高水位线调整情况会发生很多次,通过垃圾回收的日志可观察到 Full GC 多次调用。为了避免频繁 GC,建议将 -XX:MetaspaceSize 设置为一个相对较高的值。

OOM问题

从Java 8开始,随着永久代的去除,方法区OOM的问题在很大程度上得到缓解。在Java 8及以后的版本中,采用元数据区,可以根据应用程序的需要动态调整内存大小,从而更好地适应不同的应用场景。

OOM的排查与解决:

  • 可以使用JVM监控工具,例如VisualVM、JConsole或jstat,来监控方法区的使用情况。通过监控工具,你可以观察方法区的内存使用情况,及时发现潜在的OOM问题。在应用程序中,尤其是大型或长时间运行的应用程序中,可能会发生内存泄漏,导致方法区不断积累无用的类信息。通过内存分析工具,如Eclipse Memory Analyzer(MAT)或YourKit等,可以检查并解决潜在的内存泄漏问题。
  • 优化应用程序代码和配置,尽可能减少类的加载和卸载次数,合理使用缓存,以降低对方法区的压力。

*方法区的内部结构

方法区的内部结构包括常量池(Constant Pool)、类信息(包括接口、注解、方法等等信息)、静态变量、即时编译器生成的代码、运行时常量池等。
方法区的信息存储:

《深入理解Java虚拟机》书中对方法区存储内容的表述是:用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。随着jdk版本的不一样,对于这些存储信息也会有稍微的改变。

类型信息

方法区存储了加载的每个类的结构信息,包括类的字段、方法、父类、接口等。每个加载的类都有一个对应的Class对象,该对象包含了类的元信息。

对每个加载的类型(类 class、接口 interface、枚举 enum、注解 annotation),JVM 必须在方法区中存储以下类型信息:

  1. 这个类型需要是完整的类名(全限定名:包名.类名)
  2. 对于此类型的直接父类是需要完整有效名(对于interface或者java.lang.Object,都是没有父类)
  3. 这个类型的修饰符(public,abstract,final的某个子集)
  4. 这个类型直接接口的一个有序列表。(比如说一个接口实现了多个接口,这些被实现的接口是有序的)

域(Field)信息

  • JVM 必须在方法区中保存类型的所有域的相关信息以及域的声明顺序。
  • 域的相关信息包括:域名称、域类型、域修饰符(public、private、protected、static、final、volatile、transient 的某个子集)

对于静态变量(类变量),它们的信息除了存储在方法区中,还会在类加载时被分配在堆内存中,而不是对象实例的内存中。这是因为静态变量是属于类的,而不是对象的。

方法(Method)信息

方法信息包括类中的各种方法的相关数据,这些数据描述了方法的签名、访问修饰符、返回类型、方法体的字节码等。以下是方法区中存储的方法信息的一些关键点:

  • 方法名称
  • 方法的返回类型
  • 方法参数的数量和类型(需要按顺序)
  • 方法的修饰符(public,private,protected,static,final,synchronized,native,abstract 的一个子集)
  • 方法的字符码(bytecodes)、操作数栈、局部变量表及大小(abstract 和 native 方法除外)
  • 异常表(abstract 和 native 方法除外)
    • 每个异常处理的开始位置、结束位置、代码处理在程序计数器中的偏移地址、被捕获的异常类的常量池索引。

常量池与运行时常量池

常量池和运行时常量池都是用于存储字面量常量和符号引用的地方,但是二者是存在一些区别的。在方法区中,包含了运行时常量池(Runtime Constant Pool),要了解运行时常量池,就得先来了解一下常量池。

常量池(Constant Pool)

常量池是方法区的一部分,用于存储编译期生成的字面量和符号引用。常量池包括类和接口的全限定名、字段和方法的名称和描述符、字符串常量等。常量池是Class文件结构的一部分,但在加载到方法区时,它被存储为JVM的内部数据结构。

我们来了解一下常量池,它是在编译阶段由编译器生成并存储在 .class 文件中的一部分。也就是说,常量池虽然也是存储字面量和符号引用的地方,但是它主要是在编译期间确定的。所谓常量池,简单来说可以理解成一张表,虚拟机指令可以根据此表找到类名、方法名、参数类型、字面量等信息。
通过jclasslib这个idea插件可以直接查看字节码文件,可以从图中看到所谓的常量池,里面存储的类名等信息,开头[01]就是对应的常量池位置,例如#11也就对应常量池[11]
在这里插入图片描述

为什么需要常量池?

一个有效的字节码文件中除了包含类的版本信息、字段、方法以及接口等描述信息外,还包含一项信息那就是常量池表(Constant Pool Table),包含各种字面量和对类型、域和方法的符号引用。

一个 Java 源文件中的类、接口,编译后产生一个字节码文件。而 Java 中的字节码需要数据支持,通常这种数据会很大以至于不能直接存到字节码里,换另一种方式,可以存到常量池,这个字节码包含了指向常量池的引用。在动态链接的时候用到的就是运行时常量池。
在这里插入图片描述

如上图所示,字节码中链接#2对应的位置就是常量池中的[02]数据。

运行时常量池(Runtime Constant Pool)

运行时常量池与常量池相对应,运行时常量池是方法区的一部分,用于存储一些动态生成的常量,例如String对象的intern()方法生成的字符串常量。

  • 运行时常量池(Runtime Constant Pool)是在类加载阶段,就会创建对应的运行时常量池,将常量池的信息加载到内存中的一部分,属于方法区的一部分。
  • 常量池表(Constant Pool Table)是 字节码文件的一部分,用于存储编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
  • JVM 为每个已加载的类型(类或接口)都维护一个常量池。池中的数据项像数组项一样,是通过索引访问的。
  • 运行时常量池中包含各种不同的常量,包括编译器就已经明确的数值字面量,也包括到运行期解析后才能够获得的方法或字段引用。此时不再是常量池中的符号地址了,这里将是转换为真实地址。
  • 运行时常量池的内容可能会因为类的动态加载,这也就是运行时常量池相对于字节码文件常量池的另一个重要特征是:动态性
  • 当创建类或接口的运行时常量池时,如果构造运行时常量池所需的内存空间超过了方法区所能提供的最大值,则 JVM 会抛出 OutOfMemoryError 异常。
常量池与运行时常量池的区别

在 JVM 的方法区内部结构中,常量池和运行时常量池都是重要的组成部分。常量池在编译期确定,它包含了类的基本信息;而运行时常量池则在运行时加载,用于支持类的动态特性。运行时常量池通常也被认为是方法区的一部分。
二者的主要区别是:

  • ①常量池是 Java 类文件(.class 文件)的一部分,在编译期由编译器生成;常量池的数据在编译时已经确定,是类文件的一部分,不随着程序的运行而改变。
  • ②运行时常量池是在类加载阶段,将常量池的信息加载到内存中的一部分,属于方法区的一部分;运行时常量池的内容可能会因为类的动态加载、反射等操作而发生变化。

通过字节码看结构

接下来,我们使用一个demo,通过jclasslib来查看字节码信息,从而了解方法区的结构。
可以通过jclasslib插件也可以通过命令获取到字节码信息,这里我先将两种的方式做个比较。
首先使用命令来进行反编译,我们要先找到.class文件,并且将数据输出到txt文件中,命令如下:

# 切换到相应的地址
cd .\target\classes\com\lyd\testboot\jvm\
# 反编译
javap -v -p .\MethodAreaStructure.class > methodStructure.txt

我们来看一下两者数据的体现,都是用来查看反编译后的字节码信息。
在这里插入图片描述

首先,我们可以从jclasslib中看到,记录了父类以及实现的接口的类型信息,而这些数据都指向着常量池对应的索引。这些数据都会在classload加载到方法区中。

*注:加载到方法区中的类里面是记录了是哪个类加载器加载的,类加载器也会记录加载过哪些类。

在这里插入图片描述

接下来,我们看一下域信息,这些信息也是有classload加载到方法区中。其记录了域名称、域类型、域修饰符,并且这些都是有先后顺序的。
在这里插入图片描述

接着我们继续看方法,这里需要注意的是,在代码中并没有显式声明,但在编译的时候会自动加上无参构造方法,也就是对应着<init>,从jclasslib可以看到还有一个方法<clinit>,这是类的静态初始化块(static initializer),用于静态成员的初始化。
通过jclasslib来介绍一下方法信息还存储了什么,具体是怎么使用的。
在这里插入图片描述

为了方便查看这些都是什么信息,我这里将行号表、局部变量表的信息都截图粘在旁边,方便对应。首先,方法区还记会记录了栈的最大深度和局部变量表最大槽数。具体这些是对应了什么,笔者在之前的文章《探索·数据区的私有结构》都做了详细介绍,这里就不再做过多的赘述。
与javap输出的数据是一样的,只是用了不用的展示方式。

public void count();
  descriptor: ()V
  flags: ACC_PUBLIC
  Code:
    stack=2, locals=2, args_size=1
       0: iconst_0
       1: istore_1
       2: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       5: iload_1
       6: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
       9: return
    LineNumberTable:
      line 20: 0
      line 21: 2
      line 22: 9
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0      10     0  this   Lcom/lyd/testboot/jvm/MethodAreaStructure;
          2       8     1 count   I

还有一个重要的是,异常的情况。如下图,通过jclasslib中,在exceptionTest#Code下会多出一个StackMapTable(堆栈映射表)。 主要记录了在字节码的特定位置处的栈帧映射帧信息。每个栈帧映射帧描述了该位置处的局部变量表、操作数栈的类型状态,以及控制流的信息。
在Code中,能够看到异常表信息。里面会记录了异常开始的PC地址和结束的PC地址,以及触发异常之后需要跳转的PC地址,在通过行号表可以根据PC指向的地址对应到行号。
在这里插入图片描述

这里还需要注意的就是non-final的类变量

  • 静态变量和类关联在一起,随着类的加载而加载,成为类数据在逻辑上的一部分。
  • 类变量被类的所有实例共享,即使没有共享也能访问到。

例如一个简单的例子。我们定义一个静态变量,我们没有实例MethodAreaStructure对象,而是通过MethodAreaStructure.string的方法获得到这个字符串数据。即便我们创建了个null的对象,也能获得到。

public static void main(String[] args) {
    MethodAreaStructure methodAreaStructure = null;
    System.out.println(MethodAreaStructure.string);
    System.out.println(methodAreaStructure.string);
}

还有一种就是全局常量,使用static final修饰的。
被声明为final的类变量的处理方法则不同,每个全局常量在编译的时候,就已经会被分配了。

对于方法区的使用,字节码的PC包括本地变量表的变化是如何的,笔者在《探索·数据区的私有结构》一文中做了简单的介绍,后续再来补充细致化的描述。

*方法区的演进

Hotspot方法区的演变过程:(只有Hotspot才有永久代)

jdk1.6及之前有永久代,静态变量存放在永久代上
jdk1.7有永久代,但已经逐步“去永久代”,字符串常量池、静态变量移除,保存在堆中
jdk1.8及之后取消永久代,类型信息、字段、方法、常量保存在本地内存的元空间,但字符串常量池、静态变量仍在堆中
JDK1.6之前

在jdk1.6之前,方法区的落地是基于永久代(PermGen实现),其中包含了类型信息、域信息、方法信息、JIT代码缓存、静态变量和字符串常量池。
在这里插入图片描述

JDK1.7

在JDK1.7的时候,方法区的落地还是基于永久代(PermGen实现),内容的信息耶大多都不变,只不过就是把静态变量和字符串常量池提取到堆空间中了。所使用的内存还是虚拟机的内存,跟物理内存是存在着映射关系。
在这里插入图片描述

JDK1.8之后

在JDK1.8之后啊,就开始将永久代替换成了元数据区(Metaspace)来实现。使用的就不再是虚拟机内存,而是直接使用了物理内存,直接影响上限的是本地内存了。
在这里插入图片描述

永久代为何被替换呢?

替换永久代的动机可以通过官网找到答案,JEP 122: Remove the Permanent Generation, 找到Motivation标题的那段话,因为JRockit和Hotspot进行了融合,而JRockit客户不需要配置永久生成(因为JRockit没有永久生成),并且习惯于不配置永久生成,也就这样,所以永久代最后就被替换成了元数据区。
改动也是有必要的:

  • 永久代设置空间大小是很难确定的。如果动态加载很多类,就会很容易出现Perm区的OOM。而元空间并不在虚拟内存中,它依靠的是本地内存,所以,元空间在默认情况下只受本地内存的影响。
  • 对永久代进行的调优是很困难的。
字符串常量池(StringTable)为什么要做调整呢?

在JDK7中,StringTable就被放在了堆里了。这是因为永久代的回收效率很低,在full gc的时候才会触发。而full gc是因老年代空间不足、永久代不足时才会触发。这就会导致StringTable的效率不高。而正常开发来说,字符串会大量的被创建,回收效率低,导致永久代空间不足,但是放到堆里,就能够及时的回收。

方法区的垃圾回收机制

方法区的垃圾回收主要是两部分:常量池中废弃的常量不再使用的类型
先来说说方法区内常量池之中主要存放的两大类常量:字面量和符号引用。字面量比较接近 Java 语言层次的常量概念,如文本字符串、被声明为 final 的常量值等。而符号引用则属于编译原理方面的概念,包括下面三类常量:

  • 类和接口的全限定名
  • 字段的名称和描述符
  • 方法的名称和描述符

方法区的回收内容:

  • HotSpot 虚拟机对常量池的回收策略是很明确的,只要常量池中的常量没有被任何地方引用,就可以被回收。
  • 判定常量是否废弃是简单,但是判断一个类型是否属于“不再被使用的类”那就比较难的了,需要同时满足三个条件:
    • 该类的所有实例都已经被回收,也就是 Java 堆中不存在该类及其任何派生子类的实例。
    • 加载该类的类加载器已经被回收,这个条件除非是经过精心设计的可替换类加载器的场景,如 OSGi、JSP 的重加载等,否则通常很难达成。
    • 该类对应的 java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
  • Java 虚拟机被允许堆满足上述三个条件的无用类进行回收,这里说的仅仅是“被允许”,而并不是和对象一样,不使用了就必然会回收。是否对类进行回收,HotSpot 虚拟机提供了 -Xnoclassgc 参数进行控制,还可以使用 -verbose:class 以及 -XX:+TraceClassLoading 、-XX:+TraceClassUnLoading 查看类加载和卸载信息。
  • 在大量使用反射、动态代理、CGLib 等 ByteCode 框架、动态生成 JSP 以及 OSGi 这类频繁自定义 ClassLoader 的场景都需要虚拟机具备类卸载的功能,以保证永久代不会溢出。

总结

本次学完,算是把运行时数据区的内容算是弄完了,本章介绍了方法区的概念和其内存结构,详细的说明了里面各记录了什么信息,也通过了jclasslib插件反编译字节码来了解整体的逻辑关系。

👍创作不易,可能有些语言不是很通畅,如有错误请指正,感谢观看!记得点赞哦!👍

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Pyside6/PYQT6如何实现无边框设计,解决无边框窗口无法移动的问题

文章目录 💢 问题 💢💯 解决方案 💯🍔 准备工作🐾 操作步骤🐾 窗口无边框🐾 窗口透明🐾 实现窗口可移动⚓️ 相关链接 ⚓️💢 问题 💢 有时候我们需要一个无边框的UI设计来实现/美化一些功能,如:制作一个桌面时钟,进度条展示等,要实现无边框其实很简…

【 第十一章】软件设计师 之 面向对象设计与结构化分析设计

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 备考资料导航 软考好处&#xff1a;软考的…

【Proteus仿真】【Arduino单片机】LCD1602液晶显示

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器&#xff0c;使用LCD1602液晶等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602液晶显示各种效果。 二、软件设计 /* 作者&#xff1a;嗨小易&#x…

MSF图形化工具Viper快速安装

简介 Viper(炫彩蛇)是一款图形化内网渗透工具,将内网渗透过程中常用的战术及技术进行模块化及武器化. Viper(炫彩蛇)集成杀软绕过,内网隧道,文件管理,命令行等基础功能. Viper(炫彩蛇)当前已集成70个模块,覆盖初始访问/持久化/权限提升/防御绕过/凭证访问/信息收集/横向移动等…

【MySQL系列】 第二章 · SQL(下)

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

保姆级jupyter lab配置清单

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

通过SD卡给某摄像头植入可控程序

0x01. 摄像头卡刷初体验 最近研究了手上一台摄像头的sd卡刷机功能&#xff0c;该摄像头只支持fat32格式的sd卡&#xff0c;所以需要先把sd卡格式化为fat32&#xff0c;另外微软把fat32限制了最大容量32G&#xff0c;所以也只能用不大于32G的sd卡来刷机。 这里使用32G的sd卡来…

09 # 手写 some 方法

some 使用 some() 方法测试数组中是否至少有一个元素通过了由提供的函数实现的测试。如果在数组中找到一个元素使得提供的函数返回 true&#xff0c;则返回 true&#xff1b;否则返回 false。它不会修改数组。 ele&#xff1a;表示数组中的每一个元素index&#xff1a;表示数…

Unity中Shader的雾效

文章目录 前言一、Unity中的雾效在哪开启二、Unity中不同种类雾的区别1、线性雾2、指数雾1&#xff08;推荐用这个&#xff0c;兼具效果和性能&#xff09;3、指数雾2&#xff08;效果更真实&#xff0c;性能消耗多&#xff09; 三、在我们自己的Shader中实现判断&#xff0c;是…

vue设计原理-带你重走vue诞生路程

我们首先看下面这个小demo demo源码: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" conten…

RT-DETR 应用 CARAFE:特征内容感知重新组装

特征上采样是现代卷积神经网络架构中的关键操作,例如特征金字塔。其设计对于密集预测任务,如目标检测和语义/实例分割至关重要。在本研究中,我们提出了一种称为内容感知特征重组(CARAFE)的通用、轻量级且高效的操作符,以实现这一目标。CARAFE具有以下几个优点:(1)大的…

算法通关村第七关-青铜挑战二叉树的深度优先遍历(递归)

二叉树的深度优先遍历 今天我们来说二叉树的深度优先遍历 , 这次用简单但有点难理解的方式递归来实现 , 对应LeetCode 144,145 二叉树的前序遍历 描述 : 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 题目 : LeetCode 二叉树的前序遍历 : 144. 二叉…

【FAQ】Gradle开发问题汇总

1. buildSrc依赖Spring Denpendency时报错 来自预编译脚本的插件请求不能包含版本号。请从有问题的请求中删除该版本&#xff0c;并确保包含所请求插件io.spring.dependency-management的模块是一个实现依赖项 解决方案 https://www.5axxw.com/questions/content/uqw0grhttps:/…

K8S知识点(九)

&#xff08;1&#xff09;Pod详解-结构和定义 一级属性有下面这些&#xff1a;前两个属性是字符串&#xff0c;上面有定义 kind&#xff1a;Pod version&#xff1a;v1 下面的属性是object 还可以继续查看子属性&#xff1a;二级属性 还可以继续查看三级属性&#xff1a; 通…

微软近日限制员工访问ChatGPT!

作者 | 撒鸿宇 据CNBC报道&#xff0c;在这周四的短时间内&#xff0c;微软的员工被禁止使用ChatGPT。 微软在其内部网站的更新中表示&#xff1a;“由于安全和数据问题&#xff0c;一些AI工具不再对员工开放。”据CNBC查证&#xff0c;他们看到了一张截图&#xff0c;该截图显…

KubeSphere 社区双周报 | KubeSphere 3.4.1 发布 | 2023.10.27-11.09

KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书、新增的讲师证书以及两周内提交过 commit 的贡献者&#xff0c;并对近期重要的 PR 进行解析&#xff0c;同时还包含了线上/线下活动和布道推广等一系列社区动态。 本次双周报涵盖时间为&#xff1a;2023.10.27-2023.…

Nuxt.js——基于 Vue 的服务端渲染应用框架

文章目录 前言一、知识普及什么是服务端渲染什么是客户端渲染&#xff1f;服务端渲染与客户端渲染那个更优秀&#xff1f; 二、Nuxt.js的特点Nuxt.js的适用情况&#xff1f; 三、Vue是如何实现服务端渲染的&#xff1f;安装依赖使用vue安装 Nuxt使用npm install安装依赖包使用n…

UE特效案例 —— 角色刀光

目录 一&#xff0c;环境配置 二&#xff0c;场景及相机设置 三&#xff0c;效果制作 刀光制作 地裂制作 击打地面炸开制作 一&#xff0c;环境配置 创建默认地形Landscape&#xff0c;如给地形上材质需确定比例&#xff1b;添加环境主光源DirectionalLight&#xff0c;设…

3.如何实现 API 全局异常处理?-web组件篇

文章目录 1. 统一异常处理 1. 统一异常处理 在 Spring MVC 中&#xff0c;通过 ControllerAdvice ExceptionHandler 注解&#xff0c;声明将指定类型的异常&#xff0c;转换成对应的 CommonResult 响应。实现的代码&#xff0c;可见 GlobalExceptionHandler类。

【python】sys-path和模块搜索路径

我们在导入一个模块的时候&#xff0c;比如说&#xff1a; import math它必然是有搜索路径的&#xff0c;那到底是在哪个目录下面找呢&#xff1f;Python解释器去哪里找这个文件呢&#xff1f;只有找到这个文件才能读取、装载运行该模块文件。 它一般按照如下路径寻找模块文件…