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

JVM之类的初始化与类加载机制

类的初始化

clinit

  • 初始化阶段就是执行类构造器方法clinit的过程。
  • 此方法不需定义,是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并而来。
  • 构造器方法中指令按语句在源文件中出现的顺序执行。
  • clinit不同于类的构造器。(关联:构造器是虚拟机视角下的init
  • 若该类具有父类,JVM会保证子类的clinit执行前,父类的clinit已经执行完毕。
  • 虚拟机必须保证一个类的clinit方法在多线程下被同步加锁。

只有给类中的static的变量显示赋值或者静态代码块中赋值了,才会生成此方法.

哪些类不会生成clinit方法
  • 一个类中没有静态变量和静态代码块
  • 有静态变量,但是没有静态变量的显示赋值以及静态代码来执行初始化操作
  • 直接采用的 static final修饰的基本数据类型字段,这些字段在链接阶段的准备环节就已经初始化了
  • 不是显示常量赋值的话 而是调用方法去赋值还是会生成clinit方法的(在初始化阶段给他赋值)
clinit方法会死锁吗

虚拟机会保证一个类的clinit方法在多线程环境下被正确的加锁,同步(所以他多线程下是线程安全的),这同样会导致如果clinit方法中有耗时过场的操作,就可能导致线程阻塞而死锁,并且非常难以排查.

类加载的时机(什么情况会触发类的加载)

  • 当创建一个类的实例时,比如new关键字,或者是反射,克隆,反序列化等
  • 当调用类的静态方法时,即当使用了字节码invokestatic指令
  • 当使用类,接口的静态字段时(final修饰特殊考虑),比如使用getstatic或者putstatic指令
  • 当使用java.lang.reflect包中的方法反射类的方法时.比如Class.forname(“aa.bb.Test”)
  • 当初始化子类时,如果发现其父类还没有初始化,则需要先去触发父类的初始化
  • 如果一个接口定义了default方法,那么直接实现或者间接实现该接口的类初始化,该接口要在其之前被初始化
  • 当虚拟机启动时,用户需要指定一个要执行的主类(包含main方法的类),虚拟机会先初始化这个主类
  • 当初次调用MethodHandle实例时,初始化该MethodHandle指向方法所在的类

当Java虚拟机初始化一个类时,要求他所有的父类都已经被初始化,这条规则不适用于接口 \

  • 在初始化一个类时,并不会先初始化他所实现的接口
  • 在初始化一个接口时,并不会初始化他的父接口
    因此一个父接口并不会因为他的子接口或者实现类初始化而初始化,只有当程序首次使用特定接口的静态字段时,才会导致该接口初始化

被动使用不会触发类的初始化]

  • 通过子类引用父类的静态变量,不会导致子类初始化
  • 通过数组定义类引用,不会触发此类的初始化
  • 引用常量不会触发此类或接口的初始化,因为常量已经在链接准备阶段被显示赋值了
  • 调用ClassLoader类的loadClass()加载一个类,并不是对类的主动使用,不会导致类的初始化

被动的使用,意味着不需要执行初始化环节,意味着没有clinit的调用.

类的卸载

除非是你自定义的类加载器直接把这个类加载器也卸载掉(包括他下面的类),否则其他的已有的类加载器是不允许被卸载的,因为他们与类是双向绑定的关系.

类加载代码demo

public class T {public static int k = 0;public static T t1 = new T("t1");public static T t2 = new T("t2");public static int i = print("i");public static int n = 99;static {print("静态块");}public int j = print("j");{print("构造块");}public T(String str) {System.out.println((++k) + ":" + str + " i=" + i + "   n=" + n);++n;++i;}public static int print(String str) {System.out.println((++k) + ":" + str + " i=" + i + "   n=" + n);++n;return ++i;}public static void main(String[] args) {}
}

运行结果

1:j i=0   n=0
2:构造块 i=1   n=1
3:t1 i=2   n=2
4:j i=3   n=3
5:构造块 i=4   n=4
6:t2 i=5   n=5
7:i i=6   n=6
8:静态块 i=7   n=99

