清楚每个环节的操作过程就可以了
1.加载Loading
加载过程:
- 通过一个类的全限定名获取定义此类的二进制字节流
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
- 在内存中生成一个代表这个类的java.lang.class对象,作为方法区这个类的各种数据的访问入口
加载.class文件的方式:
- 从本地系统中直接加载
- 通过网络获取,典型场景: web Applet
- 从zip压缩包中读取,成为日后jar、war格式的基础运行时计算生成,使用最多的是: 动态代理技术
- 由其他文件生成,典型场景: JSP应用
- 从专有数据库中提取.class文件,比较少见
- 从加密文件中获取,典型的防class文件被反编译的保护措施
2.链接
3. 初始化
- 类都有一个构造器<init>
- <clinit>没有声明静态变量时就不会生成
- 类初始化顺序也就是<clint>执行顺序:父类静态
- 初始化一个类时会加锁,一个类只会被加载一次
在Java中,一个类只会被加载一次,这是通过Java虚拟机的类加载机制来保证的。类加载是懒加载的,只有在首次使用类的时候才会触发加载过程,加载过程包括类的加载、链接(验证、准备、解析)以及初始化。
一旦一个类被加载和初始化完成,它就会留在内存中,并且不会再次被加载。如果在同一个应用程序中多次尝试加载同一个类,Java虚拟机会识别到该类已经加载过,不会再次加载,直接返回该类的引用。
这种机制保证了类只被加载一次,避免了重复加载和初始化,节省了系统资源。这对于单例模式、静态变量等场景非常重要,因为这些情况下需要确保只有一个类的实例或静态资源。
需要注意的是,类加载器的不同实例可能会加载同一个类的多个副本。在Java中,类加载器有一个双亲委派模型,父类加载器会尝试加载类,只有在父类加载器无法加载时,子类加载器才会尝试加载。这可以避免类的重复加载。但是,不同的类加载器实例加载的类会被认为是不同的类,它们之间的类型检查会失败。
总之,一个类只会被加载一次,但是在不同的类加载器实例下,同一个类可能会加载多个副本。