java 类加载器 可以分为
根加载器
扩展加载器
应用加载器
用户自定义加载器(继承自 java.lang.ClassLoder)
查看一个类是被何种加载器 可以使用以下代码
public class ClassLoder {
public static void main(String[] args) {
System.out.println(ClassLoder.class.getClassLoader());
}
}
输出的结果为
sun.misc.Launcher$AppClassLoader@19821f
可以看出 这个类 是被应用加载器加载。
判断一个类是否会被加载,可以根据 6个条件。
首次主动使用的情形:
创建某个类的新实例时--new、反射、克隆或反序列化;
调用某个类的静态方法时;
使用某个类或接口的静态字段或对该字段赋值时(final字段除外);
调用Java的某些反射方法时
初始化某个类的子类时
在虚拟机启动时某个含有main()方法的那个启动类。
除了以上几种情形以外,所有其它使用JAVA类型的方式都是被动使用的,他们不会导致类的初始化。
看一个例子
public class LoderDemo {
public static void main(String[] args) {
System.out.println(GG.a);
}
}
class GG{
public static final int a = 10;
static{
System.out.println("GG...");
}
}
这短代码会输出多少呢
答案是 10
很明显 final 修饰的常量引用并不会引起类的初始化,我们再看下面一段代码。
public class LoderDemo {
public static void main(String[] args) {
System.out.println(GG.a);
}
}
class GG{
public static final int b = 12;
public static final int a = 1+b;
static{
System.out.println("GG...");
}
}
会输出什么呢
答案是 13
虽然a 是个表达式 但是,表达式里面的量都是常量,会被jvm 提前折叠
再看下面这段代码
public class LoderDemo {
public static void main(String[] args) {
System.out.println(GG.a);
}
}
class GG{
public static int b = 12;
public static final int a = 1+b;
static{
System.out.println("GG...");
}
}
这次的结果却是
GG...
13
虽然a 是个被final 修饰的,但是表达式含有 b一个不确定的量,所以jvm 会初始化整个类。而且静态代码块优先被执行。
我们再看 下面一短代码
class TestF{
public static TestF test = new TestF();
public static int count1 ;
public static int count2 = 0;
private TestF(){
count1++;
count2++;
}
public static TestF getInstances(){
return test;
}
}
public class SingleTownTest {
public static void main(String[] args) {
TestF f = TestF.getInstances();
System.out.println("count1="+f.count1);
System.out.println("count2="+f.count2);
}
}
输出的结果是什么呢
count1=1
count2=0
根据类的加载和初始化机制,直接在启动类里面调用其他类的静态方法,会导致初始化整个类。
根据代码执行的顺序。
TestF test 将会被赋给一个null 值,count1 count2 在第一轮赋值中都被初始化为0
new TestF(); 会调用构造函数去操作 类的两个静态成员,这个时候
count = 1 ,count2 = 1,
再往下 执行
count1 没有被再次赋值,但是count2 被赋值 为 0.
所以输出会是 1,0
我们再看下面一段代码
class TestF{
public static int count1 ;
public static int count2 = 0;
public static TestF test = new TestF();
private TestF(){
count1++;
count2++;
}
public static TestF getInstances(){
return test;
}
}
public class SingleTownTest {
public static void main(String[] args) {
TestF f = TestF.getInstances();
System.out.println("count1="+f.count1);
System.out.println("count2="+f.count2);
}
}
你会发现仅仅是将
public static TestF test = new TestF();
这句代码 移动了,但输出的结果却不同了。按照上面的分析,再来看一下。
调用 静态方法 初始化了 TestF 这个类
根据执行顺序,将 count1 count2 test 分别赋值为 0,0,null。
接着 将用户手动赋值的 0 赋值给 count2,
new TestF() 调用构造函数 并且赋值给 test
构造函数开始给 静态成员赋值,
count1 count2 分别自增1,值为1
输出。
这就是整个过程。
好好分析类加载器,其中的强大会直接影响到你的程序效率和正确性。
分享到:
相关推荐
类加载器和类之间存在一对一的关系,不同的类加载器加载的同名类会被视为不同的类。这为Java的模块化和隔离提供了基础,例如,在Web应用服务器中,每个Web应用都有自己的类加载器,保证了不同应用之间的类隔离。 6...
扩展类加载器加载`jre/lib/ext`目录下的扩展库;系统类加载器则加载应用的`CLASSPATH`指定的类。 2. **双亲委派模型** 类加载机制遵循双亲委派模型,即当一个类加载器接收到加载类的请求时,它首先会把这个请求...
Java类加载器和类加载机制实例分析 Java类加载器和类加载机制是Java语言的核心机制之一,它们负责将.class文件加载到内存中,并生成对应的java.lang.Class对象。下面我们将从实例形式分析Java类加载器和类加载机制...
类加载的层次结构(hierarchy)从引导类加载器开始,然后是扩展类加载器(ExtClassLoader),最后是应用程序类加载器(AppClassLoader),它们之间存在父子关系,形成一个树状结构。 了解类加载机制的细节有助于...
3. 单例模式的实现:在多线程环境中,如果每个线程都有自己的类加载器,可能导致单例模式失效,因为每个加载器加载的类都是独立的实例。 2. 再分析类加载 类加载的过程包括三个主要步骤:加载(Loading)、验证...
启动类加载器使用C++编写,用于加载Java的核心库,而其他类加载器则用于加载应用程序类和其他库。在判断两个类是否相等时,必须确保这两个类是由同一个类加载器加载的,否则即使来源于同一个class文件,这两个类也被...
例如,当修改了已加载类的代码,新的类可能无法覆盖旧的类,因为它们可能被不同加载器加载,导致JVM中存在两个版本的同一类,从而引发错误。 此外,热部署还可能导致类的缓存问题。JVM为了性能考虑,会缓存已加载的...
### Java反射机制与动态加载实例类 在Java中,反射是一种强大的工具,允许程序在运行时检查和修改其结构和行为。通过反射,我们可以动态地加载类、创建对象、访问和修改字段、调用方法等。本文将深入探讨Java反射...
Java提供了三种内置的类加载器:Bootstrap ClassLoader(引导类加载器)、Extension ClassLoader(扩展类加载器)和AppClassLoader(应用程序类加载器)。Bootstrap ClassLoader负责加载JDK核心库,如rt.jar;...
3. **Application Class Loader(应用程序类加载器)**:也称为系统类加载器,由`sun.misc.Launcher$AppClassLoader`实现。它负责加载用户类路径(classpath)上所指定的类库。Application Class Loader的父加载器为...
类加载器之间遵循委托机制,即下级类加载器先请求上级类加载器加载类,如果上级无法加载,则再由下级尝试加载。 3. **类的命名空间及运行时包**:类的命名空间是指在JVM中每个类都有唯一的标识符,防止命名冲突。...
在实际应用中,类加载器有多种,包括Bootstrap ClassLoader(引导类加载器)、Extension ClassLoader(扩展类加载器)和AppClassLoader(应用程序类加载器)。它们按照双亲委派模型工作,即子类加载器先尝试加载类,...
本文将深入探讨Java虚拟机中的类初始化以及加载器的父委托机制。 一、类的加载 类加载是JVM启动时或运行中根据需要动态加载类到内存中的过程。这个过程分为三个阶段:加载、链接和初始化。 1. 加载:JVM通过类...
Java虚拟机(JVM)的类加载机制是Java应用程序运行灵活性的关键。类加载涉及多个步骤,包括加载、验证、准备、解析、初始化...通过理解加载过程和类加载器的工作原理,开发者可以更好地控制和优化Java应用程序的运行。
类加载器通常分为系统类加载器和自定义类加载器,系统类加载器包括Bootstrap ClassLoader(负责加载JRE核心库)、Extension ClassLoader(加载扩展库)和App ClassLoader(加载应用程序类路径下的类)。 2. **验证*...
Java中的java.awt.datatransfer包提供了Clipboard接口和Transferable接口,可以实现程序内部或者与其他应用程序之间的数据交换。 图片操作可能涉及ImageIcon类,它可以加载并显示图片。Java Swing组件如JLabel可以...
2. **安全性和隔离性增强**:增强了类加载器的安全模型,使得不同的应用程序可以在同一个JVM实例中安全地共存。 3. **类加载器层次结构调整**:对类加载器的层次结构进行了调整,以适应新的模块化需求。 #### 六、...
Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...
这样,系统类(位于JDK的rt.jar中)通常由启动类加载器加载,而用户自定义的类则由应用程序类加载器加载,保证了核心类库与用户代码的隔离。 接着,我们来看看“命名空间保护域策略”。在Java中,每个类都有自己的...
- **扩展类加载器(Extension ClassLoader)**:该类加载器负责加载`<JAVA_HOME>/lib/ext`目录下的类库,或者被`java.ext.dirs`系统变量所指定的路径中的所有类库。 - **应用类加载器(Application ClassLoader)**:也...