当前位置:首页 » 编程语言 » javaclassloader

javaclassloader

发布时间: 2022-12-11 11:19:51

⑴ 五、ClassLoader双亲委派加载模式

获取启动类加载器加载的目录 System.getProperty("sun.boot.class.path");

获取扩展类加载器加载的目录 System.getProperty("java.ext.dirs");

获取应用类加载器加载的目录 System.getProperty("java.class.path");

将test.Test2.class移到启动类加载器加载的目录,然后其加载类

启动类加载器加载目录如下

通过上述案列可以分析出,test.Test2是由启动类加载器加载的,验证了双亲委派优先父加载器加载

通过上述案列得出AESKeyGenerator是由扩展类加载器加载的,手动修改扩展类加载器加载的目录,修改完成后在修改后的目录是找不到AESKeyGenerator,所以会报错

java -Djava.ext.dirs=./ test.Test19

将本地目录作为扩展类加载器加载的目录

同一个命名空间内的类时相互可见的

子加载器的命名空间包含所有的父加载器的命名空间。因此由子加载器加载的类可以看见父加载器加载的类。例如系统类加载器加载的类能看见跟类加载器加载的类。

由父加载器加载的类不能看见子加载器加载的类。

如果两个加载器之间没有直接或者间接的父子关系,那么它们各自加载的类相互不可见

上述案列是因为classLoader1与classLoader2的父加载器都为AppClassLoader,所以classLoader1加载完Person后在内存的缓存中是有Person.class的,classLoader2委托AppClassLoader加载的时候直接就从内存中获取Person.class,所以他们是一致的,method方法也是可以执行的

当删除当前classpath下的Person.class文件,将Person.class文件移到D盘下

此时当前的classPath下没有Person.class文件,会分别由classLoader1加载器与classLoader2加载器加载,会存在classLoader1加载器的命名空间以及classLoader2加载器的命名空间,根据  如果两个加载器之间没有直接或者间接的父子关系,那么它们各自加载的类相互不可见 的规则那么classLoader1与classLoader2加载的类时相互不可见的也是不相同的,这里会有很有趣的问题  java.lang.ClassCastException: test.Person cannot be cast to test.Person

修改扩展类加载路劲为当前路径

执行 java -Djava.ext.dirs=./ test.Test22

可以发现还是使用AppClassLoader加载的Test22以及Test1

扩展类加载器不能直接加载.class文件,需要将.class文件打成jar包

jar cvf test.jar test/Test1.class

再次执行 ,可以发现Test1是通过扩展类加载器加载的,因为此处只将Test1打成jar包了

1. 可以确保java核心库的类型安全: 例如所有的JAVA应用都至少会引用java.lang.Object类,也就是说在jvm的运行期间,java.lang.Object类会被加载到java虚拟机中,如果这个过程是由自己定义的java类加载器完成的,那么很有可能在jvm中存在多个版本的java.lang.Object类,也就是说在jvm的运行期间而这些类之间是相互不兼容的(命名空间不同导致的)。

借助双亲委派机制,java核心类库的加载必须由启动类加载器加载,从而确保java中使用的核心类库的版本统一,他们之间是相互兼容的

2. 可以保证java核心类库加载的类不会被自定义类所替代。

3. 不同类的加载器可以为相同名称的类(binary name)创建额外的命名空间。相同名称的类可以并存与不同命名空间的内存中,不同类加载器加载的类之间是相互不兼容的就相当于在java虚拟机内部创建了一个又一个相互独立并且隔离的的java空间,这类技术在很多框架都得到了使用。

在运行期间,一个Java类是由该类的完全限定名(binary name,二进制名)和用于加载该类的定义类加载器(defining loader)所共同决定的。如果同样名字(即相同的限定名)的类是由两个不同的加载类所加载,那么这些类就是不同的,即便.class文件的字节码完全一样,并且从相同的位置加载也是如此。

在Oracle的Hotspot实现中,系统属性 sun.boot.class.path如果被修改错了,则运行会出错,提示如下错误信息:

Error occureed ring initialization of VM

java/lang/NoClassDefFoundError: java/lang/Object

内建于JVM中的启动类加载器会加载java.lang.ClassLoader以及其他的java平台类,当JVM启动时,一块特殊的机器码会运行,它会加载扩展类加载器以及系统类加载器,这块特殊的机器码叫做启动类加载器(BootStrap)。启动类加载器并不是java类,而其他的加载器都是java类,启动类加载器是特定于平台的机器指令,它负责开启整个加载过程

