今台看了一点关于类加载器的东西,总结一下算作一个小复习吧,尽可能的每天学习一点知识点,积水成渊吧
首先我们如何看当一个类运行的时候相关的加载信息呢 在命令行下可以采用java -verbose:class 类名称 ,如果是在eclipse下(本人其实用的是myeclipse) 设置一下运行参数就可以。如下图

这样你就可以在运行的时候就可以看到相关类是如何加载的
我们运行一下
你会看到类似如下的信息,只是类似并不是雷同。
[Opened D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.lang.Object from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.io.Serializable from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.lang.Comparable from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.lang.CharSequence from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.lang.String from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.lang.reflect.GenericDeclaration from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.lang.reflect.Type from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.lang.reflect.AnnotatedElement from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
[Loaded java.lang.Class from D:\Program Files\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\jre\lib\rt.jar]
从以上信息你基本上可以看到一个在执行的时候加载的相关类及jar,明白类在什么时候被加载。以上都是类加载器classloader的工作(这是一份没有小费的工作),getCallerClassLoader()是类加载器的一个私有方法,所以我们是没办法直接调用的,所以在运行中我们应该通过当前 类的实例.getClass().getClassLoader(); getCallerClassLoader()这个方法的调用其实是暗箱操作如果你玩过地下柳河菜或者都求的话,你懂得! 在new一个实例的时候这个方法会被默认调用。
在这里我纠正一个常识,静态初始化区域并不是在类第一次载入才会被加载,而是在第一次初始化时被加载并且只有一次。我们测试一下,下面是测试代码:
package com.ec.test.classloader.test;
public class C {
/**
* @param args
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws ClassNotFoundException {
// TODO Auto-generated method stub
//将true改成false在测试一下
Class.forName("com.ec.test.classloader.test.B", true, new C().getClass().getClassLoader());
}
}
class B{
static{
System.out.println("test静态初始化区域");
}
}
我们看一下Class.forName()的api
* @param name fully qualified name of the desired class
* @param initialize whether the class must be initialized
* @param loader class loader from which the class must be loaded
* @return class object representing the desired class
第二个参数 initialize 布尔类型,判断该类是否必须初始化。当initialize 为true的时候我们就会看到 ”test静态初始化区域“输出 ,相反没有任何输出,
classloader.loadClass("")与 Class.forName("com.cn.B", false, classLoader);一样都没有对类进行第一次初始化
那么类如果在第一次载入的时候没有被初始化,那么在什么时候会初始化呢,答案是在第一次实例化的时候,如果第一次载入已经初始化,那么第一次实例化还会初始化吗,其实前面我们已经说到了,在第一次初始化时被加载并且只有一次。也就是说第一次载入的话已经被初始化了那么第一次实例化的时候是不会被再次初始化的,下面我们验证一下修改上面的代码
package com.ec.test.classloader.test;
public class C {
/**
* @param args
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
// TODO Auto-generated method stub
//将true改成false在测试一下
System.out.println("==========开始载入类B==========");
Class c=Class.forName("com.ec.test.classloader.test.B", true, new C().getClass().getClassLoader());
System.out.println("==========载入类B结束==========");
System.out.println("==========开始实例化B==========");
Object o=c.newInstance();
System.out.println("==========实例化B结束===========");
//new C().getClass().getClassLoader().loadClass("com.ec.test.classloader.test.B");
}
}
class B{
static{
System.out.println("test静态初始化区域");
}
}
下面我们来看一下initialize 为true的时候输出结果为
==========开始载入类B==========
test静态初始化区域
==========载入类B结束==========
==========开始实例化B==========
==========实例化B结束===========
下面我们来看一下initialize 为false的时候输出结果为
==========开始载入类B==========
==========载入类B结束==========
==========开始实例化B==========
test静态初始化区域
==========实例化B结束===========
好了通过结果你懂得。 在这里在说一点我们采用new操作的时候会自动初始化和实例化该类,这个暗箱操作也许是我们长久没发现这个问题的原因。

- 大小: 13.3 KB
分享到:
相关推荐
Java类加载器是Java虚拟机(JVM)的重要组成部分之一,主要负责在程序运行时将类文件加载到内存中,并对其进行验证、准备和解析等初始化操作。类加载器采用双亲委派模型,这种模型可以有效避免类的重复加载,同时也为...
4. **类加载器问题**:Java的类加载机制如果处理不当,可能导致类冲突或内存泄漏,从而引发JVM崩溃。理解双亲委派模型以及如何自定义类加载器是解决这类问题的关键。 5. **安全问题**:Java 8加强了安全管理,如果...
【标题】"记事本(JAVA代码)"指的是使用Java编程语言实现的一个基本文本编辑器,类似于我们在日常操作中常见的“记事本”程序。在Windows操作系统中,记事本是一个简单但实用的文本编辑工具,可以用来创建、查看和...
- **类的加载**:由类加载器负责,包括加载、验证、准备、解析和初始化等步骤。 - **对象的创建**:首先定义类,然后通过new关键字创建对象实例。 ##### 3.8 四大内部类 - **成员内部类**:定义在外部类中的非静态...
驱动管理器,是JDBC API中的核心类,用于加载和管理数据库驱动。 #### Connection 连接,是指与数据库建立的连接。在JDBC中,`Connection`对象用于代表这种连接。 #### Statement 表示执行对象,是JDBC API中的...
11. **JVM内部机制**:了解JVM的内存模型,包括类加载器、运行时数据区等。 12. **标准库API**:熟悉Java提供的各种标准库,如String类、Date类、Math类等,以及如何有效地使用它们。 通过这些题库的学习,考生...
- **实现多个接口**:在Java中,一个类可以通过implements关键字同时实现多个接口。 - **接口中的成员**:接口中只能定义常量和抽象方法。 - **构造方法调用**:在一个类的构造方法中调用另一个构造方法需要使用`...
5. **加载动态链接库**:在Java代码中使用`System.loadLibrary`或`java.lang.ClassLoader`加载本地库。 6. **XML解析**:可能使用了如libxml2或其他本地XML解析库,通过JNI接口与Java代码交互,处理XML数据。 7. *...
Hibernian在这里可能是笔误,实际应该是指Hibernate,一个流行的Java对象关系映射(ORM)框架,用于简化数据库操作。在这个"DWR_Hibernian分页类文件"中,我们很可能是看到如何结合DWR和Hibernate来实现Web应用中的...
在Android平台上进行游戏编程是一项富有挑战且充满乐趣的工作。"Learning Android Game Programming"是一本专为初学...同时,配合书中的英文原版,你还能提升专业英语阅读能力,更好地理解国际游戏开发社区的技术动态。
- **为单个域类添加功能**:讲解了如何通过方法和事件监听器为特定的域类添加额外的行为。 - **为多个域类添加功能**:介绍了插件和扩展点的概念,这些可以用于在整个应用程序范围内共享通用的功能。 - **在包内...
Tomcat9还引入了动态类加载,提高了内存利用率。此外,它优化了连接器,提升了并发处理能力,并加强了对TLS(传输层安全)的支持,提供了更先进的加密选项。 下载信息: - Apache Tomcat 9.0.8 for Windows x64: 这...
【标题】"w3school(full)" 是一个综合性的学习资源包,主要涵盖了互联网开发中的核心技术和语言,包括HTML、AJAX、Action JavaScript以及CSS。这个压缩包提供的内容旨在为学习者提供一个全面的Web开发基础知识平台。...
- **知识点**: 在Java中,`SimpleDateFormat`类用于将日期格式化为字符串,也可以将字符串解析为日期。 - **解析**: 正确答案应为`SimpleDateFormat`,题目中的括号内答案为`DateForma`,应该是笔误,正确的应该是`...
- 类加载器负责将类文件加载到JVM中。 26. **OSGI** - OSGI是一个模块化平台,支持动态加载和卸载模块。 27. **Https请求慢的解决办法** - 解决HTTPS请求慢的问题可以通过减少握手次数、预加载证书等方式实现。...
- **方法重载(Overloading)**: 在同一个类中有多个同名方法,这些方法具有不同的参数列表(参数个数不同、参数类型不同或参数顺序不同)。 - **方法重写(Overriding)**: 子类重写父类的方法,子类的方法必须与父类的...
至于标签中的"mybits",可能是笔误,应该是"MyBatis",MyBatis作为持久层框架,负责将Java对象映射到数据库中的SQL语句,使得数据库操作更加简洁。在SSM框架中,MyBatis通过Mapper接口和XML配置文件或注解定义SQL...
- **Instrumentation**:用于服务器和类加载器的工具,常用于应用服务器中的类加载。 - **Test**:提供测试支持,帮助开发者编写单元测试和集成测试。 5. **使用场景**: Spring Framework 3.2.4 可用于构建各种...
11. **OpenCore黑苹果安装**:OpenCore是MacOS的引导加载器,用于在非Apple硬件上安装和运行MacOS。教程将指导用户完成安装过程。 12. **Rust表达式Parser设计**:Rust语言可以用来实现编译器的解析器部分,用于将...