黑马程序员技术交流社区
标题:
关于类加载器的问题
[打印本页]
作者:
张源锋
时间:
2013-4-2 21:54
标题:
关于类加载器的问题
本帖最后由 无奈№追夜 于 2013-4-3 12:12 编辑
public class Test1 {
public static void main(String[] args) {
A a = new A();
B b = new B();
C c = new C();
D d = new D();
}
}
class A{
A(){
System.out.println("A");
}
}
class B{
B(){
System.out.println("B");
}
}
class C{
C(){
System.out.println("c");
}
}
class D{
D(){
System.out.println("D");
}
}
复制代码
如上,类加载器是一次性把A B C D全部加载,还是用到哪个类就加载哪个类??如能把你们的测试方法也添上来那就更完美了...
作者:
王川
时间:
2013-4-2 23:48
当程序主动使用某个类的时候,类还没有被加载到内存中。加载的步骤大概如下
1.假如这个类没有被加载和连接,就先加载并连接该类。
2.假如该类的直接父类还没有被初始化,那么先初始化其父类.这里需要明白的是,所有的类的父类是java.lang.Object类(它是类层次结构的根),所以JVM总是会初始化它.依次是下一个父类.以此类推.系统会保证该类的所有父类,包括直接的,间接的,都会被初始化。
3.假如类中有初始化语句块,系统就依次执行这些初始化语句块的语句。
作者:
随便
时间:
2013-4-3 00:16
麻烦楼主把问题改一下,这是加载顺序问题,不是ClassLoader问题。
作者:
刘焕新
时间:
2013-4-3 02:11
本帖最后由 刘焕新 于 2013-4-3 02:18 编辑
个人认为,你的示例代码中的类的加载顺序是按照代码的执行顺序加载的,就是用到哪个类才加载哪个类。
Java中的类大致分为三种:
1 系统类;
2 扩展类;
3 程序员自定义的类。
JVM在启动时,只加载一些必须的系统类和扩展类,其余的大多数应用类,将在运行时动态加载。
你可以尝试从JVM的运行效率来分析考虑:假设有非常非常多的类文件等待执行,而如果JVM一次性加载所有的类文件到内存中,将会是什么结果?
JVM的运行效率本来就不是很高,这样做的结果可想而知吧。
JVM需要加载一个.class类文件的时候只有在下面几种情况下才会发生:
1 创建一个java实例对象;
2 调用一个类的静态方法;
3 静态域赋值;
4 访问静态域;
5 在顶层类中执行assert语句
当上面的某个条件发生的时候,ClassLoader才会真正的去加载相应的类。
下面来看看关于类的加载器:
JVM中默认的三个主要的类加载器:
BootStrap:负责加载JRE/librt.jar
ExtClassLoader:负责加载JRE/lib/ext/*.jar
AppClassLoader:负责加载CLASSPATH指定路径下的class文件
当JVM启动的时候,最先运行的是BootStrap加载器,依次往下。
三个类加载器是自上而下的继承关系,从下面代码打印的最后两行可以看出AppClassLoader的父类是ExtClassLoader。
其中,BootStrap不是Java语言编写的类,而是由JVM所在系统的语言编写的。在Windows下,此类就是用C++编写的程序。
class Apple {
Apple() {
System.out.println("Apple");
}
}
class Boy {
Boy() {
System.out.println("Boy");
}
}
class Cat {
Cat() {
System.out.println("Cat");
}
}
class Dog {
Dog() {
System.out.println("Dog");
}
}
public class Test1 {
public static void main(String[] args) {
Apple a = new Apple();
Boy b = new Boy();
Cat c = new Cat();
Dog d = new Dog();
System.out.println(a.getClass().getClassLoader());
System.out.println(b.getClass().getClassLoader());
System.out.println(c.getClass().getClassLoader());
System.out.println(d.getClass().getClassLoader());
ClassLoader loader = a.getClass().getClassLoader();
while(loader != null) {
//循环打印出ClassLoader的父类
System.out.println(loader.getClass().getName());
loader = loader.getParent();
}
}
}
复制代码
打印输出结果:
Apple
Boy
Cat
Dog
sun.misc.Launcher$AppClassLoader@19821f
sun.misc.Launcher$AppClassLoader@19821f
sun.misc.Launcher$AppClassLoader@19821f
sun.misc.Launcher$AppClassLoader@19821f
sun.misc.Launcher$AppClassLoader
sun.misc.Launcher$ExtClassLoader
复制代码
从打印输出的结果来看,至少能说明以上4个类对象都是由同一个类加载器加载的,它就是AppClassLoader。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2