类的加载器

类的加载分类

  • 显示加载:调用ClassLoader类中的方法去显示的加载某个类
  • 隐式加载:是由jvm自动加载到内存中的,用到哪些加载哪些

类的唯一性

对于任意一个类,都需要由加载它的类加载器和这个类本身一同确认其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间,比较这两个类是否相等,只有在这两个类是由同一个类加载器加载的前提下才有意义

命名空间
  • 每个类加载器都有自己的命名空间,由该加载器及其所有的父类加载器所加载的类组成
  • 在同一命名空间中,不会出现类的完整名字(包括类的包名)相同的两个类
  • 在不同的命名空间,有可能出现类的完整名字(包括包名)相同的情况

在大型应用中,可以借助这个特性,来运行一个类的不同版本

类加载的三个基本特征

  • 双亲委派模型: 也有不用这个机制的 ,比如上下文加载器
  • 可见性: 子类加载器可以访问父类加载器的类型,但是反过来不被允许.
  • 单一性: 由于父类加载器对于子加载器是可见的,所以父类加载过的类,在子类中不会重复加载.

类加载的分类

JVM支持两种类型的类加载器,分别为引导类加载器(BootStrap ClassLoader)和自定义类加载器(User-Defined ClassLoader).
从概念上讲,自定义加载器应该是程序中由开发人员自定义的加载器,但是Java的虚拟机规范并没有如此定义,而是将所有派生于抽象类ClassLoader的类加载器都划分为自定义加载器,而引导类加载器是由C++源码是实现的,在Java环境中也根本获取不到

启动类加载器(BootStrap ClassLoader )
  • 这个类加载使用C/C++语言实现,嵌套在JVM内部
  • 他用来加载Java的核心库,用于提供JVM自身所需要的类
  • 不继承自ClassLoader,没有父加载器
  • 出于安全考虑,只加载包名为java,javax,sun等开头的类
  • 加载扩展类和应用程序类加载器,并指定为他们的父类加载器
扩展类加载器(Extension ClassLoader)
  • Java语言编写,由ExtClassLoader实现
  • 继承自ClassLoader类
  • 父类加载器为启动类加载器
  • 从java.ext.dirs系统属性所指定的目录中加载类库,或者从JDK的安装目录的jre/lib/ext子目录下加载类库,如果用户创建的jar放在此目录下,也会由扩展类加载器加载
应用程序加载器(系统类加载器 AppClassLoader)
  • Java语言编写,由AppClassLoader实现
  • 继承自ClassLoader类
  • 父类加载器为启动类加载器
  • 他负责加载环境变量classPath或系统属性java.class.path指定路径下的类库
  • 应用程序中的类加载器默认是系统类加载器
  • 他是用户自定义类加载器的默认父加载器
  • 通过ClassLoader的getSystemClassLoader()可以获取到该类加载器
用户自定义类加载器

通过类加载器可以实现非常绝妙的插件机制.自定义的类加载器能够实现应用隔离,tomcat和spring都在内部实现了自定义类加载器,这样的机制比c/c++要优秀太多,自定义的类加载器通常都需要继承自抽象类ClassLoader

ClassLoader源码分析

什么是双亲委派机制

在加载器加载类的时候,如果加载器有父类(一般是组合定义为父类),先让父类去加载,一层层往上找,如果父类都没有再由自己加载,否则由某一个父类加载进来.

