java.lang.NoClassDefFoundError问题

原创 2012年11月08日 14:07:01

Java程序员经常被运行时的java.lang.NoClassDefFoundError搞得焦头烂额,产生这个问题的原因显然是Java的类加载器没有找到相关类的定义


这里就先举一个实际问题的例子

[root@cat Work]# java -classpath /mnt/data/Work/TestRabbitMQ/lib/rabbitmq-client.jar -jar TestRabbitMQ.jar consumer
Exception in thread "main" java.lang.NoClassDefFoundError: com/rabbitmq/client/ConnectionFactory
at com.rain.testrabbitmq.Consumers.service(Consumers.java:30)
at com.rain.testrabbitmq.TestRabbitMQ.main(TestRabbitMQ.java:40)
Caused by: java.lang.ClassNotFoundException: com.rabbitmq.client.ConnectionFactory
at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
... 2 more
[root@cat Work]# jar tf /mnt/data/Work/TestRabbitMQ/lib/rabbitmq-client.jar | grep ConnectionFactory
com/rabbitmq/client/ConnectionFactory.class

问题:明明通过classpath参数指定了rabbitmq-client.jar路径,且该jar包中包含ConnectionFactory.class,为什么还是报java.lang.NoClassDefFoundError错误呢?


问题解决过程:

1,先引入一个非常有用的java命令参数-verbose:class,通过该参数可以详细看到Java虚拟机运行时加载class的信息,如下:

# java -verbose:class -classpath /mnt/data/Work/TestRabbitMQ/lib/rabbitmq-client.jar -jar TestRabbitMQ.jar consumer
[Opened /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.lang.Object from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.io.Serializable from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.lang.Comparable from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.lang.CharSequence from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.lang.String from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.lang.reflect.GenericDeclaration from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.lang.reflect.Type from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.lang.reflect.AnnotatedElement from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]

......

