JVM—类加载器、双亲委派机制
目录
什么是类加载器
类加载器的分类
Bootstrap启动类加载器
通过启动类加载器加载用户jar包
Extension扩展类加载器和Application应用程序类加载器
通过扩展类加载器加载用户jar包
双亲委派机制
打破双亲委派机制
自定义类加载器
线程上下文类加载器
Osgi框架的类加载器
总结
JDK9之后的类加载器
什么是类加载器
类加载器(ClassLoader)是Java虚拟机提供给应用程序去实现获取类和接口字节码数据的技术,类加载器只参与加载过程中的字节码获取并加载到内存这一部分。
类加载器会通过二进制流的方式获取到字节码文件的内容,接下来将获取到的数据交给Java虚拟机,虚拟机会在方法区和堆上生成对应的对象保存字节码信息。
类加载器的分类
类加载器分为两类,一类是Java代码中实现的,一类是Java虚拟机底层源码实现的。
1. JDK中默认提供或者自定义:JDK中默认提供了多种处理不同渠道的类加载器,程序员也可以自己根据需求定制,使用Java语言。所有Java中实现的类加载器都需要继承ClassLoader这个抽象类。
2. 虚拟机底层实现:源代码位于Java虚拟机的源码中,实现语言与虚拟机底层语言一致,比如Hotspot使用C++。主要目的是保证Java程序运行中基础类被正确地加载,比如java.lang.String,Java虚拟机需要确保其可靠性。
类加载器的设计JDK8和8之后的版本差别较大,首先来看JDK8及之前的版本,这些版本中默认的类加载器有如下几种:
Bootstrap启动类加载器
1. 启动类加载器(Bootstrap ClassLoader)是由Hotspot虚拟机提供的、使用C++编写的类加载器。
2. 默认加载Java安装目录/jre/lib下的类文件,比如rt.jar,tools.jar,resources.jar等。
/*** 启动程序类加载器案例*/
public class BootstrapClassLoaderDemo {public static void main(String[] args) throws IOException {ClassLoader classLoader = String.class.getClassLoader();System.out.println(classLoader);System.in.read();}
}
这段代码通过String类获取到它的类加载器(Bootstrap)并且打印,结果是null
。这是因为启动类加载器在JDK8中是由C++语言来编写的,在Java代码中去获取既不适合也不安全,所以返回null。
通过启动类加载器加载用户jar包
如果用户想扩展一些比较基础的jar包,并让启动类加载器加载,有以下两种途径。
1. 放入jre/lib下进行扩展(不推荐):尽可能不要去更改JDK安装目录中的内容,会出现即时放进去由于文件名不匹配的问题也不会正常地被加载;
2. 使用参数进行扩展(推荐):使用-Xbootclasspath/a:jar包目录/jar包名 进行扩展,参数中的/a代表新增。
如下图,在IDEA配置中添加虚拟机参数,就可以加载D:/jvm/jar/classloader-test.jar
这个jar包了。
Extension扩展类加载器和Application应用程序类加载器
1. ClassLoader类定义了具体的行为模式,简单来说就是先从本地或者网络获得字节码信息,然后调用虚拟机底层的方法创建方法区和堆上的对象。这样的好处就是让子类只需要去实现如何获取字节码信息这部分代码;
2. SecureClassLoader提供了证书机制,提升了安全性;
3. URLClassLoader提供了根据URL获取目录下或者指定jar包进行加载,获取字节码的数据;
4. 扩展类加载器和应用程序类加载器继承自URLClassLoader,获得了上述的三种能力。
通过扩展类加载器加载用户jar包
1. 放入/jre/lib/ext下进行扩展(不推荐):尽可能不要去更改JDK安装目录中的内容;
2. 使用参数进行扩展使用参数进行扩展(推荐):使用-Djava.ext.dirs=jar包目录 进行扩展,这种方式会覆盖掉原始目录,可以用;(windows系统)或:(macos/linux系统)符号进行分隔追加上原始目录,如下图。
使用引号将整个地址包裹起来,这样路径中即便是有空格也不需要额外处理。路径中要包含原来ext文件夹,同时在最后加上扩展的路径。
双亲委派机制
面试题1:什么是双亲委派机制
1、当一个类加载器在加载某个类时,会先自底向上查找是否有加载器加载过,如果加载过就直接返回,如果一直到最顶层的类加载器都没有加载,再由顶向下进行加载;
2、应用程序类加载器的父类加载器是扩展类加载器,扩展类加载器的父类加载器是启动类加载器。
面试题2:双亲委派的作用/好处有哪些?
1.保证类加载的安全性。通过双亲委派机制避免恶意代码替换JDK中的核心类库,比如java.lang.String,确保核心类库的完整性和安全性;
2.避免重复加载。双亲委派机制可以避免同一个类被多次加载。
面试题3:如果一个类重复出现在三个类加载器的加载位置,应该由谁来加载?
答:由启动类加载器加载,根据双亲委派机制,它的优先级是最高的。
面试题4:String类能被覆盖吗,在自己的项目中创建一个java.lang.String类,会被加载吗?
不会,因为存在双亲委派机制,类不会被重复加载,会返回启动类加载器加载在rt.jar包中的String类。
打破双亲委派机制
打破双亲委派机制历史上有如下三种方式,但本质上只有第一种算是真正的打破了双亲委派机制。
1. 自定义类加载器并且重写loadClass方法。Tomcat通过这种方式实现应用之间类隔离;
2. 线程上下文类加载器。利用上下文类加载器加载类,比如JDBC和JNDI等;
3. Osgi框架的类加载器。历史上Osgi框架实现了一套新的类加载器机制,允许同级之间委托进行类的加载,目前很少使用。
自定义类加载器
一个Tomcat程序中是可以运行多个Web应用的,如果这两个应用中出现了相同限定名的类,比如Servlet类,Tomcat就需要保证这两个类都能加载并且它们应该是不同的类。如果不打破双亲委派机制,当应用类加载器加载Web应用1中的MyServlet之后,Web应用2中相同限定名的MyServlet类就无法被加载了。
那么自定义加载器是如何做到打破双亲委派机制的呢?首先我们需要了解双亲委派机制的代码到底在哪里,接下来只需要把这段代码消除即可。
ClassLoader中包含了4个核心方法,双亲委派机制的核心代码就位于loadClass方法中。
//类加载的入口,提供了双亲委派机制。内部会调用findClass [重要]
public Class<?> loadClass(String name)//由类加载器子类实现,获取二进制数据调用defineClass
//比如URLClassLoader会根据文件路径去获取类文件中的二进制数据。[重要]
protected Class<?> findClass(String name)//做一些类名的校验,然后调用虚拟机底层的方法将字节码信息加载到虚拟机内存中
protected final Class<?> defineClass(String name, byte[] b, int off, int len)//执行类生命周期中的连接阶段
protected final void resolveClass(Class<?> c)
loadClass方法核心代码如下
//先查找是否加载过,加载过就返回
Class<?> c = findLoadedClass(name);//如果没有加载过,则委派给父类加载
if(c == null){//parent等于null则说明父类加载器是启动类加载器if(parent != null){c = parent.loadClass(name,false);//由父类加载elsec = findBootstrapClassOrNull(name);//由启动类加载器加载//若父类加载器无法加载,则由本加载器加载if(c == null)c = findClass(name);}return c;
自定义加载器通过重写 loadClass 方法,清除了其中有关双亲委派机制的逻辑,因此打破了双亲委派机制。
按照loadClass方法的逻辑,如果父类加载失败,会调用自己的findClass方法来完成类的加载。如果用户在实现自定义类加载器时,希望按照自己的意愿去加载类,但又想保证自定义类加载器是符合双亲委派机制的,则可以重写findClass方法,在该方法中实现类的加载逻辑,而不必重写loadClass方法,从而保留了双亲委派机制的逻辑。
自定义类加载器打破双亲委派机制代码如下
package classloader.broken;//package com.itheima.jvm.chapter02.classloader.broken;import org.apache.commons.io.IOUtils;import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.ProtectionDomain;
import java.util.regex.Matcher;/*** 打破双亲委派机制 - 自定义类加载器*/public class BreakClassLoader1 extends ClassLoader {private String basePath;private final static String FILE_EXT = ".class";//设置加载目录public void setBasePath(String basePath) {this.basePath = basePath;}//使用commons io 从指定目录下加载文件private byte[] loadClassData(String name) {try {String tempName = name.replaceAll("\\.", Matcher.quoteReplacement(File.separator));FileInputStream fis = new FileInputStream(basePath + tempName + FILE_EXT);try {return IOUtils.toByteArray(fis);} finally {IOUtils.closeQuietly(fis);}} catch (Exception e) {System.out.println("自定义类加载器加载失败,错误原因:" + e.getMessage());return null;}}//重写loadClass方法,不再走双亲委派机制@Overridepublic Class<?> loadClass(String name) throws ClassNotFoundException {//在加载默认的Object父类时,需要交由父类加载if(name.startsWith("java.")){return super.loadClass(name);}//从磁盘中指定目录下加载byte[] data = loadClassData(name);//调用虚拟机底层方法,方法区和堆区创建对象return defineClass(name, data, 0, data.length);}public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {//第一个自定义类加载器对象BreakClassLoader1 classLoader1 = new BreakClassLoader1();classLoader1.setBasePath("D:\\lib\\");Class<?> clazz1 = classLoader1.loadClass("com.itheima.my.A");//第二个自定义类加载器对象BreakClassLoader1 classLoader2 = new BreakClassLoader1();classLoader2.setBasePath("D:\\lib\\");Class<?> clazz2 = classLoader2.loadClass("com.itheima.my.A");System.out.println(clazz1 == clazz2);Thread.currentThread().setContextClassLoader(classLoader1);System.out.println(Thread.currentThread().getContextClassLoader());System.in.read();}
}
默认情况下自定义类加载器的父类加载器是应用程序类加载器。
两个自定义类加载器加载相同限定名的类,不会冲突吗?
不会冲突,在同一个Java虚拟机中,只有相同类加载器+相同的类限定名才会被认为是同一个类。
线程上下文类加载器
利用线程上下文类加载器加载类,比如JDBC和JNDI等,现对JDBC案例进行讨论,首先需要介绍java SPI机制。
Java SPI机制
定义:SPI 是一种基于接口的编程模式,它允许服务提供者在不修改原有系统代码的情况下,通过实现特定接口并将其部署到应用程序的类路径下,从而被应用程序自动加载和使用。服务使用者只需定义接口规范并由服务提供者负责对接口进行实现,服务使用者不用关心具体的实现细节。这使得代码的维护和升级更加容易,降低了模块之间的耦合度。
Java SPI 的详细工作原理如下
1. 定义服务接口: 首先,定义一个接口,这个接口将作为服务的规范,规定所有实现类必须遵循的方法;
2. 实现服务接口: 接着,创建一个或多个接口实现类,每个实现类代表一个具体的服务提供者;
3. 注册服务实现: 在实现类的JAR 包中,创建一个 META-INF/services/
目录,并在其中创建一个以服务接口全名命名的文件。文件内容包含实现类的全名,每行一个;
4. 加载和使用服务: 使用 ServiceLoader
类来加载这些服务实现。ServiceLoader
会查找 META-INF/services
目录中的服务定义,并加载所有实现类。
在 Java 中,数据库连接是一个典型的 SPI 应用场景。Java 的java.sql.Driver接口就是一个服务接口。不同数据库厂商(如 MySQL、Oracle、SQL Server 等)提供了各自的Driver实现类。
JDBC中使用了DriverManager来管理项目中引入的不同数据库的驱动,比如mysql驱动、oracle驱动。
DriverManager类由JDK提供,位于rt.jar包中,由启动类加载器加载。DriverManager类需要去加载服务提供者引入的jar包中的驱动类(SPI机制),而jar包中的驱动类需要委派应用程序类加载器去加载,这种父类加载器去请求子类加载器完成类的加载行为,打破了双亲委派机制。Java中涉及SPI的加载基本上都采用这种方式来完成。
Osgi框架的类加载器
历史上,OSGi模块化框架存在同级之间的类加载器的委托加载。OSGi还使用类加载器实现了热部署的功能。热部署指的是在服务不停止的情况下,动态地更新字节码文件到内存中。
以下内容节选自《深入理解 Java 虚拟机》
总结:在 OSGi 环境下,类加载器不再遵循双亲委派模型所推荐的树状结构,而是拥有一套自身的类加载规则,其中部分规则打破了类的双亲委派机制。
总结
在上述介绍的三种打破双亲委派机制的方式中,本质上只有第一种方式算是真正打破了该机制。这是因为双亲委派机制的核心代码在 loadClass 中,而只有第一种方式重写了 loadClass 方法,清除了其中有关双亲委派机制的逻辑。
至于其他两种方式,从宏观层面,也就是类的调用层面来看,违背了双亲委派机制。但这两种方式并没有重写loadClass方法,并未清除有关双亲委派机制逻辑的代码,所以从单个类的角度而言,是符合双亲委派机制的。
JDK9之后的类加载器
JDK8及之前的版本中,扩展类加载器和应用程序类加载器的源码位于rt.jar包中的sun.misc.Launcher.java。
由于JDK9引入了module的概念,类加载器在设计上发生了很多变化。
1.启动类加载器使用Java编写,位于jdk.internal.loader.ClassLoaders类中。
Java中的BootClassLoader继承自BuiltinClassLoader,实现从模块中找到要加载的字节码资源文件。启动类加载器依然无法通过java代码获取到,返回的仍然是null,保持了统一。
2、扩展类加载器被替换成了平台类加载器(Platform Class Loader)。
平台类加载器遵循模块化方式加载字节码文件,所以继承关系从URLClassLoader变成了BuiltinClassLoader,BuiltinClassLoader实现了从模块中加载字节码文件。平台类加载器的存在更多的是为了与老版本的设计方案兼容,自身没有特殊的逻辑。
相关文章:
JVM—类加载器、双亲委派机制
目录 什么是类加载器 类加载器的分类 Bootstrap启动类加载器 通过启动类加载器加载用户jar包 Extension扩展类加载器和Application应用程序类加载器 通过扩展类加载器加载用户jar包 双亲委派机制 打破双亲委派机制 自定义类加载器 线程上下文类加载器 Osgi框架的类加…...
笔试题 求空格分割的英文句子中,最大单词长度。
求空格分割的英文句子中,最大单词长度。例如:“this is a word”,最大单词长度为4。要求:不能用 split 函数对字符串进行切分,算法复杂度为o(n) public class MaxWordLength { public static int maxWordLength(String sentence) { if (se…...
【笔记】大模型长度外推技术 NTK-Aware Scaled RoPE
NTK-Aware Scaled RoPE 正弦编码(Sinusoidal)旋转位置编码RoPE编码步骤:旋转位置编码的优势 NTK-Aware Scaled RoPE直接外推线性内插进制转换高频外推、低频内插的理解位置编码 总结参考: 长度外推技术是自然语言处理(NLP)领域中&…...
前端 eslint 配置,以及在git提交之前自动format
目录 1、配置eslint步骤 1、eslint安装配置步骤 2、配置scripts步骤 3、测试eslint 2、配置git-hook1、安装环境2、最终效果 众所周知,前端项目可以在报很多error的情况下运行。但是良好的代码规范仍然有利于项目的开发维护,这里提供我的规范,…...
2024.10.9华为留学生笔试题解
第一题无线基站名字相似度 动态规划 考虑用动态规划解决 char1=input().strip() char2=input().strip() n,m=len(char1),len(char2) dp=[[0]*(m+1) for _ in range(n+1)] #dp[i][j]定义为以i-1为结尾的char1 和以 j-1为结尾的char2 的最短编辑距离 setA = set(wirel@com) set…...
利用ADPF性能提示优化Android应用体验
Android Dynamic Performance Framework(ADPF)是google推广的一套用于优化散热以及CPU性能的动态性能框架。本文主要介绍其中的performance hint的部分。 1、为何引入ADPF 我们都知道,在大多数设备上,Android 会动态调整CPU的频率和核心类型。如果work l…...
论文阅读 - Pre-trained Online Contrastive Learning for Insurance Fraud Detection
Pre-trained Online Contrastive Learning for Insurance Fraud Detection| Proceedings of the AAAI Conference on Artificial Intelligence 目录 摘要 Introduction Methodology Problem Formulation Pre-trained Model for Enhanced Robustness Detecting Network a…...
【最全基础知识2】机器视觉系统硬件组成之工业相机镜头篇--51camera
机器视觉系统中,工业镜头作为必备的器件之一,须和工业相机搭配。工业镜头是机器视觉系统中不可或缺的重要组成部分,其质量和性能直接影响到整个系统的成像质量和检测精度。 目录 一、基本功能和作用 二、分类 1、按成像方式分 2、按焦距分 3、按接口类型分 4、按应用…...
虚拟机WIN7安装PADS VX24 出现脚本故障 IPW213
用虚拟机安装WIN7,再开始安装PADS V24出现脚本故障IPW213 有去.NetFramework3.5 仍然没有效果 Download Microsoft .NET Framework 3.5 from Official Microsoft Download Center 最终用360驱动大师检测了下 发现有些必备组件没有安装,安装之后重启。 …...
Java正则表达式详解万字笔记内容丰富
正则表达式 1.1 正则表达式的概念及演示 在Java中,我们经常需要验证一些字符串,例如:年龄必须是2位的数字、用户名必须是8位长度而且只能包含大小写字母、数字等。正则表达式就是用来验证各种字符串的规则。它内部描述了一些规则,…...
文件属性与目录
⚫ Linux 系统的文件类型; 普通文件:存储数据,如文本文件、可执行文件等。 目录:用于组织文件和其他目录的特殊文件。 符号链接:指向另一个文件或目录的引用,类似于 Windows 中的快捷方式。 硬链接&#x…...
5G 基站SCTP
如何实现SCTP多归属链路对接 文章目录 前言一、SCTP是什么?二、lksctp三.sctp初始化四.绑定本端两个IP 五.与对端建链六.设置主要路径七.设置是否启用心跳八.关于防火墙的配置 总结 …...
MFC的SendMessage与PostMessage的区别
一、SendMessage 同步操作: SendMessage 是一个同步函数,它会将消息发送到指定的窗口,并等待该窗口的消息处理过程完成,然后返回。这意味着它会阻塞当前线程,直到消息处理完成。 直接调用: SendMessage 会…...
学习虚幻C++开发日志——基础案例(持续更新中)
官方文档:虚幻引擎C编程教程 | 虚幻引擎 5.5 文档 | Epic Developer Community | Epic Developer Community 1.物体上下起伏并旋转 1.1第一种写法 创建一个继承于Actor的类,并为新的Actor命名为FloatingActor,然后点击Create Class 重新…...
【CUDA代码实践03】m维网格n维线程块对二维矩阵的索引
文章目录 一、数据存储方式二、二维网格二维线程块三、二维网格一维线程块四、一维网格一维线程块 为了方便下次找到文章,也方便联系我给大家提供帮助,欢迎大家点赞👍、收藏📂和关注🔔!一起讨论技术问题&am…...
VSCode Qt6安装OpenSSL
报错 Could NOT find OpenSSL, try to set the path to OpenSSL root folder in thesystem variable OPENSSL_ROOT_DIR (missing: OPENSSL_CRYPTO_LIBRARYOPENSSL_INCLUDE_DIR SSL Crypto) (Required is at least version "3.0")问题确认 这个错误显示在Windows环境…...
JAVA学习-练习试用Java实现“定义一个用户类,包含用户名和密码”
问题: 定义一个用户类(User),包含用户名(username)和密码(password)属性,提供静态方法验证密码是否有效(长度至少为6),并提供getter和…...
大数据之VIP(Virtual IP,虚拟IP)负载均衡
VIP(Virtual IP,虚拟IP)负载均衡是一种在计算机网络中常用的技术,用于将网络请求流量均匀地分散到多个服务器上,以提高系统的可扩展性、可靠性和性能。以下是对VIP负载均衡的详细解释: 一、VIP负载均衡的基…...
鸿蒙网络编程系列38-Web组件文件下载示例
1. web组件文件下载能力简介 在本系列的第22篇文章,介绍了web组件的文件上传能力,同样的,web组件也具备文件下载能力,鸿蒙API提供了处理web组件下载事件的委托类型WebDownloadDelegate,该类型包括四个下载事件的回调接…...
Cisco Packet Tracer 8.0 路由器的基本配置和Telnet设置
文章目录 构建拓扑图配置IP地址配置路由器命令说明测试效果 构建拓扑图 1,添加2811路由器。 2,添加pc0。 3,使用交叉线连接路由器和pc(注意线路端口)。 4,使用配置线连接路由器和pc(注意线路…...
Flink系列之:学习理解通过状态快照实现容错
Flink系列之:学习理解通过状态快照实现容错 状态后端检查点存储状态快照状态快照如何工作?确保精确一次(exactly once)端到端精确一次 状态后端 由 Flink 管理的 keyed state 是一种分片的键/值存储,每个 keyed state…...
Linux 读者写者模型
1.背景概念 在编写多线程的时候,有一种情况是十分常见的。那就是,有些公共数据修改的机会比较少。相比较改写,它们读的机会反而高的多。这样就衍生出了读者写者模型,在这个模型中,有两类线程:读者和写者。读…...
JavaScript 的 axios 实现文件下载功能
用 JavaScript 的 axios 实现文件下载功能,咱们要分几个步骤来搞定它!最主要的部分是处理 二进制数据,可以生成一个进度检测,然后把它保存为文件。 文件名的获取二进制数据获取创建下载链接 const axios require(axios);const g…...
合合信息亮相2024中国模式识别与计算机视觉大会,用AI构建图像内容安全防线
近日,第七届中国模式识别与计算机视觉大会(简称“PRCV 2024”)在乌鲁木齐举办。大会由中国自动化学会(CAA)、中国图象图形学学会(CSIG)、中国人工智能学会(CAAI)和中国计…...
深度学习:匿名函数lambda函数的使用与numerical_gradient函数
背景: 假设我们有一个简单的线性回归模型,其损失函数是均方误差(MSE): class LinearModel:def __init__(self):self.W np.random.randn(1, 1) # 初始化权重def predict(self, x):return np.dot(x, self.W) # 线性预…...
PHP数据类型
几种常用的数据类型: String(字符串) Integer(整型) Float(浮点型) Boolean(布尔型) NULL(空值) Array(数组) Obje…...
2FA-双因素认证
双因素认证(2FA,Two-Factor Authentication)是一种提高安全性的方法,要求用户在登录或进行某些敏感操作时提供两种不同类型的身份验证信息。这种方法通过引入第二层验证,增加了账户被未经授权访问的难度。 项目结构 …...
解决 Python 中的 TypeError 错误
解决 Python 中的 TypeError 错误 在 Python 编程中,TypeError 是一种常见的错误,通常发生在尝试对不兼容的类型进行操作时。了解这个错误的原因以及如何有效解决它,对于提高代码的可靠性和可读性至关重要。本文将详细讨论 TypeError 的成因…...
快速学会C 语言基本概念和语法结构
😀前言 本篇博文是关于C 语言的基本概念和语法结构,希望你能够喜欢 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀,希望我的文章可以帮助到大家,您的满意是我的动力&a…...
Python酷库之旅-第三方库Pandas(172)
目录 一、用法精讲 791、pandas.UInt8Dtype类 791-1、语法 791-2、参数 791-3、功能 791-4、返回值 791-5、说明 791-6、用法 791-6-1、数据准备 791-6-2、代码示例 791-6-3、结果输出 792、pandas.UInt16Dtype类 792-1、语法 792-2、参数 792-3、功能 792-4、…...
杭州网站建设(推荐乐云践新)/济南seo网站排名关键词优化
1.Wait 用法默认情况下,Task 是有线程池中的异步线程执行,是否执行完成,可以通过Task的的属性IsCompleted 来判断, 如果想在子线程工作完成之后,在进行后续主线程工作可以通过调用task.Wait() 来等待线程完成ÿ…...
网站开发需呀那些技术/揭阳市seo上词外包
[转载]Linux下非root用户如何安装软件这是本人遇到的实际问题,之前用到的所有机器,无论是自己的PC还是云服务器,root权限都是妥妥的,但是现在发现实验室的服务器原来自己并没有root权限2333再看用户的权限。root用户是bug…...
快速建设网站视频教程/网络营销的营销理念
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以…...
东莞厚街网站建设/网站排名软件
转自 http://cryinstall.com/?p121 Mr高 被钟大神忽悠装了Opensuse,然后这俩家伙对装系统的引导项设置不对劲,Opensuse的grub直接装到硬盘的MBR上, 然后华丽丽的把原来Fedora 16的grub2给覆盖了,接着Opensuse又识别不了grub2,….…...
备案网站简介怎么写/郑州企业网站优化排名
import timeprint time.strftime(%Y-%m-%d %H:%M:%S, time.localtime(time.time())) 转载于:https://www.cnblogs.com/huangshiyu13/p/7751657.html...
对网站建设起到计划和指导的作用/最新百度快速排名技术
ubuntu18.04.5设置开机脚本报“/etc/rc.local: 17: /etc/rc.local: exit 0: not found”的问题 最近因工作需要,在编写代码时经常需要使用Android Studiu自带的虚拟机,但是虚拟机本身需要修改权限,使用chmod修改权限又只能暂时生效ÿ…...