类加载器与双亲委派
类加载器与双亲委派
Java 类加载器(Class Loader)是 Java 虚拟机(JVM)的一部分,负责将类的字节码加载到内存中,并将其转换为可执行的 Java 对象。类加载器在 Java 应用程序中起着重要的作用,它实现了动态加载类的机制,使得 Java 具备了灵活性和可扩展性。
1. 概念
1.1 类加载的过程
类的生命周期通常包括:加载、链接(验证、准备、解析)、初始化、使用和卸载。其中类加载的三个阶段为:加载、链接(验证、准备、解析)、初始化、
其作用分别为:
- 加载:通过一个类的完全限定查找类字节码文件,转化为方法区运行时的数据结构,创建一个代表该类的 Class 对象。
- 链接:
- 验证:确保 Class 文件的字节流中包含信息符合当前虚拟机要求,不会危害虚拟机自身安全。
- 准备:为类变量(即 static 修饰的字段变量)分配内存并且设置该类变量的初始值。不包含被 final 修饰的 static 变量,因为它在编译时已经分配了。
- 解析:将常量池内的符号引用转换为直接引用的过程。如果符号引用指向一个未被加载的类,或者未被加载类的字段或方法,那么解析将触发这个类的加载。
- 初始化:类加载最后阶段,若该类具有超类,则对其进行初始化,执行静态初始化器和静态初始化成员变量。
1.2 Java 类加载器
Java 类加载器:
Java 虚拟机用于加载类文件的一种机制。在 Java 中,每个类都由类加载器加载,并在运行时被创建为一个 Class 对象。类加载器负责从文件系统、网络或其他来源中加载类的字节码,并将其转换为可执行的 Java 对象。类加载器还负责解析类的依赖关系,即加载所需的其他类。
虚拟机内部提供了三种类加载器:
- 启动(Bootstrap)类加载器:也称为根类加载器,它负责加载 Java 虚拟机的核心类库,如 java.lang.Object 等。启动类加载器是虚拟机实现的一部分,它通常是由本地代码实现的,不是 Java 类。
- 扩展(Extension)类加载器:用来加载 Java 扩展类库的类加载器。扩展类库包括 javax 和 java.util 等包,它们位于 jre/lib/ext 目录下。
- 系统(System)类加载器:也称应用类加载器,它负责加载应用程序的类。它会搜索应用程序的类路径(包括用户定义的类路径和系统类路径),并加载类文件。
用户可以自定义类加载器。
1.3 双亲委派模型:加载类
类加载器采用了双亲委派模型(Parent Delegation Model)来加载类。即当一个类加载器需要加载类时,它会首先委派给其父类加载器加载。如果父类加载器无法加载,才由该类加载器自己去加载。这种层级关系使得类加载器能够实现类的共享和隔离,提高了代码的安全性和可靠性。
1.3.1 双亲委派模型的执行流程
双亲委派模型的执行流程:
1、当加载一个类时,会先从应用程序类加载器的缓存里查找相应的类,如果能找到就返回对象,如果找不到就执行下面流程;
2、在扩展加载器缓存中查找相应的类,如果能找到就返回对象,如果找不到就继续下面流程;
3、在启动类加载器中查询相应的类,如果找到就返回对象,如果找不到就继续下面流程;
4、在扩展加载器中查找并加载类,如果能找到就返回对象,并将对象加入到缓存中,如果找不到就继续下面流程;
5、在应用程序类加载器中查找并加载类,如果能找到就返回对象,并将对象加入到缓存中,如果找不到就返回 ClassNotFound 异常。
即当一个类加载器收到了一个类加载请求时,它自己不会先去尝试加载这个类,而是把这个请求转交给父类加载器
。
双亲的含义:
- 向上查找缓存并加载
- 向下加载类
ClassLoader 内的 loadClass 方法中的双亲委派实现:
protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {//检查该class是否已经被当前类加载器加载过,这是一个抽象方法,具体实现由子类实现Class<?> c = findLoadedClass(name);if (c == null) {//此时该class还没有被加载try {if (parent != null) {//如果父加载器不为null,则委托给父类加载c = parent.loadClass(name, false);} else {//如果父加载器为null,说明当前类加载器已经是启动类加载器,直接时候用启动类加载器去加载该classc = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {}if (c == null) {//此时父类加载器都无法加载该class,则使用当前类加载器进行加载long t1 = System.nanoTime();c = findClass(name);...}}//是否需要连接该类if (resolve) {resolveClass(c);}return c;}}
1.3.2 优点
安全
用户无法伪造不安全的系统类。根据双亲委派模型,jre 提供的类在启动类和扩展类加载时加载早于用户伪造的系统类的应用类加载。
避免重复加载
当一个类加载后,会被缓存,不会出现多个类加载器将同一个类重复加载的情况。
1.3.3 缺点
加载 SPI 实现类的场景
类加载的范围受到限制,某些情况下父 class loader 无法加载某些类文件,这时候就需要委托到下层级的 class loader 去加载类文件。
双亲委派使得启动类加载器无法加载用户的 jar 包,比如:
- 装载 JDBC 驱动实现类的 DriverManager 类是 JDK 核心类,而被装载的类是用户类,导致无法加载的尴尬问题,需要用 Context Class Loader 来加载 Driver 实现类,从而打破了双亲委派模型。
- 在 tomcat 中,子加载器优先于父加载器加载。即为了实现各个 webapp 的隔离性,webappClassLoader 会先于父加载器加载。
2. 自定义类加载器
参考 ClassLoader 的实现流程,需要依次实现:
- loadclass:双亲委派机制,子加载器委托父加载器加载,父加载器都加载失败时,子加载器通过 findclass 自行加载。该方法使用了模版方法模式,继承 ClassLoader 后,不需要我们实现。
- findclass:当前类加载器根据路径以及 class 文件名称加载字节码,从 class 文件中读取字节数组,然后使用 defineClass
- defineclass:根据字节数组,返回 Class 对象。
在 ClassLoader 的源码中,提供了一个自定义类加载器的模版:
class NetworkClassLoader extends ClassLoader {String host;int port;public Class findClass(String name) {// 读取class文件,转化为字节数组byte[] b = loadClassData(name);// 读取字节数组,转化为Class对象return defineClass(name, b, 0, b.length);}private byte[] loadClassData(String name) {// load the class data from the connection}}
可以看到只需要继承 ClassLoader,并且重写 findClass 方法即可。
3. JDBC 打破双亲委派
jdk 为了统一管理数据库驱动,在 java.sql 下定义了 Driver 接口,具体的实现由数据库厂商去做。
3.1 JDBC 4.0 之前
// 使用应用类加载器加载 Driver 实现类Class.forName("com.mysql.jdbc.Driver");Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
public class Driver extends NonRegisteringDriver implements java.sql.Driver {public Driver() throws SQLException {}static {try {//将mysql的Driver注册进驱动管理器中DriverManager.registerDriver(new Driver());} catch (SQLException var1) {throw new RuntimeException("Can't register driver!");}}
}
加载 Driver 实现类的过程:
- Class.forName 会使用应用类加载器加载 Driver 实现类
- 加载 Driver 实现类需要执行静态方法,即将 mysql 的 Driver 注册进驱动管理器中,那么此时需要加载 DriverManager 类
- 应用类加载器去加载 DriverManager 类,而 DriverManager 位于 rt.jar 中,便一直向上委托到启动类加载器完成加载
没有破坏双亲委派
3.2 JDBC 4.0 之后
// 直接调用 DriverManager获取驱动列表Enumeration<Driver> en = DriverManager.getDrivers();while (en.hasMoreElements()) {java.sql.Driver driver = en.nextElement();System.out.println(driver);}
应用类加载器逐层委托到启动类加载器去加载 DriverManager 时,会同时执行它的静态方法
static {loadInitialDrivers();println("JDBC DriverManager initialized");}
启动类加载 DriverManager,之后需要通过 spi 机制去加载 jar 包中的 Driver 类,而该 Driver 理应被应用类加载器加载,这个时候就需要启动类加载器去通知应用类加载器,这明显违背了双亲委派机制。
loadInitialDrivers 方法:
ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);Iterator<Driver> driversIterator = loadedDrivers.iterator();
ServiceLoader.load 方法,Thread.currentThread().getContextClassLoader()是线程上下文类加载器,使用的是线程上下文类加载器去加载的 Driver 实现类。
public static <S> ServiceLoader<S> load(Class<S> service) {ClassLoader cl = Thread.currentThread().getContextClassLoader();return ServiceLoader.load(service, cl);}
在 sun.misc.Launcher 类中,将应用类加载器设置进了线程上下文类加载器中,通过线程上下文类加载器,我们可以拿到应用类加载器的引用:
public Launcher() {this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);Thread.currentThread().setContextClassLoader(this.loader);}
打破双亲委派的过程:
在 jdbc4.0 的情况下,梳理一下整个过程:
- 应用类加载器逐层委托到启动类加载器去加载 DriverManager 类
- 启动类加载器加载 DriverManager 类时,会执行其静态方法,即通过 spi 机制去加载 jar 包中的 Driver 实现类
- 此时启动类加载器需要委托应用类加载器加载 Driver 实现类,具体做法是通过线程上下文类加载器拿到应用类加载器的引用
4. TOMCAT 打破双亲委派
TOMCAT 的两个基础功能点:
- 实时更新 JSP
- 应用打包放在 webapps 目录下就可以运行
4.1 实时更新 JSP
JVM 确定类的唯一性:由类加载器实例+全限定名一起确定的。全限定名相同,类加载器不同,则会被认定为不同的类。
4.2 应用打包放在 webapps 目录下就可以运行
应用 A 和应用 B 所依赖的 Spring 版本不同,却依旧可以运行。
webapps 下的每一个应用都会对应一个不同的类加载器实例,用以保持应用间的隔离。
4.3 打破双亲委派
某个自定义的类加载想要打破双亲委派,只需要重写 loadClass 方法即可。
Tomcat 中的 WebappClassLoader 就是自定义类加载器,它的 loadClass 方法为:
public Class loadClass(String name) throws ClassNotFoundException {return (loadClass(name, false));}public Class loadClass(String name, boolean resolve)throws ClassNotFoundException {if (log.isDebugEnabled())log.debug("loadClass(" + name + ", " + resolve + ")");Class clazz = null;// Log access to stopped classloaderif (!started) {try {throw new IllegalStateException();} catch (IllegalStateException e) {log.info(sm.getString("webappClassLoader.stopped", name), e);}}//1、从自己的本地缓存中查找,本地缓存的数据结构为ResourceEntryclazz = findLoadedClass0(name);if (clazz != null) {if (log.isDebugEnabled())log.debug(" Returning class from cache");if (resolve)resolveClass(clazz);return (clazz);}//2、从jvm的缓存中查找clazz = findLoadedClass(name);if (clazz != null) {if (log.isDebugEnabled())log.debug(" Returning class from cache");if (resolve)resolveClass(clazz);return (clazz);}//3、如果缓存中都找不到,则利用系统类加载器加载try {clazz = system.loadClass(name);if (clazz != null) {if (resolve)resolveClass(clazz);return (clazz);}} catch (ClassNotFoundException e) {// Ignore}if (securityManager != null) {int i = name.lastIndexOf('.');if (i >= 0) {try {securityManager.checkPackageAccess(name.substring(0,i));} catch (SecurityException se) {String error = "Security Violation, attempt to use " +"Restricted Class: " + name;log.info(error, se);throw new ClassNotFoundException(error, se);}}}boolean delegateLoad = delegate || filter(name);//4、开启代理的话,则使用父加载器加载if (delegateLoad) {if (log.isDebugEnabled())log.debug(" Delegating to parent classloader1 " + parent);ClassLoader loader = parent;if (loader == null)loader = system;try {clazz = loader.loadClass(name);if (clazz != null) {if (log.isDebugEnabled())log.debug(" Loading class from parent");if (resolve)resolveClass(clazz);return (clazz);}} catch (ClassNotFoundException e) {;}}//5、自行加载if (log.isDebugEnabled())log.debug(" Searching local repositories");try {clazz = findClass(name);if (clazz != null) {if (log.isDebugEnabled())log.debug(" Loading class from local repository");if (resolve)resolveClass(clazz);return (clazz);}} catch (ClassNotFoundException e) {;}//如果自己也加载不了,那就只能让父加载器加载了if (!delegateLoad) {if (log.isDebugEnabled())log.debug(" Delegating to parent classloader at end: " + parent);ClassLoader loader = parent;if (loader == null)loader = system;try {clazz = loader.loadClass(name);if (clazz != null) {if (log.isDebugEnabled())log.debug(" Loading class from parent");if (resolve)resolveClass(clazz);return (clazz);}} catch (ClassNotFoundException e) {;}}throw new ClassNotFoundException(name);}
内部逻辑:
- 先从 WebappClassLoader 的 ResourceEntry 缓存中查找
- 从 jvm 缓存中查找,比如去元数据区查找
- 利用系统类(应用类)加载器加载,避免 webapp 中的类覆盖掉标准类库中的类。
- 开启代理的话,则使用父加载器加载,这个默认没开启的。
- webappClassLoader 自行去加载
- 自己也没加载成功的话,最后只能让父加载器去加载
即:
- 对于一些标准类库中的类,比如 Object 类,会让系统类加载器加载,然后一直委托到启动类加载器,这个过程是没有违背双亲委派的。
- 而对于 webapp 中独有的类,则是 webappClassLoader 自行去加载,加载失败才让父加载器加载,明显是违背双亲委派的。
参考资料
- 深度思考:老生常谈的双亲委派机制,JDBC、Tomcat 是怎么反其道而行之的?
相关文章:
类加载器与双亲委派
类加载器与双亲委派 Java 类加载器(Class Loader)是 Java 虚拟机(JVM)的一部分,负责将类的字节码加载到内存中,并将其转换为可执行的 Java 对象。类加载器在 Java 应用程序中起着重要的作用,它…...
用Python创造乐趣:编写你自己的探索游戏世界
在当今数字化时代,编程不再是一个专业程序员的专利。无论你是一个编程新手还是有一定经验的开发者,用Python编写简单的游戏是一个有趣且富有创造性的方式。在这篇博客中,我们将探索如何用Python构建一个基本的探索游戏世界,让玩家…...
git stash弹出栈中的指定内容
使用 git stash 的相关命令来选择性地弹出特定的 stash 内容,应用到指定的分支上。如果我们使用 git stash 命令已经存储了多个记录时,每个 stash 记录都会有一个唯一的标识符(stash{0}、stash{1}…)。通过这些标识符可以应用或弹…...
5.7 汇编语言:汇编高效乘法运算
乘法指令是一种在CPU中实现的基本算术操作,用于计算两个数的乘积。在汇编语言中,乘法指令通常是通过mul(无符号乘法)和imul(有符号乘法)这两个指令实现的。由于乘法指令在执行时所消耗的时钟周期较多&#…...
Graphql中的N+1问题
开篇 原文出处 Graphql 是一种 API 查询语言和运行时环境,可以帮助开发人员快速构建可伸缩的 API。然而,尽管 Graphql 可以提供一些优秀的查询性能和数据获取的能力,但是在使用 Graphql 的过程中,开发人员也会遇到一些常见问题&…...
mysql、oracle、sqlserver常见方法区分
整理了包括字符串与日期互转、字符串与数字互转、多行合并为一行、拼接字段等一些常用的函数,当然有些功能实现的方法不止一种,这里列举了部分常用的,后续会持续补充。 MySQLOracleSQL Server字符串转数字 CAST(123 as SIGNED) 或 CONVERT(12…...
AcWing 4382. 快速打字
原题链接:AcWing 4382. 快速打字 关键词:双指针、判断子序列 芭芭拉是一个速度打字员。 为了检查她的打字速度,她进行了一个速度测试。 测试内容是给定她一个字符串 I,她需要将字符串正确打出。 但是,芭芭拉作为一…...
DataFrame.query()--Pandas
1. 函数功能 Pandas 中的一个函数,用于在 DataFrame 中执行查询操作。这个方法会返回一个新的 DataFrame,其中包含符合查询条件的数据行。请注意,query 方法只能用于筛选行,而不能用于筛选列。 2. 函数语法 DataFrame.query(ex…...
【C语言】美元名字和面额对应问题
题目 美元硬币从小到大分为1美分(penny)5美分(nickel)10美分(dime)25美分(quarter)和50美分(half-dollar),写一个程序实现当给出一个数字面额可以…...
uniapp隐藏底部导航栏(非自定义底部导航栏)
uniapp隐藏底部导航栏 看什么看,要多看uni官方文档,里面啥都有 看什么看,要多看uni官方文档,里面啥都有 uniapp官方网址:uni设置TabBar // 展示 uni.showTabBar({animation:true,success() {console.debug(隐藏成功)…...
CSS background 背景
background属性为元素添加背景效果。 它是以下属性的简写,按顺序为: background-colorbackground-imagebackground-repeatbackground-attachmentbackground-position 以下所有示例中的花花.jpg图片的大小是4848。 1 background-color background-col…...
安防监控视频平台EasyCVR视频汇聚平台和税务可视化综合管理应用方案
一、方案概述 为了确保税务执法的规范性和高效性,国家税务总局要求全面推行税务系统的行政执法公示制度、执法全过程记录制度和重大执法决定法制审核制度。为此,需要全面推行执法全过程记录制度,并推进信息化建设,实现执法全过程的…...
深度学习实战50-构建ChatOCR项目:基于大语言模型的OCR识别问答系统实战
大家好,我是微学AI,今天给大家介绍一下深度学习实战50-构建ChatOCR项目:基于大语言模型的OCR识别问答系统实战,该项目是一个基于深度学习和大语言模型的OCR识别问答系统的实战项目。该项目旨在利用深度学习技术和先进的大语言模型,构建一个能够识别图像中文本,并能够回答与…...
计算机安全学习笔记(I):访问控制安全原理
访问控制原理 从广义上来讲,所有的计算机安全都与访问控制有关。 RFC 4949: Internet Security Glossary, Version 2 (rfc-editor.org) RFC 4949 定义的计算机安全:用来实现和保证计算机系统的安全服务的措施,特别是保证访问控制服务的措施…...
Linux 虚拟机安装 hadoop
目录 1 hadoop下载 2 解压hadoop 3 为 hadoop 文件夹改名 4 给 hadoop 文件夹赋权 5 修改环境变量 6 刷新环境变量 7 在hadoop313目录下创建文件夹data 8 检查文件 9 编辑 ./core-site.xml文件 10 编辑./hadoop-env.sh文件 11 编辑./hdfs-site.xml文件 12 编辑./mapr…...
FxFactory 8 Pro Mac 苹果电脑版 fcpx/ae/motion视觉特效软件包
FxFactory pro for mac是应用在Mac上的fcpx/ae/pr视觉特效插件包,包含了成百上千的视觉效果,打包了很多插件,如调色插件,转场插件,视觉插件,特效插件,文字插件,音频插件,…...
解决问题:如何在 Git 中查看提交历史
可以使用以下命令查看 Git 中的提交历史: git log这将显示当前分支上的所有提交历史。每个提交的输出包括提交哈希(SHA-1 值)、作者、日期和提交注释。 您也可以添加一些选项,以获取更详细的提交历史: --oneline 显示…...
不同规模的测试团队分别适合哪些测试用例管理工具?测试用例管理工具选型指南
随着软件系统规模的持续增大,业务复杂度的持续增加,软件测试的复杂度也随之越来越大。软件测试工作的复杂性主要体现在测试用例的编写、维护、执行和管理方面。而创建易于阅读、维护和管理的测试用例能够显著减轻测试工作的复杂性。 本篇文章将较为系统的…...
服务器遭受攻击,CPU升高,流量升高,你一般如何处理
服务器遭受攻击,CPU升高,流量升高,你一般如何处理? 在什么情况下服务器遭受攻击,会导致CPU升高,流量升高 1.DDoS(分布式拒绝服务攻击):这是一种常见的网络攻击方式&…...
GPT生产实践之定制化翻译
GPT生产实践之定制化翻译 GPT除了能用来聊天以外,其实功能非常强大,但是我们如何把它运用到生产实践中去,为公司带来价值呢?下面一个使用案例–使用gpt做专业领域定制化翻译 思路: 定制化:有些公司词条的…...
SpringMVC入门笔记
一、SpringMVC简介 1. 什么是MVC MVC是一种软件架构的思想,将软件按照模型、视图、控制器来划分 M:Model,模型层,指工程中的JavaBean,作用是处理数据 JavaBean分为两类: 一类称为实体类Bean࿱…...
如何构建多域名HTTPS代理服务器转发
在当今互联网时代,安全可靠的网络访问是至关重要的。本文将介绍如何使用SNI Routing技术来构建多域名HTTPS代理服务器转发,轻松实现多域名的安全访问和数据传输。 SNI代表"Server Name Indication",是TLS协议的扩展,用于…...
【Java 高阶】一文精通 Spring MVC - 数据验证(七)
👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主 ⛪️ 个人社区&#x…...
木叶飞舞之【机器人ROS2】篇章_第一节、ROS2 humble及cartorgrapher安装
ROS2的humble安装 1、系统配置ubuntu 22.04 假如长期使用ros2,建议是ubuntu系统或者双系统下安装操作,不要在虚拟机中进行。ubuntu系统能用最新的大系统就用最新的,比如22.04。等明年24.04出来可以用24.04 2、humble安装 ros版本选择humb…...
Git版本管理(02)patch操作和分支操作整理
1 git patch操作 1.1 git diff比较 使用git diff用于显示当前工作区与暂存区或提交历史之间的差异,如果使用它生成patch,则需要使用git apply命令来引入patch 1.2 git patch打包 使用git format-patch生成patch # 打包最近的一个patch: $git format…...
前端需要理解的HTML知识
HTML(超文本标记语言,HyperText Markup Language)不是编程语言,而是定义了网页内容的含义和结构的标记语言。。“超文本”(hypertext)是指连接单个网站内或多个网站间的网页的链接。HTML 使用“标记”&…...
机器学习笔记 - 数据科学中基于 Scikit-Learn、Tensorflow、Pandas 和 Scipy的7种最常用的特征工程技术
一、概述 特征工程描述了制定相关特征的过程,这些特征尽可能准确地描述底层数据科学问题,并使算法能够理解和学习模式。换句话说:您提供的特征可作为将您自己对世界的理解和知识传达给模型的一种方式。 每个特征描述一种信息“片段”。这些部分的总和允许算法得出有关目标变…...
深眸科技创新赋能视觉应用产品,以AI+机器视觉解决行业应用难题
随着工业4.0时代的加速到来,我国工业领域对于机器视觉技术引导的工业自动化和智能化需求持续上涨,国内机器视觉行业进入快速发展黄金期,但需求广泛出现同时也对机器视觉产品的检测能力提出了更高的要求。 传统机器视觉由人工分析图像特征&am…...
2023年国赛 高教社杯数学建模思路 - 案例:异常检测
文章目录 赛题思路一、简介 -- 关于异常检测异常检测监督学习 二、异常检测算法2. 箱线图分析3. 基于距离/密度4. 基于划分思想 建模资料 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 一、简介 – 关于异常…...
【Electron】使用electron-builder打包时下载electron失败或慢的解决方案
问题描述 electron-builder打包时报错信息如下: Building app with electron-builder:• electron-builder version22.14.5 os10.0.19042• description is missed in the package.json appPackageFileE:\h-world\hscmweb-diagrams\dist_electron\bundled\packa…...
湖北省城乡建设厅网站首页/百度地图网页版进入
目前做的项目后台管理系统,用到了el-form中嵌套el-table,并且需要非空验证,效果图如下: 废话不多说,直接上代码 <el-formv-loading"loading":model"currBillType":rules"currBillType.ru…...
管理系统介绍/津seo快速排名
原文:Asp.Net Web API 2第九课——自承载Web API前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html Asp.Net Web API可以需要IIS。你可以在你自己的主机上来承载一个Web API。 本教程来展示在控制台应…...
公司注册后怎么做网站/自己怎么搭建网站
说明: EXP-00091: 出口可疑的统计。 EXP-00091: Exporting questionable statistics. 产生: 在数据库的服务器端和客户端字符集不同的情况下,导出 (dump) 数据库表时,会产生这个错误。虽然产生这个错误,但好像对导…...
中搜网站提交/策划网络营销活动
QList是一种表示链表的模板类。QList是Qt的一种泛型容器类。它以链表方式存储一组值,并能对这组数据进行快速索引,还提供了快速插入和删除等操作。QList、QLinkedList和QVector提供的操作极其相似:*对大多数操作来说,我们用QList就…...
广东网站优化/网上广告宣传怎么做
前几天写了个ffmpeg版本,今天特意抽空改写个vlc版本,之前vlc播放视频后,被接管了不能识别到鼠标,需要重新编译vlc源码得到支持鼠标消息的版本。/*** vlc视频播放类 作者:feiyangqingyun(QQ:517216493) 2018-5-2* 1:多线程实时播放…...
乐云seo商城网站建设/男生最喜欢的浏览器
声明: 以下内容为阅读由周志明编著的《深入理解Java虚拟机JVM高级特性与最佳实战》(第二版)自行总结记录,算不上完全解读了大神的意思,但也没有瞎写。如果写的不清楚的地方,还望能够自行阅读原著。这里写记…...