[Loaded java.lang.Enum from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.util.concurrent.TimeUnit from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.util.concurrent.TimeUnit$1 from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.util.concurrent.TimeUnit$2 from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.util.concurrent.TimeUnit$3 from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.util.concurrent.TimeUnit$4 from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.util.concurrent.TimeUnit$5 from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.util.concurrent.TimeUnit$6 from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.util.concurrent.TimeUnit$7 from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.util.Queue from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.util.concurrent.BlockingQueue from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.util.AbstractQueue from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.util.concurrent.LinkedBlockingQueue from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.util.concurrent.locks.Condition from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.util.concurrent.LinkedBlockingQueue$Node from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.util.concurrent.ThreadFactory from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
[Loaded java.util.concurrent.Executors$DefaultThreadFactory from /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/rt.jar]
Exception in thread "main" java.lang.NoClassDefFoundError: com/rabbitmq/client/ConnectionFactory
at com.rain.testrabbitmq.Consumers.service(Consumers.java:30)
at com.rain.testrabbitmq.TestRabbitMQ.main(TestRabbitMQ.java:40)
Caused by: java.lang.ClassNotFoundException: com.rabbitmq.client.ConnectionFactory
at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
... 2 more

通过这些信息发现,Java虚拟机确实没有加载rabbitmq-client.jar,那么没找到com/rabbitmq/client/ConnectionFactory就很自然了。


看来似乎这种执行方式下-classpath指定后,虚拟机并不认帐,那么换一种执行方式

cd TestRabbitMQ/bin

$java -classpath ./:/data/Work/TestRabbitMQ/lib/rabbitmq-client.jar com.rain.testrabbitmq.TestRabbitMQ consumer

发现程序执行OK,说明该参数对于这种方式还是有用的,问题是不是出在jar包上


通过查询Eclipse打jar包的资料,发现jar包中有个很重要的文件META-INF/MANIFEST.MF,该文件中的Class-Path定义了依赖的第三方jar的路径和名称,而如果该文件让Eclipse默认生成,则该文件中不会有Class-Path定义

故自己创建一个MANIFEST.MF文件

Manifest-Version: 1.0
Main-Class: com.rain.testrabbitmq.TestRabbitMQ
Class-Path: lib/rabbitmq-client.jar

关于MANIFEST.MF文件的写法可以参考http://blog.csdn.net/happyhell/article/details/6639792

打包时只需将src目录包括进来,并且利用已有的MANIFEST.MF文件即可



将生成好的jar包放在和lib平级的目录中,执行java -jar TestRabbitMQ.jar即可成功运行


查询java -jar运行方式的相关帮助,验证了这个结论:使用-jar参数后, 系统的Classpath 变量不再起作用. 虚拟机将去MANIFEST.MF中的Class-Path 下找相关的包.

          -jar
             Execute a program encapsulated in a JAR file. The first argument is the name of a JAR file instead of a startup class name. In order for this  option
             to  work,  the  manifest  of the JAR file must contain a line of the form Main-Class: classname. Here, classname identifies the class having the pub‐
             lic static void main(String[] args) method that serves as your application's starting point. See the Jar tool reference page and the Jar trail of the
             Java Tutorial @
             http://java.sun.com/docs/books/tutorial/jar for information about working with Jar files and Jar-file manifests.


          When you use this option, the JAR file is the source of all user classes, and other user class path settings are ignored.



参考文档:http://en.wikipedia.org/wiki/Classpath_(Java)

参考文档:http://www.ibm.com/developerworks/cn/java/j-lo-classloader/index.html


RabbitMQ

rabbitmq使用场景,安装,vhost配置,简单队列,工作队列work queues,消息应答ack与消息持久化durable,publish/subscribe发布订阅模式,routing路由模式,topic主题模式,消息确认机制(事务+confirm),spring集成
  • 2018年04月12日 09:22

RabbitMQ学习之Java客户端连接测试(二)

如果您和我一样是一个Linux和RabbitMQ的新手,首先不要一开始就想的太好太完美,首先从最简单的做起。 不要去找那些看上去很高大上的帖子,也不要一开始就和maven以及spring去集成。就写简...
  • wplove1029
  • wplove1029
  • 2016-04-26 12:13:00
  • 13285

Jar包冲突引发的血案

Spring Boot和RabbitMq集成的时候,引入 compile("org.springframework.boot:spring-boot-starter-amqp&quot...
  • jiaobuchong
  • jiaobuchong
  • 2018-02-09 23:37:41
  • 115

java实现rabbitmq消息的发送接受

本文不介绍amqp和rabbitmq相关知识,请自行网上查阅 本文是基于spring-rabbit中间件来实现消息的发送接受功能 see http://www.rabbitmq.com/tutor...
  • sdyy321
  • sdyy321
  • 2013-07-04 16:35:42
  • 81727

怎么解决java.lang.NoClassDefFoundError错误

前言在日常Java开发中,我们经常碰到java.lang.NoClassDefFoundError这样的错误,需要花费很多时间去找错误的原因,具体是哪个类不见了?类明明还在,为什么找不到?而且我们很容...
  • jamesjxin
  • jamesjxin
  • 2015-06-23 15:22:29
  • 456505

Rabbitmq C++客户端 Rabbitmq Client

概述 最近项目消息队列服务选用了rabbitmq,我的server端用的C++开发的,于是需要开发rabbitmq的c++客户端,国际惯例先百度了一圈,然后github搜了一圈,竟然发现排名靠前的需要...
  • woniu211111
  • woniu211111
  • 2017-07-26 11:10:18
  • 5121

线上一个类加载的问题(java.lang.NoClassDefFoundError)

一、背景     2012年02月下旬,把应用的容器从jboss换成了jetty. 二、故障      前几天上午 同学叫我看一个问题,截图如下: 大致描述...
  • bxyz1203
  • bxyz1203
  • 2012-03-04 11:22:59
  • 4885

javax.jms及java消息机制

JMS(Java Message Service) 即Java消息服务。它提供标准的产生、发送、接收消息的接口简化企业 应用的开发。它支持两种消息通信模型:点到点(point-to-point)(P2...
  • baidu_26550817
  • baidu_26550817
  • 2015-10-06 19:06:08
  • 3959

Dubbo消费端java.lang.NoClassDefFoundError错误的排查

当时在代码中调用Dubbo服务时产生这个异常。javax.servlet.ServletException: org.glassfish.jersey.server.ContainerExceptio...
  • Revivedsun
  • Revivedsun
  • 2016-10-31 19:18:14
  • 4440

nested exception is java.lang.NoClassDefFoundError: com/mchange/v2/ser/Indirector

最近在spring配置文件中遇到了一个问题困扰了挺久:        警告: Could not load driverClass com.jdbc.mysql.Driver j...
  • RiceToLife
  • RiceToLife
  • 2016-07-19 00:05:10
  • 3754
收藏助手
不良信息举报
您举报文章:java.lang.NoClassDefFoundError问题
举报原因:
原因补充:

(最多只允许输入30个字)