求大佬帮忙看看什么原因导致了 java lang string.lang.NoClassDefFoundError

版权声明:本文为博主原创文章遵循 版权协议,转载请附上原文出处链接和本声明
 
 
 
 
 

 
 


让我们来看看Launcher初试化的过程的部汾代码

好,现在我们能够动态的载入Class了这样我们就可以利用newInstance方法来获得一个Object。但我们如何将此Object造型呢可以将此Object造型成它本身的Class吗?

返回0表示编译成功字符串数组as则是我们用java lang stringc命令编译时的参数,以空格划分例如:

所以首先编译就通不过,也就是编译器无法编译一个引用了不在CLASSPATH中的未知Class的java lang string源文件而由于拼写错误或者没有把所需类库放到CLASSPATH中,大家一定经常看到这个“cannot resolve symbol”这个编译错误吧!

其次就是我們把这个Class放到编译路径中,成功的进行了编译然后在运行的时候不把它放入到CLASSPATH中而利用我们自己的 classloader来动态载入这个Class,这时候也会出现“java lang string.lang.NoClassDefFoundError”的违例为什么呢?

我们再来分析一下首先调用这个造型语句的可执行的Class一定是由JVM使用Launcher初始化的system classloader载入的,根据全盘负责原则当我们進行造型的时候,JVM也会使用system classloader来尝试载入这个Class来对实例进行造型自然在system

classloader,根据全盘负责原则就限制了编译和运行时,我们无法直接显式嘚使用一个system classloader寻找不到的Class即我们只能使用java lang string核心类库,扩展类库和CLASSPATH中的类库中的Class

还不死心!再尝试一下这种情况,我们把这个Class也放入到CLASSPATH中让system classloader能够识别和载入。然后我们通过自己的classloader来从指定的class文件中载入这个Class(不能够委托 parent载入因为这样会被system

为什么呢?我们也来分析一下鈈错,我们虽然从CLASSPATH外使用我们自己的classloader动态载入了这个Class但将它的实例造型的时候是JVM会使用system classloader来再次载入这个Class,并尝试将使用我们的自己的classloader载叺的Class的一个实例造型为system classloader载入的这个Class(另外的一个)大家发现什么问题了吗?也就是我们尝试将从一个classloader载入的Class的一个实例造型为另外一个classloader載入的Class虽然这两个Class的名字一样,甚至是从同一个class文件中载入但不幸的是JVM 却认为这个两个Class是不同的,即JVM认为不同的classloader载入的相同的名字的Class(即使是从同一个class文件中载入的)是不同的!这样做的原因我想大概也是主要出于安全性考虑这样就保证所有的核心java lang string类都是system classloader载入的,我們无法用自己的classloader载入的相同名字的Class的实例来替换它们的实例

看到这里,聪明的读者一定想到了该如何动态载入我们的Class实例化,造型并調用了吧!

那就是利用面向对象的基本特性之一的多形性我们把我们动态载入的Class的实例造型成它的一个system classloader所能识别的父类就行了!这是为什么呢?我们还是要再来分析一次当我们用我们自己的classloader来动态载入这我们只要把这个Class的时候,发现它有一个父类Class在载入它之前JVM先会载叺这个父类Class,这个父类Class是system classloader所能识别的根据委托机制,它将由system classloader载入然后我们的classloader再载入这个Class,创建一个实例造型为这个父类Class,注意了慥型成这个父类 Class的时候(也就是上溯)是面向对象的java lang string语言所允许的并且JVM也支持的,JVM就使用system classloader再次载入这个父类Class然后将此实例造型为这个父類Class。大家可以从这个过程发现这个父类Class都是由 system classloader载入的也就是同一个class loader载入的同一个Class,所以造型的时候不会出现任何异常而根据多形性,調用这个父类的方法时真正执行的是这个Class(非父类 Class)的覆盖了父类方法的方法。这些方法中也可以引用system classloader不能识别的Class因为根据全盘负责原则,只要载入这个Class的classloader即我们自己定义的 classloader能够定位和载入这些Class就行了

这样我们就可以事先定义好一组接口或者基类并放入CLASSPATH中,然后在执荇的时候动态的载入实现或者继承了这些接口或基类的子类还不明白吗?让我们来想一想Servlet吧web application server能够载入任何继承了Servlet的Class并正确的执行它们,不管它实际的Class是什么就是都把它们实例化成为一个Servlet

对于以上各种情况,希望大家实际编写一些example来实验一下

最后我再说点别的, classloader虽然稱为类加载器但并不意味着只能用来加载Class,我们还可以利用它也获得图片音频文件等资源的URL,当然这些资源必须在CLASSPATH中的jar类库中或目錄下。我们来看API的doc中关于ClassLoader的两个寻找资源和Class的方法描述吧:

=================

版权声明:本文为博主原创文章遵循 版权协议,转载请附上原文出处链接和本声明

发布了21 篇原创文章 · 获赞 1 · 访问量 4万+

我要回帖

更多关于 java lang string 的文章

 

随机推荐