所有类加载器(除了启动类加载器)都被实现为Java类。不过总归要有一个组件来加载第一个java类加载器,从而让整个加载过程能够顺利进行,加载第一个纯JAVA类加载器就是启动类加载器的职责。

启动类加载器还会负责加载JRE正常运行时所需的基本组件,这包括java.util与java.lang包中的类等等

java -Djava.system.class.loader=test.Test16 test.Test23

⑵ java classloader怎么使用

Java是一种介于解释与编绎之间的语言,
Java代码首先编绎成字节码,
在运行的时候再翻译成机器码。
这样在运行的时候我们就可以通过Java提供的反射方法(reflect)来得到一个Object的Class的额外信息,
灵活性很大,可以简化很多操作。
Class:
任何一个Object都能通过getClass()这个方法得到它在运行期间的Class。
得到这个Class之后可做的事情就多了,
比如动态得到它的构造函数,
成员变量,
方法等等。
还可以再生成一份新的实例,
下面只给出几个我们常用的方法,
更详细的用法参照Java
API
Ø
Class
Class.forName(String
className)
throws
ClassNotFoundException:
这是个静态方法,
通过一个Class的全称来得到这个Class。
Ø
String
getName()
取得这个Class的全称,
包括package名。
Ø
Object
newInstance()
得到一个实例,
调用缺省的构造函数。
例如我们有一个类:
com.some.util.MyClass
如果得到它的一个实例呢?
可能有以下两种方法:
MyClass
myClass
=
new
MyClass(),
直接通过操作符new生成;
或者:
MyClass
myClass
=
(MyClass)
Class.forName(“com.some.util.MyClass”).newInstance();
也许有人就会怀疑第二种方法实际意义,
能够直接new出来干嘛绕弯。
但实际上它的用处却很大,
举个例子:
用过struts的人都知道,
在action-config.xml当中定义了一系列的formBean与actionBean,
当然每个form与action都具有同类型,
这样在一个request过来的时候我可以动态的生成一个form与action的实例进行具体的操作,
但在编码的时候我并不知道具体是何种的form与action,
我只调用它们父类的方法。
你如果要用第一种方法的话,
你得在编码的时候通过一个标志来判断每一次request需要具体生成的form与action,
代码的灵活性大大降低。
总的来说在面向接口的编程当中经常使用这种方法,
比如不同数据库厂家的JDBC
Driver都是从标准的JDBC接口继承下去的,
我们在写程序的时候用不着管最终是何种的Driver,
只有在运行的时候确定。
还有XML的Parser也是,
我们使用的只是标准的接口,
最后到底是谁来实现它的,
我们用不着去管。
ClassLoader:
ClassLoader是一个抽象类,一般的系统有一个缺省的ClassLoader用来装载Class,
用ClassLoader.getSystemClassLoader()可以得到。不过有时候为了安全或有其它的特殊需要我们可以自定义自己的ClassLoader来进行loader一些我们需要的Class,
比如有的产品它用了自己的ClassLoader可以指定Class只从它指定的特定的JAR文件里面来loader,如果你想通过覆盖ClassPath方法来想让它用你的Class是行不通的。
有兴趣的可以参照Java
API
的更详细的用法说

⑶ java 每个类都有一个 classloader

不是这样的,通常只会有一个.

Java虚拟机启动时会调用系统类加载器BootstrapClassLoader去加载ExtClassLoader和ApplicationClassLoader.

ExtClassLoader:自定义的类加载器.

ApplicationClassLoader:当你用的某个类时会通过它进行加载,当然你也可以通过代码用自定义的类加载器进行class的加载.

加载是指将类加载到java虚拟机中.


看下上面的图片会发现class是Data1类中的一个静态域,这说明在Data1类的多个实例中只有一个class对象,一个对象怎么会返回多个classloader呢。classloader实在class加载到虚拟机时赋上去的.

⑷ java classloader 怎么加载jar包

设我们有一个hello.jar文件,里面有一个Util类,我们希望在运行期调将这个jar包放入到我们运行环境并且调用里面的Util.getVersion方法。怎么实现?
在java中,我们的类都是通过ClassLoader来加载的,同时ClassLoader具有层级关系,当某个类找不到时,它会去他的父类加载器去寻找,如果依然找不到,就抛出ClassNotFoundException了。
为了动态加载hello.jar里面的Util类,我们需要将这个jar包放入到我们的类加载器中去,然后再获取里面的类。如下面的代码。