关键方法源码分析
protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// First, check if the class has already been loadedClass<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {//在这里 Java源码判断了如果父类不为null,就去调用父类的加载方法,一直递归到最高的父类if (parent != null) {c = parent.loadClass(name, false);} else {c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) {// If still not found, then invoke findClass in order// to find the class.long t1 = System.nanoTime();c = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}
protected Class<?> findClass(String name) throws ClassNotFoundException {throw new ClassNotFoundException(name);}
protected final Class<?> defineClass(String name, byte[] b, int off, int len,ProtectionDomain protectionDomain)throws ClassFormatError{protectionDomain = preDefineClass(name, protectionDomain);String source = defineClassSourceLocation(protectionDomain);Class<?> c = defineClass1(name, b, off, len, protectionDomain, source);postDefineClass(c, protectionDomain);return c;}
private ProtectionDomain preDefineClass(String name,ProtectionDomain pd){if (!checkName(name))throw new NoClassDefFoundError("IllegalName: " + name);// Note:  Checking logic in java.lang.invoke.MemberName.checkForTypeAlias// relies on the fact that spoofing is impossible if a class has a name// of the form "java.*"if ((name != null) && name.startsWith("java.")) {throw new SecurityException("Prohibited package name: " +name.substring(0, name.lastIndexOf('.')));}if (pd == null) {pd = defaultDomain;}if (name != null) checkCerts(name, pd.getCodeSource());return pd;}
  • loadClass属于一个模板方法,不需要去重写他 否则有可能会破坏双亲委派机制
  • 子类可以去重写findClass方法,到这里是需要子类加载器自己去加载类方法了(有些像spring的感觉 新建和获取都是通过getSingletonBean去获取单例bean的)
  • defineClass是获取类的字节码流信息,并组装成class对象(这个方法也都会用到)
  • preDefineClass 中判断必须以java.开头,避免双亲委派机制遭到破坏时系统受到威胁(又加了一层判断确保安全性)
自定义类加载器
public class UserDefineClassLoader extends ClassLoader {private final String rootPath;public UserDefineClassLoader(String rootPath) {this.rootPath = rootPath;}@Overrideprotected Class<?> findClass(String name) {//转换为以文件路径表示的文件String filePath = classToFilePath(name);//获取指定路径的class文件对应的二进制流数据byte[] data = getBytesFromPath(filePath);//自定义ClassLoader 内部需要调用defineClass() 把二进制流还原为Class实例return defineClass(name, data, 0, data.length);}private byte[] getBytesFromPath(String filePath) {FileInputStream fis = null;ByteArrayOutputStream baos = null;try {fis = new FileInputStream(filePath);baos = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len;while ((len = fis.read(buffer)) != -1) {baos.write(buffer, 0, len);}return baos.toByteArray();} catch (IOException e) {throw new RuntimeException(e);} finally {if (baos != null) {try {baos.close();} catch (IOException e) {throw new RuntimeException(e);}}if (fis != null) {try {fis.close();} catch (IOException e) {throw new RuntimeException(e);}}}}private String classToFilePath(String name) {return rootPath + "\\" + name.replace(".", "\\") + ".class";}public static void main(String[] args) throws ClassNotFoundException {UserDefineClassLoader loader = new UserDefineClassLoader("D:\\code\\test");Class<?> aClass = loader.findClass("com.test.User");System.out.println(aClass);System.out.println(aClass.getClassLoader());}}

双亲委派类加载机制

优势与好处
  • 保护程序安全,防止核心的API类库被随意篡改
  • 避免类的重复加载,确保一个类的全局唯一性(当父类已经加载完成后,子类不会再去加载)
弊端
  • 下层的加载器可以访问上层父类的加载器都有什么类,但是上层是没有办法得知下层类加载器都有什么类,他是单向的
破坏双亲委派机制
  • 线程上下文加载器:(Thread.currentThread().getContextClassLoader()) jdbc等场景就是这么采用的
  • 热部署 (每一个程序模块都有一个自己的类加载器,当需要替换一个bundle时,就把bundle连同类加载器一起换掉以实现代码的热替换,这时候类加载处于一种更加复杂的网状结构)

tomcat的类加载机制

  • tomcat8可以配置<Loader delegate="true"/>表示遵循双亲委派机制
    类的结构图
    类的结构图
加载流程

当tomcat启动时,会创建几种类加载器
{fwtab}
{fwh}
{fwthead target=“1”} Bootstrap引导类加载器 {/fwthead}
{fwthead target=“2”} system系统类加载器 {/fwthead}
{fwthead target=“3”} tomcat自定义类加载器 {/fwthead}
{fwthead target=“4”} 加载顺序 {/fwthead}
{/fwh}
{fwb}
{fwtbody target=“1”}
加载jvm启动所需的类,以及标准扩展类(位于jre/lib/ext下)
{/fwtbody}
{fwtbody target=“2”}
加载tomcat启动的类,比如bootstrap.jar,通常在catalina.bat或者catalina.sh中指定,位于CATALINA_HOME/bin下
{/fwtbody}
{fwtbody target=“3”}
Common/Catalina/Shared/WebappClassLoader
这些是tomcat自己定义的类加载器,它们分别加载’/common/,/server/,/shared/*'(在tomcat6以后已经合并到了根目录的lib目录下)和/WebApp/WEB-INF/*中的Java类库,其中WebApp类加载器和jsp类加载器通常会存在多个实例,每一个web应用程序对应一个WebApp类加载器,每一个jsp文件对应一个jsp类加载器

  • CommonClassLoader,Tomcat最基本的类加载器,加载路径中的class可以被Tomcat容器本身以及各个WebApp访问(加载CATALINA_HOME/lib下的结构,比如servlet-api.jar)
  • CatalinaClassLoader,Tomcat容器私有的类加载器,加载路径中的class对于WebApp不可见
  • SharedClassLoader,各个WebApp共享的类加载器,加载路径中的class对于所有WebApp可见,但是对于Tomcat容器不可见
    {/fwtbody}
    {fwtbody target=“4”}
    当应用需要某个类时,则会按照下面的顺序进行类加载
  • 使用bootstrap引导类加载器加载
  • 使用system系统类加载器加载
  • 使用应用类加载器在WEB-INF/classes中加载
  • 使用应用类加载器在WEB-INF/lib中加载
  • 使用common类加载器在CATALINA_HOME/lib中加载
    {/fwtbody}
    {/fwb}
    {/fwtab}

从图中的委派关系可以看出:
CommonClassLoader能加载的类都可以被CatalinaClassLoader和SharedClassLoader使用,从而实现了公有类库的共用,而
CatalinaClassLoader和SharedClassLoader自己能加载到类则与对方相互隔离.
WebAPPClassLoader可以使用SharedClassLoader加载到的类,但是每个WebAPPClassLoader实例之间互相隔离.
而JsperLoader的加载范围仅仅是这个jsp文件所编译出来的一个.class文件,他出现的目的就是为了被丢弃,当web容器检测到jsp文件被修改时,会替换掉目前的JsperLoader实例再去重建一个新的,以实现jsp文件的热修改功能

tomcat不遵循双亲委派机制会有风险吗

tomcat不遵循双亲委派机制,只是自定义的ClassLoader加载顺序不同,没有去严格的遵循双亲委派机制(我个人觉得这个设计是为了给每个WebApp更好的设置隔离性,以避免互相干扰),但是核心的jdk的api也是遵循双亲委派去由顶层的加载器加载的(他自己的核心api也是有自己的加载器去专门加载,也没有恶意篡改的风险)

tomcat作为web容器,要解决的问题是什么
  • 一个web容器可能需要部署多个应用程序,不同的应用程序可能会依赖同一个第三方类库的不同版本,因此要保证每个应用程序的类库是独立的,保证相互的隔离性
  • 部署在用一个web容器中相同的类库相同的版本可以共享,否则就会出现多个相同的类加载进入虚拟机,显然这是要去尽力避免的
  • web容器自身也需要有一个自己的类库支持,他不能与应用的类库所混淆,基于安全上的考虑,应该让容器的类库和程序的类库相互隔离开
  • 支持jsp的热修改(那时候的jsp属于主流技术,还是非常流行的 现在都是动静分离,前后分离了)
如果Tomcat的CommonClassLoader想加载WebAppClassLoader中的类怎么办

用线程上下文加载器

为什么Java文件放在eclipse/idea中的src文件夹下会优先于jar包中的class

tomcat破坏双亲委派机制,自己指定的加载顺序 先使用应用类加载器在WEB-INF/classes中加载,再使用应用类加载器在WEB-INF/lib中加载

相关文章:

JVM之类的初始化与类加载机制

类的初始化 clinit 初始化阶段就是执行类构造器方法clinit的过程。此方法不需定义&#xff0c;是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并而来。构造器方法中指令按语句在源文件中出现的顺序执行。clinit不同于类的构造器。(关联&#xff1a;…...

面试专题:java 多线程(1)----synchronized关键字相关问答

在java 多线程 面试中最多问题1.悲观锁和乐观锁&#xff1b;2.synchronized和lock的区别&#xff1b;3.可重入锁和非可重入锁的区别&#xff1b;4.多线程是解决什么问题的&#xff1b;5.线程池解决什么问题的&#xff1b;6.线程池原理&#xff1b;7.线程池使用注意事项&#xf…...

VMware SD-WAN 5.2 发布 - 软件定义的 WAN

VMware SD-WAN 5.2 发布 - 软件定义的 WAN SD-WAN 解决方案的领导者 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-sd-wan-5/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 产品概述 软件定义的 WAN (SD-WAN)…...

Oracle+11g+RAC+PSU_EAM(2)

2.15 解压安装介质 在获取开篇1.2节中提到的安装介质如下&#xff1a; [rootebsrac1 ~]# ls -l -rw-r–r– 1 root root 1358454646 Apr 20 16:22 p13390677_112040_Linux-x86-64_1of7.zip -rw-r–r– 1 root root 1142195302 Apr 20 16:29 p13390677_112040_Linux-x86-64_…...

智能出行 驱动未来|2023 开放原子全球开源峰会 CARSMOS 开源智能出行生态年会即将启幕

由开放原子开源基金会主办&#xff0c;元遨 / CARSMOS 开源智能出行项目组协办&#xff0c;深信科创、Futurewei Technologies、Open Motors、北极雄芯等单位共同承办的 2023 开放原子全球开源峰会 “CARSMOS 开源智能出行生态年会” 将于 6 月 12 日在北京经开区北人亦创国际会…...

Linux:centos:周期性计划任务管理《crontab》

crontab常用基础属性 -e 编辑计划任务 -l 查看计划任务 -r 删除计划任务 -u 指定用户的计划任务 首先创建一个名为test的用户名 crontab时间规定 格式&#xff1a;分钟 小时 日期 月份 星期 命令 分钟-- 0-59整数 小时 -- 0-23整数 日期 -- 1--31 整数 月份 -- 1-12 整数 星期…...

克拉默法则证明(Cramer‘s Rule)

若 n 个方程 n 个未知量构成的非齐次线性方程组&#xff1a; { a 11 x 1 a 12 x 2 . . . a 1 n x n b 1 a 21 x 1 a 22 x 2 . . . a 2 n x n b 2 . . . . . . a n 1 x 1 a n 2 x 2 . . . a n n x n b n \begin{equation*} \begin{cases} a_{11}x_{1} a_ {12}x_{2}…...

【接口防刷】处理方案

【接口防刷】 欢迎使用【接口防刷】常见的处理方案访问次数和频率限制验证码校验登录校验机制数据交互加密异常监测机制附录 欢迎使用【接口防刷】常见的处理方案 接口防刷处理方案是指为了防止恶意攻击或非法数据采集&#xff0c;采取一系列技术措施来保护接口数据的安全和完…...

安装Linux-SUSE操作系统

文章目录 一、安装Linux-SUSE系统1、环境准备2、SUSE 镜像的下载2.1、下载企业服务器2.2、ARM和桌面的ISO 3、安装SUSE4、配置本地 yum 源5、SUSE常用安装命令6、在 SUSE系统上安装mysql数据库步骤&#xff1a;7、破解SUSE系统root密码 一、安装Linux-SUSE系统 1、环境准备 操…...

二、机器人的结构设计

1 、螺丝连接的坚固性 坚固性是机器人能顺利完成指定任务的一个重要条件&#xff0c;无论我们程序设计的如何完美&#xff0c; 如果不能保证机器人具有坚固性和稳定性&#xff0c;就无法保证任务的顺利完成&#xff0c;机器人在运行时如 果发生散架和分裂都会影响其功能的实现…...

UITableView学习笔记

看TableView的资料其实已经蛮久了&#xff0c;一直想写点儿东西&#xff0c;却总是因为各种原因拖延&#xff0c;今天晚上有时间静下心来记录一些最近学习的TableView的知识。下面进入正题&#xff0c;UITableView堪称UIKit里面最复杂的一个控件了&#xff0c;使用起来不算难&a…...

Nginx反向代理与负载均衡

简介 Nginx 是一款高性能、轻量级的 Web 服务器软件&#xff0c;常用于反向代理和负载均衡。以下是 Nginx 反向代理和负载均衡的基本原理和实现方式 1、反向代理 当客户端请求访问一个 Web 服务器时&#xff0c;首先会发送请求到 Nginx&#xff0c;然后 Nginx 将请求转…...

Delaunay三角剖分学习笔记

文章目录 Delaunay三角剖分学习笔记1 Voronoi \text{Voronoi} Voronoi图1.1 定义与性质 2 三角剖分2.1 定义与性质2.2 质量(quality)评定标准 3 Delaunay三角剖分3.1 定义3.2 准则与性质 4 Delaunay三角剖分算法4.1 Bowyer-Watson算法4.1.1 算法步骤&#xff1a;4.1.2 算法伪代…...

@Resource和@Autowired的区别

1.相同点 Resource和Autowired这两个注解的作用都是在Spring生态里面去实现Bean的依赖注入 2.不同点 2.1 Autowired 首先&#xff0c;Autowired是Spring里面提供的一个注解&#xff0c;默认是根据类型来实现Bean的依赖注入。 Autowired注解里面有一个required属性默认值是t…...

linux达梦数据库的安装与卸载

一、安装 创建dmdba用户及用户组 创建安装目录&#xff1a; mkdir -p /dm8 创建组 &#xff1a;groupadd dinstall 创建用户 &#xff1a;useradd -g dinstall dmdba 设置密码 &#xff1a;passwd dmdba 创建文件夹&#xff1a;mkdir /dmdata 更改安装目录所有者&#xff1a; c…...

生成式模型的质量评估标准

Sample Quality Matrix 如何评价生成式模型的效果&#xff1f;ISFIDsFIDPrecision & RecallPrecisonRecall计算precision和recall 如何评价生成式模型的效果&#xff1f; Quality: 真实性&#xff08;逼真&#xff0c;狗咬有四条腿&#xff09; Diversity: 多样性&#x…...

pinpoint安装部署(相关博客合集)

pinpoint安装部署 说明一、PinPoint介绍及工作原理1.1 确定部署的组件及服务 二、相关组件版本兼容情况2.1 确定版本 三、部署3.1 HBASE3.2 agent 说明 本博客写在搭建PinPoint之前&#xff0c;主要是用来记录查阅的相关博客资料&#xff0c;等到动手搭建完再更新实际部署操作…...

python-匿名函数(lambda函数)

匿名函数&#xff08;lambda函数&#xff09; 匿名函数&#xff08;也称为lambda函数&#xff09;是一种在代码中定义临时函数的方式&#xff0c;它没有明确的函数名称。匿名函数通常用于需要简短、一次性的函数定义&#xff0c;特别是在处理函数作为参数传递或函数返回的情况…...

JS逆向常见情况

分类&#xff1a;JS压缩混淆加密 与 URL/API参数的加密 代码压缩&#xff1a;去除不必要的空格换行等内容&#xff0c;使源码变成几行&#xff0c;大大降低可读性并提升网站加载速度 代码混淆&#xff1a;使用变量替换、字符串阵列化、控制流平坦化、多态变异、僵尸函数…...

利用matlab对滤波器频率特性分析

【设计目标】对双二阶环路滤波器进行时频域分析和处理的基本方法 【设计工具】MATLAB【设计要求】 1)分析典型的双二阶环路滤波器电路:低通、高通、带通、带阻 2)理论分析各滤波电路的系统函数 3)利用Matlab分析各滤波电路的系统函数的频率特性(幅频、相频)、零极点分…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...