package csu;
class ClassLoaderTest
{
public static void main(String[] args)
{
int a = 5, b = 10;
int max = Max.getMax(a, b);
System.out.println("a和b中较大的值是:"+max);
System.out.println(ClassLoaderTest.class.getName());
System.out.println(ClassLoaderTest.class.getClassLoader().getClass().getName());
}
}
class Max
{
public static int getMax(int a,int b)
{
return (a>b)?a:b;
}
}
保存文件,运行得到的结果是:
a和b中较大的值是:10
csu.ClassLoaderTest
sun.misc.Launcher$AppClassLoader
将文件中Max类修改成如下(只修改了Max类的getMax方法,就是讲a>b改为a<b):
class Max
{
public static int getMax(int a,int b)
{
return (a<b)?a:b;
}
}
保存文件,运行得到的结果是:
a和b中较大的值是:5
csu.ClassLoaderTest
sun.misc.Launcher$AppClassLoader
变化了,没错,就应该是这样。。。
现在,将该文件用MyEclipse打包成一个jar包,放到xxx\MyEclipse\Common\binary\com.sun.java.jdk.win32.x86_64_1.6.0.013\jre\lib\ext(xxx表示myeclipsse安装目录)目录下
保存文件并运行,结果依然是:
a和b中较大的值是:5
csu.ClassLoaderTest
sun.misc.Launcher$ExtClassLoader
这里也很好理解,不解释
接下来,把文件中Max类再改回来,即将return (a<b)?a:b;改为return (a>b)?a:b;
运行,得到的结果如下:
a和b中较大的值是:5
csu.ClassLoaderTest
sun.misc.Launcher$ExtClassLoader
明明把Max类中getMax方法改了,但运行的结果却和之前一样,为什么呢?
因为java类的加载有一种叫做委托机制的东西,就是要加载某个类时,虚拟机(具体不详)会先请求父类的加载器去加载所需要的类,
逐级往上申请,直到BootStrap类加载器(该加载器没有父加载器了),当父类加载器找到了所需要的类,就会直接加载该类,子类加载器就不需要加载了,
所以,即便子类加载器所寻找的位置有所需要的类,该类也不会被加载。
上面的例子就是这样,ExtClassLoader是AppClassLoader的父类,它会寻找\MyEclipse\Common\binary\com.sun.java.jdk.win32.x86_64_1.6.0.013\jre\lib\ext中的.jar文件,
如果找到所需要的类,AppClassLoader就不会再它寻找的位置去寻找所需要的类了,所以最终打印的结果是之前达成jar包中类所运行的结果。
但是问题来了,当我把ClassLoaderTest改为ClassLoaderTest2时,即把主类名字改了(下面用到改名字的地方也改了),
在运行文件,出现如下错误提示:
Exception in thread "main" java.lang.IllegalAccessError: tried to access class csu.Max from class csu.ClassLoaderTest2
at csu.ClassLoaderTest2.main(ClassLoaderTest.java:8)
试图从csu.ClassLoaderTest2类中的主函数访问csu.Max类
为什么不可以呢????
类加载器一直往上寻找,没找到ClassLoaderTest2类,然后由AppClassLoader加载该类。
ClassLoaderTest2类中主函数调用Max类中getMax方法时,AppClassLoader类加载器在委托父类加载器加载Max类,
最终ExtClassLoaderTest类加载器寻找到了所需要的Max类,但是为什么不能访问呢???
本人暂时还没搞明白,希望有高人指点一二,以解小白之疑惑。