// 位于hello.jar
package com.flyingzl;

public class Util {

public static void getVersion(){

System.out.println("java version: " + System.getProperty("java.version"));
}

}

⑸ Java的ClassLoader对象如何关闭

URLClassLoader loader =new URLClassLoader(new URL[] { new URL("file:" + jarRoute) });
loader.close();

⑹ 怎么 classloader 加载一个java源文件

1.类加载器深入剖析
Java虚拟机与程序的生命周期 :
当我们执行一个java程序的时候 , 会启动一个JVM进程 , 当程序执行完之后 , JVM进程就消亡了 ;
在如下情况下JVM将结束声明周期 :
System.exit(int)方法 , 当执行这个方法的时候 , 虚拟机会退出 ; 这个方法传入一个整形参数 , 这个参数是状态吗 : 如果这个整形是 0 的话 , 就是正常退出 , 如果不是0的话 , 就是异常退出 ;
程序正常结束 ;
程序执行过程中 , 遇到了异常或错误 , 而异常终止 : 如果我们在程序中出现了异常 , 而不去处理 , 会将异常一直抛给main函数 , main函数会将异常抛给JVM , JVM如果处理不了异常 , JVM就会异常退出 ;
由于操作系统出现错误导致JVM进程终止 : JVM所依赖的平台出现错误 , 导致JVM终止 ;

2.类的加载,连接和初始化
加载 : 查找并加载类的二进制数据 , 将class字节码文件加载到内存中 ;
连接 :

-
验证
: 确保被加载的类的正确性 , 使用javac 编译工具生成的字节码文件能通过验证 , 如果不是由javac编译生成的字节码文件 , 如果自己生成的字节码文件不符合JVM虚拟机对字节码文件的要求的话 , 可能会出现验证通不过的情况 ; 比如说随便拿一个文件 , 将后缀名直接修改为.class , 这样的字节码文件肯定不合法 ;

-
准备
: 为类的静态变量分配内存 , 并将其初始化为默认值 ;

-
解析
: 把类中的符号引用转为直接引用 ;
初始化 : 为类的静态变量赋予正确的初始值(正确的值指的是用户赋的值) ;
-好像这个与连接阶段的准备有些重复 , 在连接的准备阶段只是赋予初始变量 , 如果用户给这个变量赋了初始值 , 那么这个变量在连接的准备阶段仍然会赋予初始值 ;

-在这个阶段 , 才会真正的将初始值赋给静态变量 ;

Java程序对类的使用方式有 主动使用 和 被动使用 ;
所有的JVM实现 , 必须在每个类或者接口 , 被java程序 “首次主动使用” 时才初始化他们 ;
主动使用 :
创建类的实例 ;
访问某个类或接口的静态变量 , 或者对该静态变量赋值 ;
调用类的静态方法 ;
反射 : Class.forName(“类名”) ;
初始化一个类的子类 , 看做对父类的主动使用 ;
java虚拟机启动的时候 , 被标明启动类的类 , 即包含main方法的类 , 程序的入口 ;

除了上面6种主动使用之外 , 其它的情况均为被动使用 , 其它情况都不会执行第三步初始化 ;

3.类的加载
(1)概念

类的加载 : 指的是将类的.class文件中的二进制数据读入到内存中 , 将其放在运行时数据区的方法区内 , 然后再堆区创建一个java.lang.Class对象 , 用来封装类在方法区内的数据结构 ;
反射 : 反射就是跟句堆区的字节码文件 , 获取方法去的数据结构 ;
解析 : Class对象是由JVM自己创建的 , 所有的对象都是经过Class对象创建 , 这个Class对象是反射的入口, 通过Class对象 , 可以关联到目标class字节码文件的内部结构 ;

所有的类对应的Class对象都是唯一的一个 , 这个类是由JVM进行创建的 , 并且只有JVM才会创建Class对象 ;

类加载的最终产品是位于堆区中的Class对象 , Class对象封装了类在方法区内的数据结构 , 并且向Java程序员提供了访问方法区内的数据结构的接口(反射用的接口) ;

(2)加载.class文件的方式
从本地系统中直接加载 : 编译好的.class字节码文件直接从硬盘中加载 ;
通过网络下载.class文件 : 将class字节码文件放在网络空间中 , 使用URLClassLoader来加载在网络上的.class字节码文件 , 使用默认的父亲委托机制加载字节码文件 ;
从zip , jar 等压缩文件中加载字节码文件 : 在开发的时候 , 导入jar包 , 就是这种方式 ;
从专有的数据库中提取字节码文件 ;
将java源文件动态编译为字节码文件 ;

