【学习笔记】深入理解JVM之类加载机制
【学习笔记】深入理解JVM之类加载机制
以后基本上都在语雀上面更新,大家有兴趣可以看看嗷!
首发地址: 知识库
文章流程图:
1、概述
首先我们先来看看一个 Class
文件所需要经过的一个流程图:
而我们今天要重点需讲的就是 类加载器
这部分。
在讲类加载器之前先问一个问题——什么是
Class
文件?
Class
文件是一组 8
字节为基础单位的二进制文件,各个数据项项目严格按照顺序紧凑地排列在文件之中,中间没有添加任何分隔符,这使得 Class
文件中存储的内存内容部分都是程序运行的必要数据,没有空隙存在。
通过上面的回答我们知道
Class
文件,是一个以8
自己为基础单位的二进制文件,那如果遇到一个需要 占用8字节以上的的空间数据项时会怎么办?
当出现占用超过 8
以上空间的数据项时,则会采用 高位在前 的方式分割成若干个 8
个字节进行存储。
补充:
一般
Class
文件的头四个字节被称为 魔数(Magic Number) ,它的作用就是确定这个文件是否为一个能被虚拟机接受的Class
文件。
2、类加载机制
那什么又是类加载机制呢?
Java虚拟机把描述类的数据从 Class
文件加载到内存,并对数据进行 校验、转换解析和初始化
,最终形成可以被虚拟机直接使用的Java类型,这个过程被称作虚拟机的类加载机制。
类加载的过程图:
2.1 加载
注意此处的 “加载” 是 ‘’类加载“ 过程中的一个阶段, 大家不要弄混了嗷。
在加载阶段,Java
虚拟机需要完成以下三件事:
- 通过一个类的
全限定名
来获取定义此类的二进制字节流。 - 将这个
字节流
所代表的静态存储结构
转化为方法区的运行时数据结构
。 - 在内存中生成一个代表这个类的
java.lang.Class
对象,作为方法区这个类的各种数据的访问入口。
补充:
可以获取二进制字节流的方式:
- 从ZIP压缩包中读取,这很常见,最中成为日后JAR、EAR、WAR的格式基础。
- 从网络中获取,这种场景最低昂行的应用就是
Web Applet
。- 运行时计算生成,这种场景使用得最多的就是 动态代理 技术,在
java.lang.reflect.Proxy
中,就是用了ProxyGenerator.generateProxyClass()
来为特定接口生成形式为"*$Proxy"
的代理类的二进制字节流。- 从数据库中读取。
- 其他文件生成。
- …
2.2 验证
验证是链接阶段的第一步,这一阶段的目的是确保 Class
文件的字节流中包含的信息符合 《Java虚拟机规范》的全部约束要求,保证这些信息被当作代码运行后不会危害虚拟机自身的安全。
举个例子:
我们知道 Class
文件并不一定都是 Java
源码编译而来,它可以使用包括靠键盘 0和1
直接在二进制编辑器中敲出 Class
文件。如果不进行此方面的验证,对其完全信任的话,可能会有恶意的企图的字节码流程,而导致整个系统搜到破坏。
所以说验证字节码是 Java
虚拟机自我保护的一项必要措施。
验证阶段是是十分严谨的,直接决定了 Java虚拟机
是否能承受恶意代码的攻击。验证阶段大致分为以下四个阶段:
文件格式验证
元数据验证
字节码验证
符号引用验证
♣️ 2.2.1 文件格式验证
第一阶段就是需要验证字节流是否符合 Class
文件格式的规范,并且能被当前版本的虚拟机处理。这一阶段可能包括下面这些验证点:
- 是否以魔数
0xCAFEBABE
开头。 - 主、次版本号是否在当前的
Java
虚拟机接受范围之内。 - 常量池的常量中是否有不被支持的常量类型。
- 指向常量的各种索引值中是否有指向不存在的常量或不符合类型的常量。
- CONSTANT_Utf8_info型的常量中是否有不符合UTF-8编码的数据。
Class
文件中各个部分及文件本身是否有被删除的或附加的其他信息。- …
目的:
上述的验证阶段主要是为了保证输入的字节流能正确地解析并存储于方法区内。这个阶段是基于二进制字节流进行的,只有通过了这个阶段的验证之后,这段字节流才被允许进入Java虚拟机内存的方法区中进行存储。所以后面的三个验证阶段都是基于 方法区的存储结构来进行的
。
♣️ 2.2.2 元数据验证
第二阶段是对字节码描述的信息进行语义分析,以保证其描述的信息符合《Java语言规范》要求,这个阶段可能包括的验证点如下:
- 这个类是否有父类(除了
java.lang.Object
之外,所有的类都应当有父类)。 - 这个类的父类是否继承了不允许被继承的类(被final修饰的类)。
- 如果这个类不是抽象类,是否实现了其父类或接口之中要求实现的所有方法。
- 类中的字段、方法是否与父类产生矛盾(例如覆盖了父类的final字段,或者出现不符合规则的方法重载,例如方法参数都一致,但是返回值类型却不同等)。
- …
目的:
是对类的元数据信息进行语义校验,保证不存在《Java语言规范》定义相悖的元数据信息。
♣️ 2.2.3 字节码验证
本阶段是真个验证阶段最为复杂的一个阶段,主要目的是通过数据流分析和控制流分析,确定程序语义是合法的、符合逻辑的。本阶段是对 方法体(Class文件中的Code属性) 进行校验分析,保证被校验类的方法在运行时不会做出未来虚拟机安全的行为。
例如:
- 保证任意时刻操作数栈的数据类型与指令代码序列都能配合工作,例如不会出现类似于“在操作栈放置了一个int类型的数据,使用时却按照long类型来加载本地变量表中” 这样的情况。
- 保证跳转指令都不会跳转到方法体以外的字节码指令上。
- 保证方法体中的类型转换总是有效的,例如可以把一个子类的对象赋值给父类数据类型,这样是安全的,但是把父类对象赋值给自类数据类型,甚至把对象赋值给与它毫无继承关系、完全不想干的一个数据类型,则是危险和不合法的。
如果有一个方法体中的字节码没有通过字节码的验证,那它肯定是有问题的。但是如果通过了验证也不能百分之百的保证他是安全的。
♣️ 2.2.4 符号引用验证
最后一个阶段的校验行为发生在虚拟机将符号转化为直接引用的时候,这个转化动作将在连接的第三阶段( 解析阶段中发生 )。其可以看作是对类自身以为(常量池中各个符号引用)的各类信息进行匹配性校验,通俗来说就是,该类是否缺少或者被禁止访问它依赖的某些外部类、方法、字段等资源。本阶段通常需要校验下列内容:
- 符号引用中通过
字符串描述
的全限定名
是否能找到对应的类
。 - 在
指定类中
是否存在符合方法的字段描述符
及简单名称
所描述的方法和字段
。 - 符号引用中的类、字段、方法的可访问性(
private、protected、public、<package>
) 是否可被当前类访问。 - …
本阶段的主要目的就是确保解析行为能正常执行,如果无法通过 符号引用验证 阶段 Java虚拟机 将会抛出一个 java.lang.IncompatibleClassChangeError
的子类异常,典型的如:java.lang.IllegalAccessError、java.lang.NoSuchFieldError、java.lang.NoSuchMethodError
等。
♣️ 2.2.5 总结
验证阶段对于虚拟机的类加载机制来说,是一个非常重要的、但却不是必须要执行的阶段,因为验证阶段只有通过或者不通过的差别,只要通过了验证,其后就对程序运行期没有任何影响,如果程序运行的全部代码(包括自己编写的、第三方包中的、从外部加载的、动态生成的等所有代码)都已经被反复使用和验证过了,再生产环境的实施阶段即可以考虑使用 -X verify:none
参数来关闭大部分的类验证措施,以缩短虚拟机类加载的时间。
2.3 准备
准备阶段是正式为类中定义的变量( 静态变量,被 static
修饰的变量 ) 分配内存并设置变量的初始值的阶段。从概念上讲,这些变量所使用的内存都应当在方法区中进行配置,但应该注意方法区本生就是一个逻辑上的区域。在 JDK1.8
之后,类变量会随着 Class
对象一起存放在 Java
堆中。
注意:
准备阶段进行内存分配的仅包括类变量,而不是实例变量,实例变量将会在对象实例化的时候随着对象一起分配在Java堆中
。
我们通常情况下数据类型 零值 。
例如:
public static int value = 123;
如上述代码,value
在准备阶段过后的初始值为0而不是123,因为 这时尚未开始执行任何Java方法,而把 value
赋值为123的 putstatic
指令是程序被编译后,存放于类构造器 <clinit>()
方法之中,所以把 value
赋值为123的动作要到类的初始化阶段才会被执行。
零值表补充:
但是会出现特殊情况:
如果类字段的字段属性表中存在 ConstantValue
属性,那在准备阶段变量值就会被初始化为 ConstantValue
属性所指定的初始值,如果上面代码改为以下情况:
public static final int value = 123;
编译时 Javac
会将为 value
值生成 ConstantValue
属性,在准备阶段虚拟机就会根据 ConstantValue
的设置将 value
赋值为 123。
总结:
- 为类变量分配内存并切设置该类变量的默认初始值,即零值。
- 这里不包含使用
final
修饰的static
,因为final
在编译的时候机会分配,准备阶段会显示初始化。 - 这里不会为 实例变量 分配初始化,类变量会分配在方法区中,而实例变量实惠随着对象一起分配到 Java堆中。
2.3 解析
解析过程是 Java虚拟机
将常量池内的 符号引用
替换为 直接引用
的过程。
-
符号引用: 符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可。
-
直接引用: 直接引用是可以直接指向目标的指针、相对偏移量或者是一个能间接定位到目标的句柄。
解析的流程有以下四个:
类或接口的解析
字段解析
方法解析
接口方法解析
事实上解析操作都是往往伴随着 JVM
在执行过程中完成初始化之后再执行。
2.4 初始化
类的初始化阶段是类加载过程的最后一个步骤,之前介绍的的几个类的加载动作里,除了在 加载阶段
用户应用程序可以通过自定义类加载器的方式局部参与,其余动作完全由 Java
虚拟机来主导控制权。直到 初始化阶段 ,Java
虚拟机才开始真正开始执行类中编写的 Java
程序代码,将主导权移交给应用程序。
而在初始化阶段,则会根据程序员通过程序编码指定的主观计划去初始化类变量和其他资源。
总结:
- 初始化阶段就是执行类构造器
<clinit>()
方法的过程。 - 此方法不需要被定义,而javac编译器自动收集类中所有变量值的赋值动作和静态代码块中语句合并而来。
- 构造器方法中指令按语句在源文件中出现的顺序执行。
<clinet>()
不同于类的构造器(<init>()
)- 若该类具有父类,
JVM
保证子类的<client>()
执行前,父类的<clinit>()
已经执行完毕。 - 虚拟机必须保证一个类的
<clinit>()
方法再多线程下被同步加锁。
3、类加载器
首先我们要知道什么是 类加载器
?
通过一个类的全限定名来获取描述该类的二进制字节流
这个动作放到Java
虚拟机外部去实现,以便让应用程序自己去决定如何获取所需的类。实现这个动作的代码被称为类加载器(Class Loader)
。
对于任意一个类,都必须由加载它的类加载器和这个类本身一起共同确立其在 java
虚拟机中的 唯一性 ,每一个类加载器都拥有一个独立的类名称空间。通俗一点讲就是:比较两个类是否相等,只有在这两个类是同一个类加载器加载的前提下才有意义。
类加载器一共有以下几种:
名称 | 加载哪的类 | 说明 |
---|---|---|
Bootstrap ClassLoader(启动类加载器) | JAVA_HOME/jre/lib | 无法直接访问 |
Extension ClassLoader(扩展类加载器) | JAVA_HOME/jre/lib/ext | 上级为 Bootstrap,显示为 null |
Application ClassLoader(应用程序类加载器) | classpath | 上级为 Extension |
自定义类加载器 | 自定义 | 上级为 Application |
类加载器的优先级(由高到低):启动类加载器 -> 扩展类加载器 -> 应用程序类加载器 -> 自定义类加载器 。
3.1 启动类加载器(Bootstrap ClassLoader)
- 这个类加载器是使用
C++/C
语言来实现的,嵌套在JVM
内部。 - 它用来加载
Java
的核心库(JAVA_HOME/jre/lib
),用于提供JVM
自身需要的类。 - 并不是继承自
java.lang.Class.ClassLoader
,没有父加载器。 - 加载扩展类和应用程序类加载器,并指定为他们的父类加载器。
获取启动类能够加载的路径:
public static void main(String[] args) {URL[] urLs = Launcher.getBootstrapClassPath().getURLs();for(URL element: urLs){System.out.println(element.toExternalForm());}}
file:/Users/tiejiaxiaobao/Library/Java/JavaVirtualMachines/liberica-1.8.0_345/jre/lib/resources.jar
file:/Users/tiejiaxiaobao/Library/Java/JavaVirtualMachines/liberica-1.8.0_345/jre/lib/rt.jar
file:/Users/tiejiaxiaobao/Library/Java/JavaVirtualMachines/liberica-1.8.0_345/jre/lib/sunrsasign.jar
file:/Users/tiejiaxiaobao/Library/Java/JavaVirtualMachines/liberica-1.8.0_345/jre/lib/jsse.jar
file:/Users/tiejiaxiaobao/Library/Java/JavaVirtualMachines/liberica-1.8.0_345/jre/lib/jce.jar
file:/Users/tiejiaxiaobao/Library/Java/JavaVirtualMachines/liberica-1.8.0_345/jre/lib/charsets.jar
file:/Users/tiejiaxiaobao/Library/Java/JavaVirtualMachines/liberica-1.8.0_345/jre/lib/jfr.jar
file:/Users/tiejiaxiaobao/Library/Java/JavaVirtualMachines/liberica-1.8.0_345/jre/classes
3.2 扩展类加载器(Extension ClassLoader)
- Java语言编写,由
sun.misc.Launcher$ExtClassLoader
实现。 - 派生于ClassLoader类。
- 父类加载器为启动类加载器。
- 从
java.ext.dirs
系统属性所指定的目录中加载类库,或从 JDK 的安装目录的jre/lib/ext
子目录(扩展目录)下加载类库。如果用户创建JAR在此目录下,则会自由由扩展类加载器加载。
//获取系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
// sun.misc.Launcher$AppClassLoader@18b4aac2
例如:
public static void main(String[] args) {String property = System.getProperty("java.ext.dirs");for(String p: property.split(":")){System.out.println(p);}}
输出:
/Users/tiejiaxiaobao/Library/Java/Extensions
/Users/tiejiaxiaobao/Library/Java/JavaVirtualMachines/liberica-1.8.0_345/jre/lib/ext
/Library/Java/Extensions
/Network/Library/Java/Extensions
/System/Library/Java/Extensions
/usr/lib/java
3.3 应用程序加载器(AppClassLoader)
- 由Java语言编写,由
sun.misc.Launcher$AppClassLoader
实现。 - 派生于
ClassLoader
类。 - 父类加载器为扩展加载器。
- 它负责加载环境变量
classpath
或系统属性java.class.path
指定路径下的类库。
3.4 用户自定义类加载器
为什么要自定义类加载器呢?
- 隔离加载类
- 修改类加载的方式
- 扩展加载源
- 防止源码泄露
那又什么时候去定义呢?
- 1)想加载非 classpath 随意路径中的类文件
- 2)都是通过接口来使用实现,希望解耦时,常用在框架设计
- 3)这些类希望予以隔离,不同应用的同名类都可以加载,不冲突,常见于 tomcat 容器
步骤:
- 继承 ClassLoader 父类。
- 要遵从双亲委派机制,重写 findClass 方法 注意不是重写 loadClass 方法,否则不会走双亲委派机制。
- 读取类文件的字节码。
- 调用父类的 defineClass 方法来加载类。
- 使用者调用该类加载器的 loadClass 方法。
4、双亲委派模型
♣️ 什么是双亲委派模型呢?
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。
实现:
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {// 首先,检查请求的类是否已经被加载过了 Class c = findLoadedClass(name); if (c == null) {try {if (parent != null) {c = parent.loadClass(name, false);} else {c = findBootstrapClassOrNull(name); }} catch (ClassNotFoundException e) {// 如果父类加载器抛出ClassNotFoundException // 说明父类加载器无法完成加载请求}if (c == null) {// 在父类加载器无法加载时// 再调用本身的findClass方法来进行类加载 c = findClass(name);} }if (resolve) { resolveClass(c);}return c;
}
♣️为什么使用双亲委派模型呢?(好处)
- 采用双亲委派模式的是好处是Java类随着它的类加载器一起具备了一种带有优先级的层次关系,通过这种层级关可以避免类的重复加载,当父加载器已经加载了该类时,就没有必要子加载器再加载一次。
- 其次是考虑到安全因素,java 核心 api 中定义类型不会被随意替换,假设通过网络传递一个名为
java.lang.Integer
的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer
,而直接返回已加载过的Integer.class
,这样便可以防止核心API库被随意篡改。
参考
本篇笔记参考:尚硅谷JVM 26 - 36 集
《深入理解Java虚拟机》第三版
第六章—类文件结构
第七章—虚拟机类加载机制
文章地址:https://blog.csdn.net/weixin_43591980/article/details/119916684
相关文章:
【学习笔记】深入理解JVM之类加载机制
【学习笔记】深入理解JVM之类加载机制 以后基本上都在语雀上面更新,大家有兴趣可以看看嗷! 首发地址: 知识库 文章流程图: 1、概述 首先我们先来看看一个 Class 文件所需要经过的一个流程图: 而我们今天要重点需讲的…...
驾驭云端之风1——Spring Cloud微服务架构实践指南
本博客纯属个人总结,非原创。喜欢技术交流的,可关注博主,武汉有后端开发群,可支持内推,了解武汉行情等。 前沿 优惠卷平台项目的整体功能和模块,以及每个功能点的技术选型和背后的依据。 搭建一个简化版的…...
【计算机网络基础】
计算机网络基础网络的基本概念网络互联网IP地址MAC地址网络协议网络分层模型网络应用程序的通信流程网络的基本概念 网络 网络是由若干结点和链接这些结点的链路组成,网络中的结点可以是计算机,交换机,路由器等设备 网络设备:交…...
grep与nm命令的应用
相关知识拓展 Linux中grep的命令使用 在Linux中,grep可用于shell脚本,因为grep通过返回一个状态值来说明搜索状态,如果模板搜索成功,则返回0,如果搜索不成功,则返回1,如果搜索的文件不存在&…...
【linux】软硬链接
在linux中在磁盘中定位文件并不是根据文件名而是根据文件的inode,一个文件对应一个inode但是一个inode可以对应多个文件。硬链接硬链接是通过索引节点进行的链接。在Linux中,多个文件指向同一个索引节点是允许的,像这样的链接就是硬链接。硬链…...
骨传导蓝牙耳机排行,盘点几款性能不错的骨传导耳机
随着蓝牙耳机的普及,骨传导耳机也越来越受到欢迎,很多人也都开始在了解并尝试骨传导耳机。相比于其他类型耳机,在舒适度、安全方面有一定优势。尤其是在户外运动时,或者长时间佩戴运动时,使用骨传导耳机可以避免耳朵因…...
ARM中的寄存器
ARM工作模式 ARM有8个基本的工作模式 User 非特权模式,一般在执行上层的应用程序时ARM处于该模式FIQ 当一个高优先级中断产生后ARM将进入这种模式IRQ 当一个低优先级中断产生后ARM将进入这种模式SVC 当复位或执行软中断指令后ARM将进入这种模式Abort 当产生存取异常…...
git操作修改历史版本指定tag标签的代码,并发布新标签
场景: 当项目已经迭代多个版本之后,突然发现旧版本0.0.1出现了紧急bug,需要及时处理; 如果直接用新版本替换上去是存在极大隐患的,且时间来不及; 所以需要直接在0.0.1版本的基础上去修复bug,然…...
SpringMVC——响应处理(1)【包含源码分析】
Controller public class JsonReturnController {ResponseBodyGetMapping("/getPet")public Pet getPet(){Pet petnew Pet();pet.setAge(5);pet.setName("lily");return pet;} }项目启动后 浏览器输入 http://localhost:8080/getPet 。 debug DispatcherS…...
Normalization
1、BN(Batch Normalization) 深度网络参数训练时内部存在协方差偏移(Internal Covariate Shift)现 象:深度网络内部数据分布在训练过程中发生变化的现象。训练深度网络时,神经网络隐层参数更新会导致网络输…...
27K测试老鸟分享自己6年面试心得,四种公司、四种问题…
这里总结了下自己今年的面试情况 先说一下自己的个人情况,普通二本计算机专业毕业,懂python,会写脚本,会selenium,会性能。趁着金三银四跳槽季,面试字节跳动测试岗技术面都已经过了,本来以为是…...
中小企业数字化自动化转型的方法
自动化是我们国内未来的趋势。智能制造的实现主要依托两个基础能力,一个是工业制造技术,另一个就是工业互联网。而自动化是工业制造技术的重要组成部分,是高度智能制造装备的核心部分,与承接着制造单元与工业互联网这两大核心。懂…...
利用GPT-3 Fine-tunes训练专属语言模型
利用GPT-3 Fine-tunes训练专属语言模型 文章目录什么是模型微调(fine-tuning)?为什么需要模型微调?微调 vs 重新训练微调 vs 提示设计训练专属模型数据准备清洗数据构建模型微调模型评估模型部署模型总结什么是模型微调࿰…...
kubeadm方式安装k8s高可用集群(版本1.26x)
K8S官网:https://kubernetes.io/docs/setup/ 高可用Kubernetes集群规划 配置备注系统版本CentOS 7.9Docker版本20.10.xPod网段172.16.0.0/12Service网段10.103.10.0/16 主机IP说明k8s-master01 ~ 03192.168.77.101 ~ 103master节点 * 3k8s-master-lb192.168.77.2…...
分享5款堪称神器的免费软件,建议先收藏再下载
转眼间新年已经过去一个月了,最近陆陆续续收到好多小伙伴的咨询,这边也是抓紧整理出几个好用的软件,希望可以帮到大家。 1.电脑安全管家——火绒 火绒是一款电脑安全软件,病毒库更新及时,界面清晰干净,没…...
【项目实战】从0开始入门JDK源码 - LinkedList源码
一、源码位置 一般来说IDEA配置好JDK以后 ,JDK的源码其实也配置好了,本文是基于JDK1.8的源码说明 rt - java - util - LinkedList 二、 继承关系图 LinkedList public class LinkedList<E>extends AbstractSequentialList<E>implements...
Polygon zkEVM的gas定价
1. 引言 所有的zkEVM都存在一个有趣的问题: 如何给gas定价? 在Ethereum Virtual Machine (EVM)中,gas通过为每个计算设置economic fee,来保持网络安全。恶意行为,如拒绝服务(DoS)攻击&#x…...
stl中的智能指针类详解
C98/03的尝试——std::auto_ptr C11标准废弃了std::auto_ptr(在C17标准中被移除),取而代之的是std::unique_ptr, std::auto_ptr容易让人误用的地…...
Linux 阻塞和非阻塞 IO 实验
目录 一、阻塞和非阻塞简介 1、IO 概念 2、阻塞与非阻塞 二、等待队列 1、等待队列头 2、等待队列项 3、将队列项添加/移除等待队列头 4、等待唤醒 5、等待事件 三、轮询 1、应用程序的非阻塞函数 2、Linux 驱动下的 poll 操作函数 四、阻塞IO之等待事件唤醒 添加…...
你要的react+ts最佳实践指南
本文根据日常开发实践,参考优秀文章、文档,来说说 TypeScript 是如何较优雅的融入 React 项目的。 温馨提示:日常开发中已全面拥抱函数式组件和 React Hooks,class 类组件的写法这里不提及。 前沿 以前有 JSX 语法,…...
软件测试人员会被替代吗?IT行业哪个方向的前景最好?字节12年测开是这样说的
互联网测试从业12年,前来作答。 逻辑上来说,软件工程最初始只需要两个岗位,一个是产品经理。,一个是研发(开发),剩余的 所有岗位都是由他们衍生而来的。 第三个岗位大概率就是测试,…...
十六、vue3.0之富文本编辑器的选择
在工作过程中我们会遇到很多的时候会使用到富文本编辑器,市场上流行的也是各种各样的,那么究竟如何选择呢,今天就给大家讲讲有哪一些,方便大家的选择。 一、TinyMCE TinyMCE 是富文本编辑器领域的头部玩家之一,主流富文本编辑器,功能非常全,你需要的大多数功能它都支持…...
kafka(一) 的架构,各概念
Kafka架构 Kafak 总体架构图中包含多个概念: (1)ZooKeeper:Zookeeper负责保存broker集群元数据,并对控制器进行选举等操作。 (2)Producer: 生产者负责创建消息,将消息发…...
【ts的常用类型】
ts的常用类型前言安装ts常见类型原始类型 、数组、 any变量上的类型注解函数对象类型联合类型类型别名接口接口和类型别名的对比前言 typescript中为了使编写的代码更规范,更有利于维护,增加了类型校验,安装 安装 typescript npm i typescr…...
Hyper-V与安卓模拟器不共存
一是某些新的模拟器已经开始使用新接口开发,支持了共存,安装这种新的安卓模拟器即可。 对于不支持共存的模拟器,只得增加一个windows开机后的系统选项,如果需要切换这两种不同选项使用系统,每次切换都需要重启windows系…...
【图像分类】卷积神经网络之ZFNet网络模型结构详解
写在前面: 首先感谢兄弟们的关注和订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。 1. 前言 由于AlexNet的提出,大型卷积网络开始变得流行起来,但是人们对于网络究竟为什么能表现的这么好,以及怎…...
亿级高并发电商项目-- 实战篇 --万达商城项目 十三(编写购物车、优化修改商品、下架商品方法、购物车模块监听修改商品、删除商品消息)
👏作者简介:大家好,我是小童,Java开发工程师,CSDN博客博主,Java领域新星创作者 📕系列专栏:前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶 Ǵ…...
springboot 虚拟线程demo
jd19支持虚拟线程,虚拟线程是轻量级的线程,它们不与操作系统线程绑定,而是由 JVM 来管理。它们适用于“每个请求一个线程”的编程风格,同时没有操作系统线程的限制。我们能够创建数以百万计的虚拟线程而不会影响吞吐。 做个 spri…...
CTFer成长之路之逻辑漏洞
逻辑漏洞CTF 访问url: http://1b43ac78-61f7-4b3c-9ab7-d7e131e7da80.node3.buuoj.cn/ 登录页面用随意用户名密码登录 访问url: http://1b43ac78-61f7-4b3c-9ab7-d7e131e7da80.node3.buuoj.cn/user.php 登陆后有商品列表,共三个商品,点击购买flag 钱…...
入门力扣自学笔记238 C++ (题目编号:1144)
1144. 递减元素使数组呈锯齿状 题目: 给你一个整数数组 nums,每次 操作 会从中选择一个元素并 将该元素的值减少 1。 如果符合下列情况之一,则数组 A 就是 锯齿数组: 每个偶数索引对应的元素都大于相邻的元素,即 A…...
网站建设和开发/g3云推广
注:本文来自维基教科书引用网址:http://zh.wikibooks.org/zh-cn/Vim/%E4%B8%89%E7%A7%8D%E6%A8%A1%E5%BC%8FVim和Vi一样具有三种模式:命令模式(Command mode),插入模式(Insert mode)和底线命令模式(Last line mode)。当用户处于不…...
wordpress readme/全国防疫大数据平台
那Swing的话就是那么样哪。如JTextField jtfnew JTextField(40);你要从文本框提取数据就用jtf.getText()但的确获得的是String型的,java中Interger类封装了一个静态方法parseInt(String s)就用Interger.parseInt(jtf.getText.trim())//这个就可以获取文本框的内容,t…...
网站流量来源/企业管理软件管理系统
jQuery UI是一套非常好用的jQuery Tools库,目前已经发布的最新版本是1.8.4。在我自己的使用过程中,总有一些不爽。因为我下载的那个包里默认的主题样式是下图这样的,使用起来很难和具体的网页风格去配合。 一开始,我准备去动手&am…...
做积分商城网站/网站技术外包公司
1. CAP 的由来 要理解 CAP,首先我们要清楚,为何会有人提出 CAP?他提出 CAP 是为了解决什么问题? 时间回到 1985 年,彼时,后来证明了 CAP 理论的 Lynch 教授此时给当时的 IT 界来了一记惊雷: …...
给男票做网站表白的软件/网站关键词排名查询
getSqlSessionFactory 1.new SqlSessionFactoryBuilder().bulid(全局配置文件的流in)2.build(in) 进入build(in)3.parser new XMLconfigurationBuilder(in) 创建解析器解析 全局配置文件 build(parser.parse()) 进入parse() 方法4.parse()最后返回的 是 configurationparseC…...
网站建设方法有那几种/百度百科官网登录
昨天提交给苹果审核版本的时候出现了: ERROR ITMS-90037:"This bundle is invalid. the Info.plist is missing or could not be parsed. Please check it for embedded control characters..." 从网上找了各种方法,最后还是给解决了ÿ…...