JVM的艺术—类加载器篇(jvm的类加载机制)
nanshan 2024-11-10 10:11 18 浏览 0 评论
今天我们继续来深入的剖析类加载器的内容。上节课我们讲了类加载器的基本内容,拉勾IT课小编分解:
什么是定义类加载器和初始化类加载器?
· 定义类加载器:假设我们的某一个类是由ExtClassLoader加载的,那么ExtClassLoader称为该类的定义类加载器
· 初始化加载器:能够返回Class对象引用的都叫做该类的初始类加载器,比如类A是由我们的ExtClassLoader加载,那么
ExtClassLoader是该类的定义类加载器,也是该类的初始类加载器,而我们的AppClassLoader也能返回我们A类的引用
那么AppClassLoader也是该类的初始类加载器。
什么是类加载器的双亲委派模型?
上篇文章我们提到了类加载器的双亲委派模型,也可以称为双亲委托模型。今天这篇文章我们就来把这个概念给讲明白。
概念:用一种简单的方式去描述双亲委托的概念。可以分为两个部分去理解
1委托:
jvm加载类的时候是通过双亲委派的方式去加载,自下而上的去委托。
自定义类加载器需要加载类时,先委托应用类加载器去加载,然后应用类加载器又向扩展类加载器去委托,扩展类加载器在向启动类加载器去委托。
如果启动类加载器不能加载该类。那么就向下加载
2加载:
jvm加载类的时候是通过双亲委派的方式去加载委托,但是加载的时候是由上向下去加载的,当委托到最顶层启动类加载器的时候,无法在向上委托,那么
启动类加载器就开始尝试去加载这个类,启动类加载器加载不了就向下交给扩展类加载器去加载,扩展类加载器加载不了就继续向下委托交给应用类加载器
去加载,以此类推。
如果文字描述你还不清楚什么是双亲委托机制,那么我画了一幅图可以更清楚类加载的过程。如下:
通过上图,我们知道更能清楚的知道,双亲委托模型的工作机制,用一句简单的话说,就是需要加载一个类的时候,向上委托,向下加载。
注意:在双亲委派机制中,各个加载器按照父子关系形成树型结构,除了根加载器以外,每一个加载器有且只有一个父加载器。
接下来,我也从jdk底层源码的角度给大家画了一张类加载的主要过程,图如下:
以上就是类加载器加载一个类的重要过程步骤。希望各位小伙儿可以结合源码的方式,仔细再研究一下。其实还挺好理解的。
下面咱们再说说,java采用双亲委托的方式去加载类,这样做的好处是什么呢?
· 双亲委派模型的好处
总所周知:java.lang.object类是所有类的父类,所以我们程序在运行期间会把java.lang.object类加载到内存中,假如java.lang.object类
能够被我们自定义类加载器去加载的话,那么jvm中就会存在多份Object的Class对象,而且这些Class对象是不兼容的。
所以双亲委派模型可以保证java核心类库下的类型的安全。
借助双亲委派模型,我们java核心类库的类必须是由我们的启动类加载器加载的,这样可以确保我们核心类库只会在jvm中存在一份
这就不会给自定义类加载器去加载我们核心类库的类。
根据我们的演示案例,一个class可以由多个类加载器去加载,同时可以在jvm内存中存在多个不同版本的Class对象,这些对象是不兼容的。
并且是不能相互转换的。
什么是全盘委托加载?
解释:假如我们的Person类是由我们的系统类APP类加载器加载的,而person类所依赖的Dog类也会委托给App系统类进 行加载,这个委托过程也遵循双亲委派模型。代码如下
- person类代码中创建Dog实例
public class Person {
public Person(){
new Dog();
}
}
public class Dog {
public Dog(){
System.out.println("Dog 的构造函数");
}
}
· 测试类
· public class MainClass02 {
·
· public static void main(String[] args) throws Exception {
· //创建自定义类加载器的一个实例,并且通过构造器指定名称
· Test01ClassLoader myClassLoader = new Test01ClassLoader("loader1");
· myClassLoader.setPath("I:\test\");
· Class<?> classz = myClassLoader.loadClass("com.test.Person");
· System.out.println(classz.getClassLoader());
· System.out.println(Dog.class.getClassLoader());
· }
· }
·
·
· 运行结果:
·
· sun.misc.Launcher$AppClassLoader@18b4aac2
· sun.misc.Launcher$AppClassLoader@18b4aac2
·
· Process finished with exit code 0
从上面的运行结果,我们可以看出,当我们用自定义类加载器去加载我们的Person的时候,根据双亲委托模型,我们的Person并没有被自定义类加载(Test01ClassLoader)加载,而是被AppClassloader加载成功,同时根据全盘委托规则,我们的Dog类也被AppClassLoader加载了。所以大家一定要记住这个至关重要的结论。为我们后面的学习打下坚实的基础。
下面我们在看一个例子。我们把类路径下的Person.class文件删除掉,然后再运行一下上面的main函数,看看结果。代码如下:
通过那行结果我们看出,Person类是由我们的自定义类加载器加载的。那为什么Dog类没有进行全盘委托的,这是因为双亲委托模型的缘故,我们的类路径下并没有Person类,故此AppClassLoader是无法加载我们的路径I:\test\下的com.test.Person.class文件的。所以Person类是由我们自定的类加载器加载的。再看Dog类,由于它的加载要遵循双亲委托模型,因为类路径下有Dog.class文件,所以AppClassLoader就可以加载Dog类。故此加载Dog类的ClassLoader是AppClassLoader。写到这里,大家对类加载已经有了一个非常深刻的理解。那么java为什么使用双亲委托模型的好处我相信已经不言而喻了。那么下面来说说双亲委托模型,有没有他的弊端呢,或者说有什么不好的地方嘛?我们可以打破这种双亲委托的方式去加载类嘛?下面我们来看一个例子。
类加载器的命名空间
说到双亲委托模型的弊端,那我就离不开命名空间的概念。
类加载器的命名空间 是由类加载器本身以及所有父加载器所加载出来的binary name(full class name)组成.
①:在同一个命名空间里,不允许出现二个完全一样的binary name。
②:在不同的命名空间种,可以出现二个相同的binary name。当时二者对应的Class对象是相互不能感知到的,也就是说Class对象的类型是不一样的。
解释:同一个Person.class文件 被我们的不同的类加载器去加载,那么我们的jvm内存中会生成二个对应的Person的Class对象,而且这二个对应的Class对象是相互不可见的(通过Class对象反射创建的实例对象相互是不能够兼容的不能相互转型**
③:子加载器的命名空间中的binary name对应的类中可以访问 父加载器命名空间中binary name对应的类,反之不行
下面准备了一张图,以便于大家的理解。
上面这张图就很好的解释了命名空间的概念。大家可以再好好的体会一下。
我们光画图,光用嘴说并不是一种很有力的证据,就如同我写在这篇博文的时候所提,我们在学习和掌握某个概念的时候,就必须要拿出有力的证据,来证明自己的猜想或者是观点,那我们就举一个例子。来验证一下我们上面的理论是否正确。代码如下:
这是Person类的代码。
package com.test;
public class Person {
public Person() {
new Dog();
System.out.println("Dog的classLoader:-->"+ Dog.class.getClassLoader());
}
static{
System.out.println("person类被初始化了");
}
}
这是Dog类的代码。
package com.test;
public class Dog {
public Dog(){
System.out.println("Dog 的构造函数");
}
}
具体的验证思路是这样的,首先我们把Person类的Class文件放到启动类加载器的加载目录下(C:Program FilesJavajdk1.8.0_144jreclasses 这是启动类加载器的加载目录)来达到Person类交给启动类加载器加载的目的。
然后呢,我们让Dog类去被AppClassLoader(系统类加载器去加载)。然后我们在Person类中去访问Dog类。看看能否访问成功。
测试环境:把我们的Person.class放置在C:Program FilesJavajdk1.8.0_131jreclasses这个目录下,那么我们的Person.class就会被我们的启动类加载器加载,而我们的Dog类是被AppClassLoader进行加载,我们的Person类 中引用我们的Dog类会抛出异常.
创建main方法进行测试:
package com.test;
import java.lang.reflect.Method;
/**
* jvm 类加载器 第一章
* @author 奇客时间-时光
* 自定义类加载器——命名空间
* 测试父加载所加载的类,不能访问子加载器所加载的类。
*/
public class MainClass02 {
public static void main(String[] args) throws Exception {
System.out.println("Person的类加载器:"+Person.class.getClassLoader());
System.out.println("Dog的类加载器:"+Dog.class.getClassLoader());
Class<?> clazz = Person.class;
clazz.newInstance();
}
}
运行结果:
"C:Program FilesJavajdk1.8.0_144binjava.exe" "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2019.2libidea_rt.jar=59226:C:Program FilesJetBrainsIntelliJ IDEA 2019.2bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_144jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_144jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_144jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_144jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_144jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_144jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_144jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_144jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_144jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_144jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_144jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_144jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_144jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_144jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_144jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_144jrelibjce.jar;C:Program FilesJavajdk1.8.0_144jrelibjfr.jar;C:Program FilesJavajdk1.8.0_144jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_144jrelibjsse.jar;C:Program FilesJavajdk1.8.0_144jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_144jrelibplugin.jar;C:Program FilesJavajdk1.8.0_144jrelibresources.jar;C:Program FilesJavajdk1.8.0_144jrelibrt.jar;I:jvmoutproductionjvm-classloader" com.test.MainClass02
Person的类加载器:null
Dog的类加载器:sun.misc.Launcher$AppClassLoader@18b4aac2
person类被初始化了
Exception in thread "main" java.lang.NoClassDefFoundError: com/test/Dog
at com.test.Person.<init>(Person.java:7)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at com.test.MainClass02.main(MainClass02.java:20)
Process finished with exit code 1
总结:通过上面的代码我们就可以看出来,我们在Person中去new一个Dog的实例的时候,并没有创建成功,而是抛出了Exception in thread "main" java.lang.NoClassDefFoundError: com/test/Dog这样的异常,这也就证明了,我们上面所说的结论(父加载器所加载的类,不能访问子加载所加载的类。)
即启动类加载器所加载的类,不能访问系统类加载器所加载的类(AppClassLoader)。
那么肯定会有人问,我们的子加载器所加载的类,可以访问父加载器所加载的类嘛?我们不妨来证实一下,我们只需要改动一下MainClass02这个类的代码即可,让AppClassLoader去加载Dog类,让我们的自定义类加载器去加载我们的Person类。并在Person类中去访问Dog类。然后将之前C:Program FilesJavajdk1.8.0_131jreclasses目录下的Person中的Class文件删除掉,另外还有把我们类路径下的Person文件删除掉,并且在I:test目录下添加com.test.Person.class文件。代码如下:
package com.test;
import java.lang.reflect.Method;
/**
* jvm 类加载器 第一章
* @author 奇客时间-时光
* 自定义类加载器
* 测试子类加载器所加载的类,能否访问父加载器所加载的类。
*/
public class MainClass02 {
public static void main(String[] args) throws Exception {
//创建自定义类加载器的一个实例,并且通过构造器指定名称
Test01ClassLoader myClassLoader = new Test01ClassLoader("loader1");
myClassLoader.setPath("I:\test\");
Class<?> classz = myClassLoader.loadClass("com.test.Person");
System.out.println(classz.getClassLoader());
System.out.println("Dog的类加载器:"+Dog.class.getClassLoader());
classz.newInstance();
}
}
运行结果:
"C:Program FilesJavajdk1.8.0_144binjava.exe" "-javaagent:C:Program FilesJetBrainsIntelliJ IDEA 2019.2libidea_rt.jar=60588:C:Program FilesJetBrainsIntelliJ IDEA 2019.2bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_144jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_144jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_144jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_144jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_144jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_144jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_144jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_144jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_144jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_144jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_144jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_144jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_144jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_144jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_144jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_144jrelibjce.jar;C:Program FilesJavajdk1.8.0_144jrelibjfr.jar;C:Program FilesJavajdk1.8.0_144jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_144jrelibjsse.jar;C:Program FilesJavajdk1.8.0_144jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_144jrelibplugin.jar;C:Program FilesJavajdk1.8.0_144jrelibresources.jar;C:Program FilesJavajdk1.8.0_144jrelibrt.jar;I:jvmoutproductionjvm-classloader" com.test.MainClass02
自己的类加载器被加载了
com.test.Test01ClassLoader@677327b6
Dog的类加载器:sun.misc.Launcher$AppClassLoader@18b4aac2
Dog 的构造函数
Process finished with exit code 0
从上面的结果可以看出,Person是由我们的Test01ClassLoader自定义类加载器所加载的,那么它的父亲加载器是AppClassLoader,显然Dog类是由我们的AppClassLoader所加载的。故此代码正常运行,没有抛出异常,从而得出结论:
1:父加载器所加载的类,不能访问子加载器所加载的类。
2:子加载器所加载的类,可以访问父加载器所加载的类。
双亲委托模型的弊端
· 我们先看一段我们非常熟悉的数据库连接相关的代码片段。
· Class.forName("com.mysql.jdbc.Driver");
· Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/RUNOOB","root","123456");
· Statement stmt = conn.createStatement();
案例分析
- 在上述图中的第五步为什么会用线程上下文加载器进行加载呢?
- 在双亲委托模型的机制下,类的加载是由下而上的。即下层的加载器会委托上层进行加载。有些接口是Java核心库(rt.jar)提供的例如上面的createStatement接口,而Java核心库是由启动类加载器进行加载的。而这些接口的具体实现是来自不同的厂商(Mysql)。而具体的实现都是通过依赖jar包放到我们项目中的classPath下的。Java的启动类加载器/根类加载器是不会加载这些其他来源的jar包。
- 我们都知道classPath下的jar包是由我们系统类加载器/应用加载器进行加载,根据我们双亲委托的机制父类加载器是看不到子类(系统类加载器)所加载的具体实现。createStatement 这个接口是由根类加载器进行加载的 而具体的实现又加载不了。在双亲委托的机制下,createStatement这个接口就无具体的实现。
- 我们Java的开发者就通过给当前线程池设置上下文加载器的机制,就可以由设置的上下文加载器来实现对于接口实现类的加载。换句话说父类加载器可以使用当前线程上下文加载器加载父类加载器加载不了的一些接口的实现。完美了解决了由于SPI模型(接口定义在核心库中,而实现由各自的厂商以jar的形式依赖到我们项目中)的接口调用。
下面我提供了一张SPI的流程图。不知道什么是SPI的小伙伴儿,可以看一下这张图:
从上面的例子,我们可以看出,双亲委托模型的弊端。然后我们的jdk给我们提供了一种通过修改线程上下文类加载的方式来打破这种双亲委托的规则。关于修改上下文类加载的话题,我们下个章节再具体的讲解。接下来呢,我们再看看,获取类加载器的几个方法。并且奉上翻译好的java doc文档。方便我们后续学习线程类加载器。
获取类加载器的几个方法
- Class.getClassLoader()
/**
* Returns the class loader for the class(返回加载该类的类加载器). Some implementations may use
* null to represent the bootstrap class loader(有一些jvm的实现可能用null来表示我们的启动类加载器比如 hotspot).
* This method will return null in such implementations if this class was loaded by the bootstrap class loader.
* 若这个方法返回null的话,那么这个类是由我们的启动类加载器加载
*
* If this object represents a primitive type or void, null is returned.
(原始类型 比如int,long等等的类或者 void类型 那么他们的类加载器是null)
*
*
*/
public ClassLoader getClassLoader() {
ClassLoader cl = getClassLoader0();
if (cl == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
}
return cl;
}
· 1:返回代表加载该class的类加载器
· 2:有一些虚拟机(比如hotspot) 的启动类加载器是null来表示
· 3:原始类型 比如int ,long 或者是void类型 ,他们的类加载器是null
· ClassLoader.getSystemClassLoader()方法解读
/**
* Returns the system class loader for delegation(该方法返回系统类加载器). This is the default
* delegation parent for new ClassLoader instances(也是我们自己定义的类加载器的委托父类), and is
* typically the class loader used to start the application(通常系统类加载器是用来启动我们的应用的)
*
* This method is first invoked early in the runtime's startup
* sequence(程序在运行早起就会调用该方法), at which point it creates the system class loader and sets it
* as the context class loader of the invoking <tt>Thread</tt>.(在那个时间,调用线程创建我们的系统类加载器同时把系统类加载器设置到我们线程上下文中)
*
* <p> The default system class loader is an implementation-dependent
* instance of this class.(这句话没有很好的理解)
*
* <p> If the system property "<tt>java.system.class.loader</tt>" is defined
* when this method is first invoked then the value of that property is
* taken to be the name of a class that will be returned as the system
* class loader. The class is loaded using the default system class loader
* and must define a public constructor that takes a single parameter of
* type <tt>ClassLoader</tt> which is used as the delegation parent. An
* instance is then created using this constructor with the default system
* class loader as the parameter. The resulting class loader is defined
* to be the system class loader.
我们可以通过java.system.class.loader 系统属性来指定一个自定义的类加载的二进制名称作为新的系统类加载器,
在我们自定的加载中我们需要定义个带参数的构造函数,参数为classLoader,那么我们这个自定义的类加载器就会看做系统类加载器
*
* @return The system <tt>ClassLoader</tt> for delegation, or
* <tt>null</tt> if none
*
* @throws SecurityException
* If a security manager exists and its <tt>checkPermission</tt>
* method doesn't allow access to the system class loader.
*
* @throws IllegalStateException
* If invoked recursively during the construction of the class
* loader specified by the "<tt>java.system.class.loader</tt>"
* property.
*
* @throws Error
* If the system property "<tt>java.system.class.loader</tt>"
* is defined but the named class could not be loaded, the
* provider class does not define the required constructor, or an
* exception is thrown by that constructor when it is invoked. The
* underlying cause of the error can be retrieved via the
* {@link Throwable#getCause()} method.
*
* @revised 1.4
*/
@CallerSensitive
public static ClassLoader getSystemClassLoader() {
//初始化系统类加载器
initSystemClassLoader();
if (scl == null) {
return null;
}
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkClassLoaderPermission(scl, Reflection.getCallerClass());
}
return scl;
}
- 1:该方法的作用是返回系统类加载器
- 2:也是我们自定义加载器的直接父类
- 3:系统类加载器是用来启动我们的应用的
- 4:在系统早期,调用线程会创建出我们的系统类加载器,并且把我们的系统类加载器设置到当前线程的上下文中
相关推荐
- 三种自建KMS激活系统自动激活windows方法
-
第一种:在windows服务器上搭建主要针对vol版本(win7、win10、win20xx、win2012等等)平台:我自己搭建的windows虚拟机,windows2016的操作系统软件:...
- 重装系统被收98元?避开Windows付费陷阱的实用指南
-
重装系统被收98元?避开Windows付费陷阱的实用指南有网友反映,在重装Windows系统后,屏幕突然弹出“激活系统需支付98元服务费”的提示,疑惑自己是不是遭遇了付费陷阱。事实上,微软官方的Wi...
- Windows Server2012远程桌面服务配置和授权激活
-
安装:注意:安装完毕之后需手动重启一下计算机配置终端服务管理工具---远程桌面服务---RD授权诊断程序,查看当前服务器有没有授权授权:运行—>gpedit.msc->计算机配置---管理...
- 新书速览|Windows Server 2022 系统与网站配置实战
-
讲述桌面体验、ServerCore/NanoServer,容器与云系统的配置1本书内容《WindowsServer2022系统与网站配置实战》秉持作者一贯理论兼具实践的写作风格,以新版的Wi...
- Windows激活全攻略:KMS神钥与专业工具的完美结合!
-
对于许多Windows用户来说,系统的激活是一个必经的过程。虽然Windows操作系统在未经激活的状态下也可以使用一段时间,但长期来看,未激活的系统会限制某些功能并频繁提示用户激活。以下是两种流行的激...
- 微软Win9全新激活技术曝光(微软系统激活有什么用)
-
2014-07-0905:46:00作者:徐日俄罗斯Wzor日前披露了更多关于Windows9的最新消息,据悉,Windows9将会在今年秋季亮相,其宣传口号是“想要开始按钮和开始菜单?如你所...
- 快速激活Windows 10/11:CMD命令详细教程
-
#记录我的2024#激活Windows操作系统是确保系统功能和安全更新正常运行的重要步骤。本文将为您分享如何使用命令提示符(CMD)在Windows10和Windows11上进行激活的详细步骤。...
- Wndows 2019 RDS应用发布部署(rds的安装和应用程序的发布)
-
安装前的准备1、需要提供服务器作为应用中心,应用中心的推荐配置如下表所示。规格建议1-10人11-20人21-50人51-100人100+人CPU4核8核16核内存8GB16GB32GB64GB系统盘...
- 解决 Windows 系统激活难题(如何解决windows激活问题)
-
今天,一位朋友给我说,他手头有三台电脑,均同时弹出系统未激活的提示。他对此毫无头绪,便急忙将电脑上出现的激活提示信息一股脑发给了我。我看到其中一台显示的是“Windows10企业版LTSC尚...
- 自建KMS激活服务器(自建kms激活服务器的风险)
-
自建KMS激活服务器Win10和office安装后,都需要激活才可以使用,一般可以输入购买的MAK激活码进行在线激活,也可以通过KMS激活,网上也有很多激活工具,但这些工具一般都含有病毒或木马程序,容...
- 30秒免费激活windows和office亲测有效!
-
“第三方工具有病毒?”“KMS服务器激活总失效?”今天给大家分享一个开源激活工具——MicrosoftActivationScripts(MAS),无需密钥、不装软件,30秒永久激活Window...
- 「操作系统」Windows 10 LTSC 2019 企业版C大集成更新版
-
Windows10LTSC企业版CHIANNET集成更新优化整合多镜像版,CHIANNET,是USBOS超级PE维护盘工具箱作者,长久以来一直默默的更新着,USBOSPE软件,电脑城装机及...
- 一文看懂Windows激活:自查方法+授权类型科普(Win7/Win10通用)
-
一、如何判断Windows是否永久激活?无论是Win7还是Win10,均可通过以下方法快速验证:命令提示符法(通用):按下Win+R,输入slmgr.vbs/xpr并按回车键运行即可查看是否...
- 部分Windows Server 2019/2022用户反馈无法运行微软Teams应用
-
IT之家7月2日消息,科技媒体borncity今天(7月2日)发布博文,报道称在多个WindowsServer版本上,MicrosoftTeams应用近期出现了运行故障。用...
- 这种Windows激活方式已有20年...(windows现在激活)
-
2006年微软正式发布WindowsVista,随之而来引入了一项新的激活机制「OEM激活」,这项机制在Vista和Win7上最为流行。其实WindowsServer自2008开始至2025版本一...
你 发表评论:
欢迎- 一周热门
-
-
UOS服务器操作系统防火墙设置(uos20关闭防火墙)
-
极空间如何无损移机,新Z4 Pro又有哪些升级?极空间Z4 Pro深度体验
-
NAS:DS video/DS file/DS photo等群晖移动端APP远程访问的教程
-
如何在安装前及安装后修改黑群晖的Mac地址和Sn系列号
-
手机如何设置与显示准确时间的详细指南
-
如何修复用户配置文件服务在 WINDOWS 上登录失败的问题
-
一加手机与电脑互传文件的便捷方法FileDash
-
日本海上自卫队的军衔制度(日本海上自卫队的军衔制度是什么)
-
10个免费文件中转服务站,分享文件简单方便,你知道几个?
-
爱折腾的特斯拉车主必看!手把手教你TESLAMATE的备份和恢复
-
- 最近发表
-
- 三种自建KMS激活系统自动激活windows方法
- 重装系统被收98元?避开Windows付费陷阱的实用指南
- Windows Server2012远程桌面服务配置和授权激活
- 新书速览|Windows Server 2022 系统与网站配置实战
- Windows激活全攻略:KMS神钥与专业工具的完美结合!
- 微软Win9全新激活技术曝光(微软系统激活有什么用)
- 快速激活Windows 10/11:CMD命令详细教程
- Wndows 2019 RDS应用发布部署(rds的安装和应用程序的发布)
- 解决 Windows 系统激活难题(如何解决windows激活问题)
- 自建KMS激活服务器(自建kms激活服务器的风险)
- 标签列表
-
- linux 查询端口号 (58)
- docker映射容器目录到宿主机 (66)
- 杀端口 (60)
- yum更换阿里源 (62)
- internet explorer 增强的安全配置已启用 (65)
- linux自动挂载 (56)
- 禁用selinux (55)
- sysv-rc-conf (69)
- ubuntu防火墙状态查看 (64)
- windows server 2022激活密钥 (56)
- 无法与服务器建立安全连接是什么意思 (74)
- 443/80端口被占用怎么解决 (56)
- ping无法访问目标主机怎么解决 (58)
- fdatasync (59)
- 405 not allowed (56)
- 免备案虚拟主机zxhost (55)
- linux根据pid查看进程 (60)
- dhcp工具 (62)
- mysql 1045 (57)
- 宝塔远程工具 (56)
- ssh服务器拒绝了密码 请再试一次 (56)
- ubuntu卸载docker (56)
- linux查看nginx状态 (63)
- tomcat 乱码 (76)
- 2008r2激活序列号 (65)