明明jar包已经引入了,并且编译不报错,但是运行却还提示classnotfound,什么原因?

来源:互联网 发布:linux查看log文件 编辑:程序博客网 时间:2024/04/29 16:05

我在写cxf的客户端代码调用cxf接口的时候,编译不报错,但是运行这一句的时候的时候报错:

Client client = clientFactory.createClient("http://XX.XX.XX.XX:8080/XX/XXService?wsdl");

报错提示:

Caused by: java.lang.ClassNotFoundException: com.sun.tools.internal.xjc.api.XJC//缺少的class,即jar包

···

···

at org.apache.cxf.common.jaxb.JAXBUtils.createSchemaCompiler(JAXBUtils.java:672)//出错的class,即运行出错的class


我发现该class在tool.jar中,所以将tool.jar引入。运行还是报错:

Caused by: java.lang.ClassNotFoundException: com.sun.tools.internal.xjc.api.XJC,明明我已经引入了,这就奇怪了。

我现在有两个疑问:

1)既然缺class(即却jar包),为什么编译不报错?

这个很好理解,因为我的java代码中这一句是没有编译错误的:

Client client = clientFactory.createClient("http://XX.XX.XX.XX:8080/XX/XXService?wsdl");

这就是封装的弊端了,封装(即引入class文件,即jar包)是java的特点和优势,同时也是它的劣势。因为劣势就表现在编译的时候,不能深入class文件去编译,就算被封装的class(即jar包中的某个class)的代码中缺少另一个class即jar包,编译的时候也不会报错。只有运行的时候才会报错。


2)既然包含这个class的jar包已经引入了,为什么运行还报错?

这就是classloader的问题了,即class文件的加载原理(即java代码中import的class,是从哪个路径下获取下获取并加入到内存中的)。

所以,包含com.sun.tools.internal.xjc.api.XJC的jar包已经引入了,还报错的原因,就出在classloader。

原因是:

我引入的jar包如A.jar中某个class如a.class中(其实是a.class的源代码即a.java中)import了com.sun.tools.internal.xjc.api.XJC,而A.jar中的MANIFEST.MF文件,设置了jar包依赖的jar包的路径,如B.jar、C.jar两个。因此在a.class运行的时候,classloader会去A.jar包的MANIFEST.MF文件制定的依赖jar包中找com.sun.tools.internal.xjc.api.XJC这个class,而B.jar、C.jar根本没有引入,或者B.jar、C.jar中没有com.sun.tools.internal.xjc.api.XJC这个class,就会报错了。

classloader这个东西,这么傻、这么不智能吗?如果去A.jar的依赖的jar包即B.jar、C.jar中找不到com.sun.tools.internal.xjc.api.XJC这个class,就不会去整个lib库中去搜索吗?

这就要看classloader的原理了,看是不是这么回事。

======classloader的原理,加载依赖jar包:


还有一个原因我忽略了:

classA中的代码提示classB不存在,即classnotfound,并不是classB没有在classA中import,而是根本不需要import,因为classA和classB在一个目录下边,不需要import。

所以是因为classA路径下,没有classB这个类,所以报错,classnotfound。而根本不需要import。



----看来要找到原因,只能在调试的时候,引入源码了。

例子,以及调试过程见:

http://blog.csdn.net/ideality_hunter/article/details/73613161,链接中的文章,通过深入调试源码,彻底明白了了classnotfound的原因,以及找到了解决办法,此问题完美解决。




阅读全文
0 0
原创粉丝点击