(3)类加载器
l Java虚拟机自带的类加载器 :
-根类加载器 ( Bootstrap ) : 是C++写的 , 程序员无法再java代码中获取这个类 , 如果使用getClassLoader()方法获取到的是一个null值 ;
package jvm;
Java代码
public class ClassLoaderTest {
public static void main(String[] args) throws Exception {
//java.lang包下的类使用的是跟类加载器进行加载的
Class clazz = Class.forName("java.lang.String");
System.out.println(clazz.getClassLoader());
//自定义的类使用的是应用类加载器(系统加载器)
Class clazz2 = Class.forName("jvm.C");
System.out.println(clazz2.getClassLoader());
}
}
class C{}
执行结果 :
null
Java代码
sun.misc.Launcher$AppClassLoader@1372a1a
-扩展类加载器 ( Extension ) : Java编写 ;
-系统类加载器(应用加载器) ( System ) : Java编写 ;

用户自定义的类加载器 :
-自定义的类加载器都是java.lang.ClassLoader子类 ;
-用户可以定制类的加载方式

String类是由根类加载器进行加载的 , 我们可以调用Class对象的

关于代理中创建对象的类加载器 : 创建代理对象的时候 , 动态创建一个类 , 然后使用指定的类加载器将这个类加载到内存中 , 然后用加载到内存中的类生成代理对象 ;
创建代理对象的方法 : newProxyInstance(ClassLoader loader , Class [] Interfaces , InvocationHandler h )
loader 是定义的代理类的类加载器 , 中间的接口数组是代理类的要实现的接口列表 , h 是指派方法调用的调用处理程序 ;

类加载器并不需要在某个类被 “首次主动使用” 时再加载它 :
-预加载机制 : JVM规范允许类加载器在预料某个类将要被使用的时就预先加载它 ;
-报错时机 : 如果在预加载的过程中遇到了字节码文件缺失或者存在错误的情况 , 类加载器会在程序首次主动使用(上面提到的六种情况)该类的时候报错(LinkageError错误) ;
-不报错时机 : 如果这个错误的字节码文件所对应的类一直没有被使用 , 那么类加载器就不会报告错误 ,即便有错误也不会报错 ;

LinkageError : 这个错误是Error的子类 , 程序不能处理这些错误 , 这些错误都是由虚拟机来处理 , 这个错误表示出错的是子类 , 在一定程序上依赖于另一个类 , 在编译了前面一个类的时候 , 与后面所依赖的类出现了不兼容的情况 ;
例如 : 我们使用了jdk 1.6 在编译一个程序 , 但是运行环境是jre1.5的 , 就会出现LinkageError错误 ;
4.类的连接
(1)定义
类被加载之后 , 就进入链接阶段 ; 链接 : 将已读入内存的二进制数据合并到虚拟机的运行时环境中去 ;
链接顾名思义就是讲类与类之间进行关联 , 例如我们在类A中调用了类B , 在链接过程中 , 就将A与B进行链接 ,将面向对象语言转化为面向过程语言 ;

(2)类的验证
类文件的结构检查 : 确保类文件遵从java类文件的固定格式 , 开始类的描述 , 声明 , 方法调用格式等 ;
语义检查 : 确保类本身符合java语言的语法规定 , 比如final类型的类没有子类 , final类型的方法没有被覆盖 ,在eclipse中这种错误编译的时候不能通过 , 但是通过其他的方法可以生成错误的字节码文件 , 这里就是检测恶意生成的字节码文件 ;
字节码验证 : 确保字节码流可以被JVM安全的执行 , 字节码流代表java方法(包括静态方法和实例方法) , 它是由被称作操作码的单字节指令组成的序列 , 每一个操作码后面跟着一个或多个操作数 , 字节码验证步骤会检查每个操作码是否合法 , 即是否有着合法的操作数 ;
下面是指令码组成的序列 , 类似于微指令 :

