JVM--Java类加载器笔记
Java类加载器
代码经过编译变成了字节码打包成 Jar 文件。让 JVM 去加载需要的字节码,变成持久代/元数据区上的 Class 对象,接着执行程序逻辑。
类声明周期和加载过程
步骤:加载->链接(校验->准备->解析)->初始化->使用->卸载
-
加载:根据明确知道的 class 完全限定名, 来获取二进制 classfile 格式的字节流(找到文件系统中/jar 包中/或存在于任何地方的“
class 文件
”。 如果找不到二进制表示形式,则会抛出NoClassDefFound
错误。) -
校验:确保 class 文件里的字节流信息符合当前虚拟机的要求,不会危害虚拟机的安全。
- 在某个类的加载过程中,JVM 必须加载其所有的超类和接口。如果类层次结构有问题(例如,该类是自己的超类或接口,死循环了),则 JVM 将抛出
ClassCircularityError
。 而如果实现的接口并不是一个 interface,或者声明的超类是一个 interface,也会抛出IncompatibleClassChangeError
。
- 在某个类的加载过程中,JVM 必须加载其所有的超类和接口。如果类层次结构有问题(例如,该类是自己的超类或接口,死循环了),则 JVM 将抛出
-
准备:会创建静态字段, 并将其初始化为标准默认值(比如
null
或者0 值
),并分配方法表,即在方法区中分配这些变量所使用的内存空间。- 准备阶段并未执行任何 Java 代码。
- public static int i = 1;备阶段
i
的值会被初始化为 0,后面在类初始化阶段才会执行赋值为 1; - public static final int i = 1如果使用 final 作为静态常量,对应常量 i,在准备阶段就会被赋值 1;
-
解析:进入可选的解析符号引用阶段。 也就是解析常量池,主要有以下四种:类或接口的解析、字段解析、类方法解析、接口方法解析。
- 编写的代码中,当一个变量引用某个对象的时候,这个引用在
.class
文件中是以符号引用来存储的(相当于做了一个索引记录)。 - 在解析阶段就需要将其解析并链接为直接引用(相当于指向实际对象)。如果有了直接引用,那引用的目标必定在堆中存在。
- 加载一个 class 时, 需要加载所有的 super 类和 super 接口。
- 编写的代码中,当一个变量引用某个对象的时候,这个引用在
-
初始化: 必须在类的首次“主动使用”时才能执行类初始化。
- 初始化的过程包括执行:
- 类构造器方法
- static 静态变量赋值语句
- static 静态代码块
- 如果是一个子类进行初始化会先对其父类进行初始化,保证其父类在子类之前进行初始化。所以其实在 java 中初始化一个类,那么必然先初始化过
java.lang.Object
类,因为所有的 java 类都继承自 java.lang.Object。
- 初始化的过程包括执行:
类加载时机
触发类的初始化情况:
- 当虚拟机启动时,初始化用户指定的主类,就是启动执行的 main 方法所在的类;
- 当遇到用以新建目标类实例的 new 指令时,初始化 new 指令的目标类,就是 new 一个类的时候要初始化;
- 当遇到调用静态方法的指令时,初始化该静态方法所在的类;
- 当遇到访问静态字段的指令时,初始化该静态字段所在的类;
- 子类的初始化会触发父类的初始化;
- 如果一个接口定义了 default 方法,那么直接实现或者间接实现该接口的类的初始化,会触发该接口的初始化;
- 使用反射 API 对某个类进行反射调用时,初始化这个类,其实跟前面一样,反射调用要么是已经有实例了,要么是静态方法,都需要初始化;
- 当初次调用 MethodHandle 实例时,初始化该 MethodHandle 指向的方法所在的类。
同时以下几种情况不会执行类初始化:
- 通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化。
- 定义对象数组,不会触发该类的初始化。
- 常量在编译期间会存入调用类的常量池中,本质上并没有直接引用定义常量的类,不会触发定义常量所在的类。
- 通过类名获取 Class 对象,不会触发类的初始化,Hello.class 不会让 Hello 类初始化。
- 通过 Class.forName 加载指定类时,如果指定参数 initialize 为 false 时,也不会触发类初始化,其实这个参数是告诉虚拟机,是否要对类进行初始化。Class.forName(“jvm.Hello”)默认会加载 Hello 类。
- 通过 ClassLoader 默认的 loadClass 方法,也不会触发初始化动作(加载了,但是不初始化)。
示例: 诸如 Class.forName(), classLoader.loadClass() 等 Java API, 反射API, 以及 JNI_FindClass 都可以启动类加载。 JVM 本身也会进行类加载。 比如在 JVM 启动时加载核心类,java.lang.Object, java.lang.Thread 等等。
类加载机制
类加载过程可以描述为“通过一个类的全限定名 a.b.c.XXClass 来获取描述此类的 Class 对象”,这个过程由“类加载器(ClassLoader)”来完成。这样的好处在于,子类加载器可以复用父加载器加载的类。
- 系统自带的类加载器分为三种:
- 启动类加载器(BootstrapClassLoader):由 JVM 内部实现的,在 Java 的 API 里无法拿到。
- 用来加载 Java 的核心类,是用原生 C++ 代码来实现的,可以看做是 JVM 自带的,在代码层面无法直接获取到启动类加载器的引用,所以不允许直接操作它。
- 例如:java.lang.String 是由启动类加载器加载的,所以 String.class.getClassLoader() 就会返回 null。但是后面可以看到可以通过命令行参数影响它加载什么。
- 扩展类加载器(ExtClassLoader):
- 负责加载 JRE 的扩展目录,lib/ext 或者由 java.ext.dirs 系统属性指定的目录中的 JAR 包的类,代码里直接获取它的父类加载器为 null(因为无法拿到启动类加载器)。
- 类加载器在 Oracle Hotspot JVM 里,都是在中
sun.misc.Launcher
定义的。一般都继承自URLClassLoader
类,这个类也默认实现了从各种不同来源加载 class 字节码转换成 Class 的方法。
- 应用类加载器(AppClassLoader):
- 负责在 JVM 启动时加载来自 Java 命令的 -classpath 或者 -cp 选项、java.class.path 系统属性指定的 jar 包和类路径。在应用程序代码里可以通过 ClassLoader 的静态方法 getSystemClassLoader() 来获取应用类加载器。如果没有特别指定,则在没有使用自定义类加载器情况下,用户自定义的类都由此加载器加载。
- 类加载器在 Oracle Hotspot JVM 里,都是在中
sun.misc.Launcher
定义的,一般都继承自URLClassLoader
类,这个类也默认实现了从各种不同来源加载 class 字节码转换成 Class 的方法。
- 自定义类加载器。
- 自定义类加载器都以应用类加载器作为父加载器。应用类加载器的父类加载器为扩展类加载器。这些类加载器是有层次关系的,启动加载器又叫根加载器,是扩展加载器的父加载器,但是直接从 ExClassLoader 里拿不到它的引用,同样会返回 null。
- 启动类加载器(BootstrapClassLoader):由 JVM 内部实现的,在 Java 的 API 里无法拿到。
- 类加载机制
- 双亲委托:当一个自定义类加载器需要加载一个类,比如 java.lang.String,先委托自己的父加载器去加载,父加载器如果发现自己还有父加载器,会一直往前找,这样只要上级加载器,比如启动类加载器已经加载了某个类比如 java.lang.String,所有的子加载器都不需要自己加载了。如果几个类加载器都没有加载到指定名称的类,那么会抛出 ClassNotFountException 异常。
- 负责依赖:如果一个加载器在加载某个类的时候,发现这个类依赖于另外几个类或接口,也会去尝试加载这些依赖项。
- 缓存加载:为了提升加载效率,消除重复加载,一旦某个类被一个类加载器加载,那么它会缓存这个加载结果,不会重复加载。
自定义类加载器示例
public class Hello {static {System.out.println("Hello Class Initialized!");}
}
import java.util.Base64;public class HelloClassLoader extends ClassLoader {public static void main(String[] args) {try {new HelloClassLoader().findClass("jvm.Hello").newInstance(); // 加载并初始化Hello类} catch (ClassNotFoundException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();}}@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {String helloBase64 = "yv66vgAAADQAHwoABgARCQASABMIABQKABUAFgcAFwcAGAEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2N" +"hbFZhcmlhYmxlVGFibGUBAAR0aGlzAQALTGp2bS9IZWxsbzsBAAg8Y2xpbml0PgEAClNvdXJjZUZpbGUBAApIZWxsby5qYXZhDAAHAAgHABkMABoAGwEAGEhlb" +"GxvIENsYXNzIEluaXRpYWxpemVkIQcAHAwAHQAeAQAJanZtL0hlbGxvAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2" +"YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0cmluZzspVgAhAAUABgAAAAAAAgABAAcACA" +"ABAAkAAAAvAAEAAQAAAAUqtwABsQAAAAIACgAAAAYAAQAAAAMACwAAAAwAAQAAAAUADAANAAAACAAOAAgAAQAJAAAAJQACAAAAAAAJsgACEgO2AASxAAAAAQAK" +"AAAACgACAAAABgAIAAcAAQAPAAAAAgAQ";byte[] bytes = decode(helloBase64);return defineClass(name,bytes,0,bytes.length);}public byte[] decode(String base64){return Base64.getDecoder().decode(base64);}}
- 两个没有关系的自定义类加载器之间加载的类是不共享的(只共享父类加载器,兄弟之间不共享),这样就可以实现不同的类型沙箱的隔离性
- 可以用多个类加载器,各自加载同一个类的不同版本,在这个基础上可以实现类的动态加载卸载,热插拔的插件机制等。
实用技巧
-
排查再找不到jar包的问题
-
结果可以看到三种类加载器各自默认加载了哪些 jar 包和包含了哪些 classpath 的路径
-
import java.lang.reflect.Field; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList;public class JvmClassLoaderPrintPath {public static void main(String[] args) {// 启动类加载器URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();System.out.println("启动类加载器");for(URL url : urls) {System.out.println(" ==> " +url.toExternalForm());}// 扩展类加载器printClassLoader("扩展类加载器", JvmClassLoaderPrintPath.class.getClassLoader().getParent());// 应用类加载器printClassLoader("应用类加载器", JvmClassLoaderPrintPath.class.getClassLoader());}public static void printClassLoader(String name, ClassLoader CL){if(CL != null) {System.out.println(name + " ClassLoader -> " + CL.toString());printURLForClassLoader(CL);}else{System.out.println(name + " ClassLoader -> null");}}public static void printURLForClassLoader(ClassLoader CL){Object ucp = insightField(CL,"ucp");Object path = insightField(ucp,"path");ArrayList ps = (ArrayList) path;for (Object p : ps){System.out.println(" ==> " + p.toString());}}private static Object insightField(Object obj, String fName) {try {Field f = null;if(obj instanceof URLClassLoader){f = URLClassLoader.class.getDeclaredField(fName);}else{f = obj.getClass().getDeclaredField(fName);}f.setAccessible(true);return f.get(obj);} catch (Exception e) {e.printStackTrace();return null;}} }
-
-
如何排查类的方法不一致的问题
- 假如确定一个 jar 或者 class 已经在 classpath 里了,但是却总是提示
java.lang.NoSuchMethodError
? - 很可能是加载了错误的或者重复加载了不同版本的 jar 包。
- 用前面的方法就可以先排查一下,加载了具体什么 jar,然后是不是不同路径下有重复的 class 文件,但是版本不一样。
- 假如确定一个 jar 或者 class 已经在 classpath 里了,但是却总是提示
-
怎么看到加载了哪些类,以及加载顺序?
- 假如有两个地方有 Hello.class,一个是新版本,一个是旧的,怎么才能直观地看到他们的加载顺序呢?
- 可以直接打印加载的类清单和加载顺序。
- 只需要在类的启动命令行参数加上
-XX:+TraceClassLoading
或者-verbose
即可,注意需要加载 Java 命令之后,要执行的类名之前,不然不起作用。例如:java -XX:+TraceClassLoading jvm.HelloClassLoader
-
怎么调整或修改 ext 和本地加载路径?
-
从前面的例子我们可以看到,假如什么都不设置,直接执行 java 命令,默认也会加载非常多的 jar 包,怎么可以自定义加载哪些 jar 包呢?比如我的代码很简单,只加载 rt.jar 行不行?答案是肯定的。
$ java -Dsun.boot.class.path="D:\Program Files\Java\jre1.8.0_231\lib\rt.jar" -Djava.ext.dirs= jvm.JvmClassLoaderPrintPath启动类加载器==> file:/D:/Program%20Files/Java/jdk1.8.0_231/jre/lib/rt.jar 扩展类加载器 ClassLoader -> sun.misc.Launcher$ExtClassLoader@15db9742 应用类加载器 ClassLoader -> sun.misc.Launcher$AppClassLoader@73d16e93==> file:/D:/git/studyjava/build/classes/java/main/==> file:/D:/git/studyjava/build/resources/main
- 我们看到启动类加载器只加载了 rt.jar,而扩展类加载器什么都没加载,这就达到了我们的目的。
- 命令行参数
-Dsun.boot.class.path
表示我们要指定启动类加载器加载什么,最基础的东西都在 rt.jar 这个包了里,所以一般配置它就够了。需要注意的是因为在 windows 系统默认 JDK 安装路径有个空格,所以需要把整个路径用双引号括起来,如果路径没有空格,或是 Linux/Mac 系统,就不需要双引号了。 - 参数
-Djava.ext.dirs
表示扩展类加载器要加载什么,一般情况下不需要的话可以直接配置为空即可。
-
-
怎么运行期加载额外的 jar 包或者 class 呢?
-
有时候在程序已经运行了以后,还想要再额外的去加载一些 jar 或类.简单说就是不使用命令行参数的情况下,怎么用代码来运行时改变加载类的路径和方式
-
假如说,在
d:/app/jvm
路径下,有刚才使用过的 Hello.class 文件,怎么在代码里能加载这个 Hello 类呢?- 一个是自定义 ClassLoader 的方式
- 还有一个是直接在当前的应用类加载器里,使用 URLClassLoader 类的方法 addURL,不过这个方法是 protected 的,需要反射处理一下,然后又因为程序在启动时并没有显示加载 Hello 类,所以在添加完了 classpath 以后,没法直接显式初始化,需要使用 Class.forName 的方式来拿到已经加载的Hello类(Class.forName(“jvm.Hello”)默认会初始化并执行静态代码块)。代码如下:
package jvm;import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader;public class JvmAppClassLoaderAddURL {public static void main(String[] args) {String appPath = "file:/d:/app/";URLClassLoader urlClassLoader = (URLClassLoader) JvmAppClassLoaderAddURL.class.getClassLoader();try {Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);addURL.setAccessible(true);URL url = new URL(appPath);addURL.invoke(urlClassLoader, url);Class.forName("jvm.Hello"); // 效果跟Class.forName("jvm.Hello").newInstance()一样} catch (Exception e) {e.printStackTrace();}} }
执行以下,结果如下:
$ java JvmAppClassLoaderAddURL Hello Class Initialized!
结果显示 Hello 类被加载,成功的初始化并执行了其中的代码逻辑。
-
相关文章:
JVM--Java类加载器笔记
Java类加载器 代码经过编译变成了字节码打包成 Jar 文件。让 JVM 去加载需要的字节码,变成持久代/元数据区上的 Class 对象,接着执行程序逻辑。 类声明周期和加载过程 步骤:加载->链接(校验->准备->解析)-…...
【在Ubuntu部署Docker项目】— PROJECT#1
一、说明 让我们深入了解 Docker。用docker构建web服务器。我们正在计划开发JavaScript API,建立MySQL数据库,并创建一个 PHP 网站使用 API 服务。Php Node.js Mysql — DockerSeries — Episode#1 二、系统架构概述 我们要构建的容器,是三…...
【学习笔记】LOJ #6240. 仙人掌
毒瘤题😅 简单版本 CF235D Graph Game 首先,考虑建立圆方树,然后对于一个点双(简单环)上的两个点,有两条路径可以到达 和简单版本类似,考虑容斥。即枚举点对 i , j i,j i,j之间 哪些路径是联…...
java通过接口转发文件(上传下载)
java接口转发上传的文件 RequestMapping(value "/XXXX/fileUpload", method RequestMethod.POST) public String getFileUpload2(RequestParam("file") MultipartFile file, HttpServletRequest request) public static String hotMapPost3(String ur…...
Docker-部署docker-compose以及管理服务
部署docker-compose以及管理服务 文章目录 部署docker-compose以及管理服务[TOC] 前言一、docker-compose是什么?1、介绍2、 功能 二、安装docker-compose1.yum直接安装2.二进制安装3.pip安装 三、docker-compose部署服务1.编写docker-compose.yml文件 总结 前言 D…...
Android - Monkey 测试应用出现Crash报错IllegalStateException
问题描述 平时使用Lottie动画都是正常的,没出过这个crash问题,看下的报错信息,代码中文件夹也设置了,没看出来问题。 AndroidRuntime: java.lang.IllegalStateException: You must set an images folder before loading an imag…...
Spring源码分析 事务 实现原理
文章目录 什么是事务Spring事务管理Spring事务实现原理事务管理器事务定义事务的开启事务核心方法业务代码使用事务TransactionInterceptor 什么是事务 一般所指的事务是数据库事务,是指一批不可分割的数据库操作序列,也是数据库并发控制的基本单位。其…...
ADS-B及雷达显示终端8.3
新版本功能升级主要有如下: 1、地图更新 在上一版本8.2中使用的高程地图为由SRTM经过地形晕渲后,生成地形图片,然后对图片进行贴图,一一按规定位置、大小将地形图贴至底图上,而后在底图上进行二维矢量地图的绘制,包括…...
第二章:最新版零基础学习 PYTHON 教程(第二节 - Python 输入/输出–从 Python 控制台获取输入)
目录 Python 中的控制台是什么? 接受来自控制台的输入: 1. 将输入类型转换为整数:...
linux安装配置 flume
目录 一 解压安装包 二 配置部署 (1)修改配置 (2)下载工具 (3)创建配置文件 (4)启动监听测试 (5)flume监控文件 一 解压安装包 这里提供了网盘资源 链…...
SSM - Springboot - MyBatis-Plus 全栈体系(十五)
第三章 MyBatis 二、MyBatis 基本使用 4. CRUD 强化练习 4.1 准备数据库数据 首先,我们需要准备一张名为 user 的表。该表包含字段 id(主键)、username、password。创建SQL如下: CREATE TABLE user (id INT(11) NOT NULL AUT…...
win10默认浏览器改不了怎么办,解决方法详解
win10默认浏览器改不了怎么办,解决方法详解_蓝天网络 在使用Windows 10操作系统时,你可能会遇到无法更改默认浏览器的情况。这可能是因为其他程序或设置正在干扰更改。如果你也遇到了这个问题,不要担心,本文将为你提供详细的解决…...
C语言连接MySQL并执行SQL语句(hello world)
1.新建一个控制台项目 参考【VS2022 和 VS2010 C语言控制台输出 Hello World】VS2022 和 VS2010 C语言控制台输出 Hello World_vs2022源文件在哪_西晋的no1的博客-CSDN博客 2.安装MySQL 参考【MySQL 8.0.34安装教程】MySQL 8.0.34安装教程_西晋的no1的博客-CSDN博客 3.复制MySQ…...
react实现动态递增展示数字特效
在可视化展示界面时有一种场景,就是页面在初始化的时候,有些数字展示想要从某个值开始动态递增到实际值,形成一种动画效果。例如: 写一个数字递增的组件,有两种方式:1.固定步长,代码如下&#x…...
读取.nrrd和.dcm文件格式医学图片可视化与预处理
nrrd数据格式 MITK默认会将医学图像保存为格式为NRRD的图像,在这个数据格式中包含: 1、一个单个的数据头文件:为科学可视化和医学图像处理准确地表示N维度的栅格信息。 2、既能分开又能合并的图像文件。 nrrd_options输出 {u’dimension’:…...
VS CODE中的筛选器如何打开?
最近更新了vscode1.82版本,发现在git管理界面有一个“筛选器”功能,十分好用,后来关掉了,找了好久都没有找到办法打开这个筛选器功能,今天无意中不知道按到了哪个快捷键,打开了,就是下图这个&am…...
vue 多环境文件配置(开发,测试,生产)
1.经常我们在开发时候会有不同环境,要代理的路由等等都会出现不同 配置一下三个文件打包的时候,执行三个不同的指令就会打包不同的环境 npm run build:dev npm run build:test npm run build:prodpackage.json 中配置scripts 指令 以,env.development…...
在服务器上搭建pulseaudio的运行环境,指定其运行目录、状态目录和模块目录
如果想在搭建 PulseAudio 的服务器上指定其运行目录、状态目录和模块目录,可以通过修改 PulseAudio 的配置文件来实现。一般情况下所涉及的配置文件和相关选项如下所示: 1、配置文件路径:通常情况下,PulseAudio 的配置文件位于 /…...
[Qt]QListView 重绘实例之一:背景重绘
0 环境 Windows 11Qt 5.15.2 MinGW x64 1 系列文章 简介:本系列文章,是以纯代码方式实现 Qt 控件的重构,尽量不使用 Qss 方式。 《[Qt]QListView 重绘实例之一:背景重绘》 《[Qt]QListView 重绘实例之二:列表项覆…...
国庆周《Linux学习第二课》
Linux开篇指南针环境安装(第一课)-CSDN博客 Linux详细的环境安装介绍在上面 第一 环境准备过程 安装过程...
6年前的麒麟980依旧可以再战
麒麟980,使用6年后的今天,我对它进行跑分测试。 在bench旗下的VRMark跑分中,麒麟980荣获5023分,同款跑分APP,要知道同一时期的高通骁龙855只有4937分, 打游戏,以和平精英为例,帧率3…...
JS计算任意多边形的面积
计算任意多边形的面积需要使用一些几何数学公式。具体的计算方法取决于多边形的形状和提供的顶点坐标。下面是一个通用的 JavaScript 函数,用于计算任意多边形的面积,假设你提供多边形的顶点坐标数组: function calculatePolygonArea(vertic…...
ios xcode15 navigationController?.navigationBar.isHidden = false无效
xcode 15 用 navigationController?.setNavigationBarHidden(true, animated: false)隐藏navigationBar后,再调用 navigationController?.navigationBar.isHidden false无效 解决 用 navigationController?.navigationBar.isHidden true隐藏navigationBar...
Python二级 每周练习题20
练习一: 日期计算器 设计一款日期计算程序,能否实现下面的功能: (1)要求用户分别输入年、月、日(分三次输入); (2)程序自动会根据输入的年月日计算出这一天是这一年的第几天; (3)输出格式为:这…...
深度学习-一个简单的深度学习推导
文章目录 前言1.sigmod函数2.sigmoid求导3.损失函数loss4.神经网络1.神经网络结构2.公式表示-正向传播3.梯度计算1.Loss 函数2.梯度1.反向传播第2-3层2.反向传播第1-2层 3.python代码4.MNIST 数据集 前言 本章主要推导一个简单的两层神经网络。 其中公式入口【入口】 1.sigmod…...
ES写入数据报错:retrying failed action with response code: 429
报错: 使用logstash导入分片数量为9的index发生错误,[logstash.outputs.elasticsearch] retrying failed action with response code: 429 ({"type">"es_rejected_execution_exception", "reason">"rejected execution …...
Redis给Lua脚本的调用
Redis给Lua脚本的调用 Redis为Lua提供了一组内置函数,这些函数可用于执行与Redis数据存储和操作相关的任务。这些内置函数可以在Lua脚本中使用,以便在Redis中执行各种操作。以下是一些常用的Redis Lua内置函数: 主要知道call就好了 redis.ca…...
Spring工具类--ReflectUtils的使用
原文网址:Spring工具类系列--ReflectUtils的使用_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Spring的ReflectUtils的使用。 ReflectUtils工具类的作用:便利地进行反射操作。 Spring还有一个工具类:ReflectionUtils,它们在功能上…...
联盟 | 彩漩 X HelpLook,AI技术赋能企业效率提升
近日,AI 驱动的 PPT 协作分享平台「 彩漩 」与 AI 知识库搭建工具「 HelpLook」,携手为用户工作流注入更多智能和创造力,全面拥抱 AIGC 时代带来的机遇,致力于提供前沿的智能解决方案。 彩 漩 彩漩是一个以 AI 技术为基础、贯彻 …...
MATLAB m文件格式化
记录一个网上查到的目前感觉挺好用的格式化方法。 原链接: https://cloud.tencent.com/developer/article/2058259 压缩包: 链接:https://pan.baidu.com/s/1ZpQ9qGLY7sjcvxzjMPAitw?pwd6666 提取码:6666 下载压缩包…...
凡客诚品是什么/seo网站优化平台
试验网站#1搜索引擎优化收录情况记录日期Yahoogooglebaidusogou每日收录每日收录增量每日收录每日收录增量每日收录每日收录增量每日收录每日收录增量2007-6-24288 333 1060 4813 2007-6-25164013523330108020481302007-6-26空间超过本月流量限制……,快到月底了…...
电子商务网站设计的基本要求/上海百度推广公司
WScript.Shell(Windows Script Host Runtime Library)是一个对象,对应的文件是C:/WINDOWS/system32/wshom.ocx,Wscript.shell是服务器系统会用到的一种组件。shell 就是“壳”的意思,这个对象可以执行操作系统外壳常用…...
如何修改网站logo/百度推广做二级域名
每天花1-2个小时左右来学习就够了。 PMP考试其实说难也不难,说容易也不简单,但只要你是认真的在学,基本上都能过。主要还是看上课的老师讲课、是否专业,这些方面。 今天就跟大家讲讲一个完全不了解PMP的人要怎样去准备PMP考试&a…...
php做网站如何配置域名的/磁力在线搜索引擎
同步就是一个任务的完成需要依赖另外一个任务时,只有等待被依赖的任务完成后,依赖的任务才能算完成,这是一种可靠的任务序列 异步是不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即…...
茂名做网站/seo排名怎么样
wordcloud安装参考:下载安装wordcloud snownlp安装参考:下载安装snownlp jieba安装参考:使用码云下载Github文件 wordcloud强调python版本,snownlp和jieba不强调版本,我装的都是python3.6下的。 数据:和鲸社…...
wordpress 破解/百度公司推广电话
MySQL之表(或数据库)操作语言-01 学习目标MySQL之表(或数据库)操作语言-011. 表(或数据库)操作语句1.1 查询表(或数据库)1.2 新建表(或)数据库1.3 删除表(或数据库&#…...