Jvm编译指令代码代码
// Compiled from ByteToCharCp1122.java (version 1.5 : 49.0, super bit)
public class sun.io.ByteToCharCp1122 extends sun.io.ByteToCharSingleByte {

// Field descriptor #17 Lsun/nio/cs/ext/IBM1122;
private static final sun.nio.cs.ext.IBM1122 nioCoder;

// Method descriptor #18 ()Ljava/lang/String;
// Stack: 1, Locals: 1
public java.lang.String getCharacterEncoding();
0 ldc <String "Cp1122"> [1]
2 areturn
Line numbers:
[pc: 0, line: 25]

// Method descriptor #2 ()V
// Stack: 2, Locals: 1
public ByteToCharCp1122();
0 aload_0 [this]
1 invokespecial sun.io.ByteToCharSingleByte() [25]
4 aload_0 [this]
5 getstatic sun.io.ByteToCharCp1122.nioCoder : sun.nio.cs.ext.IBM1122 [23]
8 invokevirtual sun.nio.cs.ext.IBM1122.getDecoderSingleByteMappings() : java.lang.String [27]
11 putfield sun.io.ByteToCharSingleByte.byteToCharTable : java.lang.String [24]
14 return
Line numbers:
[pc: 0, line: 28]
[pc: 4, line: 29]
[pc: 14, line: 30]

// Method descriptor #2 ()V
// Stack: 2, Locals: 0
static {};
0 new sun.nio.cs.ext.IBM1122 [15]
3 p
4 invokespecial sun.nio.cs.ext.IBM1122() [26]
7 putstatic sun.io.ByteToCharCp1122.nioCoder : sun.nio.cs.ext.IBM1122 [23]
10 return
Line numbers:
[pc: 0, line: 22]
}
l 二进制兼容性的验证 : 确保相互引用的类之间协调一致的 ; 例如在A类的a()方法中调用B类的b()方法 , JVM在验证A类的时候 , 会验证B类的b()方法 , 加入b()方法不存在 , 或者版本不兼容(A,B两类使用不同的JDK版本编译) , 会抛出NoSuchMethodError错误 ;

(3)准备阶段
在准备阶段 , JVM为类的静态变量分配内存空间 , 并设置默认的初始值 . 例如下面的Sample类 , 在准备阶段 ,为int类型的静态变量分配4个字节 , 并赋予初始值 0 ; 为long 类型的静态变量 b , 分配8个字节 , 并赋予初始值 0 ;
PS : 在java中基本类型变量占用的空间是一定的 , java运行在JVM上的 , 在C中 , 就要根据平台变化而变化了 ;

public class Sample {
Java代码
private static int a = 1 ;
private static long b ;
static {
b = 2 ;
}
(4)类的解析
在解析阶段 , JVM 会把类的二进制数据中的符号引用替换为直接引用 , 例如在A类中的a()方法引用B类中的b()方法 ;
在A类的二进制数据中包含了一个对B类的b()方法的符号引用 , 这个符号引用由b()方法的全名和相关的描述符组成 , 在Java解析阶段 , 就会把这个符号引用替换为指针 , 这个指针就是C语言中的指针了 , 该指针指向B类的b()方法在方法区中的内存位置 , 这个指针就是直接引用 ;

5.类的初始化
在初始化阶段 , Java虚拟机执行类的初始化操作 , 为类的静态变量赋予初始值 , 在程序中 , 静态变量初始化有两种途径 :
直接在声明处进行初始化 , 例如下面的Sample中的 变量a ;
在静态代码块中进行初始化 , 例如下面的Sample中的变量b ;

Java代码
public class Sample {
private static int a = 1 ;
private static long b ;
static {
b = 2 ;
}
}

6.面试题介绍

Java代码
public class PrepareOrInit {
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
System.out.println(singleton.count1);
System.out.println(singleton.count2);
}
}
class Singleton{
private static Singleton singleton = new Singleton() ;
public static int count1 ;
public static int count2 = 0 ;
private Singleton(){
count1 ++ ;
count2 ++ ;
}
public static Singleton getInstance(){
return singleton ;
}
}
执行结果 : 1 0

分析 : 这段代码与类的链接中的准备阶段 和 初始化阶段 有关系 , 准备阶段是给静态的字段赋予默认值 , 初始化阶段给静态变量赋予正确的值 , 即用户的值 ;
在主函数中 , 调用了类的静态方法 , 相当于主动使用 , 这里调用了类的静态方法 ;
之后进行连接的准备操作 , 给类中的静态变量赋予初值 , singleton值为null , count1 与 count2 值为0 ;
执行初始化操作 , 给类中的静态变量赋予正确的值 , 给singleton变量赋予正确的值 , 调用构造方法 , 此时count1与 count2执行自增操作 , 两者都变成1 , 然后执行count1的赋予正确值操作 , 这里用户没有赋值操作 , count2 用户进行了 赋值为0的操作 , 0将原来的1覆盖掉了 , 因此结果为 1 , 0 ;

Java代码
public class PrepareOrInit {
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
System.out.println(singleton.count1);
System.out.println(singleton.count2);
}
}
class Singleton{
public static int count1 ;
public static int count2 = 0 ;
private static Singleton singleton = new Singleton() ;
private Singleton(){
count1 ++ ;
count2 ++ ;
}
public static Singleton getInstance(){
return singleton ;
}
}
执行结果 : 1 1

在准备阶段count1 和 count2 都赋值为0 , 然后在初始化阶段 , 全部赋值为1 ;

⑺ java classloader 加载哪些类

BootStrap ClassLoader:称为启动类加载器,是Java类加载层次中最顶层的类加载器,负责加载JDK中的核心类库,如:rt.jar、resources.jar、charsets.jar等
Extension ClassLoader:称为扩展类加载器,负责加载Java的扩展类库,默认加载JAVA_HOME/jre/lib/ext/目下的所有jar
App ClassLoader:称为系统类加载器,负责加载应用程序classpath目录下的所有jar和class文件

⑻ Java:如何编写自己的Java类加载器

给你简单介绍一下类加载器

1.类加载器就加载字节码文件(.class)

public class FileClassLoader extends ClassLoader {String rootDir=null;public FileClassLoader(String rootDir) {this.rootDir = rootDir;}@Overrideprotected Class<?> findClass(String className) throws ClassNotFoundException {//首先检查是否已经被加载了。Class<?> c = findLoadedClass(className);String path = rootDir + "/" + className.replace('.', '/') + ".class";if (c != null) {return c;} else {/*双亲委托模式*/ClassLoader loaderParent = this.getParent();c = loaderParent.loadClass(className);if (c != null) {return c;} else {/*如果再不行的话,就再进行加载。因为字节码的本质就是一个字节数组*/InputStream is = null;ByteArrayOutputStream outputStream = new ByteArrayOutputStream();try {is = new FileInputStream(path);byte[] buffer = new byte[1024];int len = 0;while ((len = is.read(buffer)) != -1) {outputStream.write(buffer, 0, len);}c = defineClass(className, buffer, 0, buffer.length);}catch (Exception e) {e.printStackTrace();}finally {if (is != null) {try {is.close();}catch (IOException e) {e.printStackTrace();}}}}return c;}}

}

/*

相同的类加载器对同一个类进行加载,得到的hascode是相同的

* 不同的类加载器对同一类进行加载,得到的hascode是不一样的*/public class Demo {public static void main(String[] args) {FileClassLoader loader = new FileClassLoader("c://myjava");FileClassLoader loader2=new FileClassLoader("c://myjava");try {Class<?> c = loader.findClass("com.lg.test.HelloWorld");Class<?> c0=loader.findClass("com.lg.test.HelloWorld");Class<?> c1=loader2.findClass("com.lg.test.HelloWorld");Class<?> c2=loader.findClass("com.lg.test.Demo01");Class<?> c3=loader.findClass("java.lang.String");System.out.println(c.hashCode());System.out.println(c.getClassLoader());System.out.println(c0.hashCode());System.out.println(c0.getClassLoader());System.out.println(c1.hashCode());System.out.println(c1.getClassLoader());System.out.println(c2.hashCode());System.out.println(c2.getClassLoader());System.out.println(c3.hashCode());System.out.println(c3.getClassLoader());}catch (ClassNotFoundException e) {e.printStackTrace();}}}
热点内容
a星算法视频 发布:2025-01-22 07:55:01 浏览:878
快手安卓怎么直播 发布:2025-01-22 07:54:58 浏览:937
买服务器搭建vpn 发布:2025-01-22 07:53:21 浏览:808
路由器忘记密码如何解 发布:2025-01-22 07:38:47 浏览:153
5分钟视频编译 发布:2025-01-22 07:36:33 浏览:772
asp执行存储过程 发布:2025-01-22 07:35:55 浏览:126
镇政府搭建服务器 发布:2025-01-22 07:32:13 浏览:1001
安卓系统可以查去过哪里吗 发布:2025-01-22 07:25:05 浏览:27
三星手机怎么设置热点密码 发布:2025-01-22 07:20:11 浏览:38
Ip呼叫服务器 发布:2025-01-22 07:19:32 浏览:633