java Web 环境 Spring/Wicket/Derby/Jetty 中 NoClassDefFoundError 错误的问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5597947/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 11:50:17  来源:igfitidea点击:

Issue with NoClassDefFoundError error in a web environment Spring/Wicket/Derby/Jetty

javaspringmavenjettyderby

提问by Berlin Brown

I am trying to build a simple JDBC Spring Template application, the web framework I am using is wicket and under the jetty 6 web server (through the Jetty Maven Plugin). Also, I am building the app with Eclipse.

我正在尝试构建一个简单的 JDBC Spring 模板应用程序,我使用的 Web 框架是 wicket 并且在 jetty 6 Web 服务器下(通过 Jetty Maven 插件)。另外,我正在使用 Eclipse 构建应用程序。

For some reason, I am getting a NoClassDefFoundError with the Derby jdbc class. I am assuming I would get a class not found exception was not found, so am guessing something else is happening. The derby class is part of the classpath, the WEB-INF/lib directory. What do you think the issue is?

出于某种原因,我在使用 Derby jdbc 类时遇到了 NoClassDefFoundError。我假设我会得到一个 class not found 异常未找到,所以我猜测其他事情正在发生。derby 类是类路径的一部分,即 WEB-INF/lib 目录。你认为问题是什么?

My thoughts on the problem:It is not a "jar not found in the classpath" error but more an issue with Java or spring dynamically loading that class and when it gets loaded.

我对这个问题的看法:这不是“在类路径中找不到 jar”错误,而是 Java 或 spring 动态加载该类以及何时加载的问题。

I am using Eclipse as the development tool but it probably isn't part of the problem. I am still using Maven on the command line and getting the same issue.

我使用 Eclipse 作为开发工具,但这可能不是问题的一部分。我仍在命令行上使用 Maven 并遇到相同的问题。

Here is the error:

这是错误:

WicketMessage: Can't instantiate page using constructor public wicketspring.easy.HomePage()

WicketMessage:无法使用构造函数 public wicketspring.easy.HomePage() 实例化页面

Root cause:

根本原因:

java.lang.NoClassDefFoundError: Could not initialize class org.apache.derby.jdbc.EmbeddedDriver
     at java.lang.Class.forName0(Native Method)
     at java.lang.Class.forName(Class.java:169)
     at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1130)
     at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:880)
     at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:113)
     at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:79)
     at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:577)
     at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:619)
     at wicketspring.easy.jdbc.JdbcWicketSpringHandler.data(JdbcWicketSpringHandler.java:39)
     at WICKET_wicketspring.easy.jdbc.JdbcWicketSpringHandler$$FastClassByCGLIB$$f1187cb6.invoke(<generated>)
     at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
     at org.apache.wicket.proxy.LazyInitProxyFactory$CGLibInterceptor.intercept(LazyInitProxyFactory.java:319)
     at WICKET_wicketspring.easy.jdbc.JdbcWicketSpringHandler$$EnhancerByCGLIB$$e8f0e174.data(<generated>)
     at wicketspring.easy.HomePage.<init>(HomePage.java:91)
     at wicketspring.easy.HomePage.<init>(HomePage.java:47)

Here is the applicationContext.xml for Spring:

这是 Spring 的 applicationContext.xml:

<beans>
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver" />
        <property name="url"><value>jdbc:derby:wicketspringdb</value></property>
        <property name="username"><value></value></property>
        <property name="password"><value></value></property>
    </bean> 
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource" />
    </bean> 
</beans>
<beans> 
    <import resource="classpath:common.xml"/>
    <bean id="jdbcHandler" class=wicketspring.easy.jdbc.JdbcWicketSpringHandler">
        <property name="jdbcTemplate" ref="jdbcTemplate" />
    </bean>

</beans>


...
Another stack trace system out.

Page.java:74) - At [2b] -- java.lang.NoClassDefFoundError: Could not initialize class org.apache.derby.jdbc.EmbeddedDriver
java.lang.NoClassDefFoundError: Could not initialize class org.apache.derby.jdbc.EmbeddedDriver
        at wicketspring.easy.HomePage.<init>(HomePage.java:72)
        at wicketspring.easy.HomePage.<init>(HomePage.java:47)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:
39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorIm
pl.java:27)

...

...

Here is the java code, the code compiles and I can print out the class but I can't instantiate it. Strange?

这是java代码,代码编译,我可以打印出类,但我不能实例化它。奇怪的?

Java Code:

Java代码:

package wicketspring.easy;

import java.util.List;

import org.apache.wicket.Application;
import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.proxy.IProxyTargetLocator;
import org.apache.wicket.proxy.LazyInitProxyFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import model.LoadableDetachableList;
import model.SelectionOptionBean;
import wicketspring.easy.jdbc.JdbcWicketSpringHandler;
import wicketspring.easy.service.IStateListService;
import wicketspring.easy.service.StateListServiceImpl;

import org.apache.derby.jdbc.EmbeddedDriver;

public class HomePage extends WebPage {

    private final JdbcWicketSpringHandler jdbcWicketSpringHandler;

    public HomePage(final PageParameters parameters) {

        super(parameters);        
        jdbcWicketSpringHandler = (JdbcWicketSpringHandler) LazyInitProxyFactory.createProxy(JdbcWicketSpringHandler.class,
                new IProxyTargetLocator() {
                    private static final long serialVersionUID = 1L;
                    public Object locateProxyTarget() {
                        return ((WicketApplication) Application.get()).context().getBean("jdbcHandler");
                    }
                });    

        /// WEIRD BECAUSE IT REACHES THIS POINT!!!
        LOGGER.debug("At [1] -- " + EmbeddedDriver.class);
        try {
            LOGGER.debug("At [2] -- " + new org.apache.derby.jdbc.EmbeddedDriver());
        } catch (NoClassDefFoundError ne) {
                // STACK TRACE ERROR HERE!!!!
            LOGGER.debug("At [2b] -- " + ne);
            ne.printStackTrace();
        } catch (Exception e) {
            LOGGER.debug("At [2] -- " + e);
            e.printStackTrace();
        }
        try {

            LOGGER.debug("At -- " + Class.forName("org.apache.derby.jdbc.EmbeddedDriver"));     
        } catch (NoClassDefFoundError ne) {
            LOGGER.debug("At [3b] -- " + ne);
            ne.printStackTrace();
        } catch (Exception e) {
            LOGGER.debug("At [3] -- " + e);
            e.printStackTrace();
        }

        /// ERROR FOR STACKOVERFLOW IS GENERATED FROM THIS LINE!!!!
        LOGGER.debug("At HomePage - jdbcHandler [3]: " + jdbcWicketSpringHandler.toStringJdbcTemplate());
        LOGGER.debug("At HomePage - jdbcHandler [3]: " + jdbcWicketSpringHandler.data());        

        ...

} // End of Class //

Edit: I might be missing a jar file that is a dependency of Spring Jdbc or dbcp.

编辑:我可能缺少一个依赖 Spring Jdbc 或 dbcp 的 jar 文件。

Here is my WEB-INF/lib listing:

这是我的 WEB-INF/lib 列表:

antlr-2.7.6.jar
aopalliance-1.0.jar
avalon-framework-4.1.3.jar
axis-1.4.jar
axis-jaxrpc-1.4.jar
cglib-nodep-2.2.jar
commons-collections-3.1.jar
commons-dbcp-1.2.2.jar
commons-logging-1.1.jar
commons-pool-1.3.jar
derby-10.6.1.0.jar
dom4j-1.6.1.jar
hibernate-core-3.5.1-Final.jar
jetty-6.1.4.jar
jetty-management-6.1.4.jar
jetty-util-6.1.4.jar
jta-1.1.jar
log4j-1.2.14.jar
logkit-1.0.1.jar
mx4j-3.0.1.jar
mx4j-tools-3.0.1.jar
servlet-api-2.5-6.1.4.jar
servlet-api-2.5.jar
slf4j-api-1.5.8.jar
slf4j-log4j12-1.4.2.jar
spring-2.5.6.jar
spring-aop-2.5.6.jar
spring-beans-2.5.6.jar
spring-context-2.5.6.jar
spring-core-2.5.6.jar
spring-jdbc-2.5.6.jar
spring-test-2.5.6.jar
spring-tx-2.5.6.jar
testRunWrapper-1.0.0.jar
wicket-1.4.13.jar
wicket-ioc-1.4.13.jar
wicket-spring-1.4.13.jar
xml-apis-1.0.b2.jar

采纳答案by Berlin Brown

So the 'Could not initialize class org.apache.derby.jdbc.EmbeddedDriver' error was actually the main symptom of some other, less obvious, class loading issues.

因此,“无法初始化类 org.apache.derby.jdbc.EmbeddedDriver”错误实际上是其他一些不太明显的类加载问题的主要症状。

I was using Jetty as the web server and Spring as the framework under java6.

我使用 Jetty 作为 web 服务器,使用 Spring 作为 java6 下的框架。

I believe there was a class loading issue, related to the MBeanServer class.

我相信存在与 MBeanServer 类相关的类加载问题。

And I did ignore an error that happened at startup: "Caused by: java.lang.LinkageError: loader constraint violation: loader (instance of org/mortbay/jetty/webapp/WebAppClassLoader) previously initiated loading for a different type with name "javax/management/MBeanServer" at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632) at java.lang.ClassLoader.defineClass(ClassLoader.java:616) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)"

而且我确实忽略了启动时发生的错误:“由以下原因引起:java.lang.LinkageError:加载器约束违规:加载器(org/mortbay/jetty/webapp/WebAppClassLoader的实例)之前为名称为“javax”的不同类型启动了加载/management/MBeanServer" at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632) at java.lang.ClassLoader.defineClass(ClassLoader.java:616) at java。 security.SecureClassLoader.defineClass(SecureClassLoader.java:141)"

I searched for the class in my WEB-INF/lib directory. It was included as part of mx4j:jar. Mx4j was a dependency for jetty-management.jar. I didn't really need jetty-management so I removed that reference from my pom file.

我在我的 WEB-INF/lib 目录中搜索了这个类。它作为 mx4j:jar 的一部分包含在内。Mx4j 是 jetty-management.jar 的依赖项。我真的不需要码头管理,所以我从我的 pom 文件中删除了那个引用。

Basically the inclusion of MBeanServer (from mx4j) caused some kind of class loading issue where org.apache.derby.jdbc.EmbeddedDriver couldn't be loaded properly. I removed it from my web application and the application started working properly.

基本上,包含 MBeanServer(来自 mx4j)导致了某种类加载问题,其中 org.apache.derby.jdbc.EmbeddedDriver 无法正确加载。我从我的 Web 应用程序中删除了它,应用程序开始正常工作。

回答by Luke Woodward

The message Could not initialize class org.apache.derby.jdbc.EmbeddedDrivermeans that at that point the JVM has already tried and failed to initialize this class.

该消息Could not initialize class org.apache.derby.jdbc.EmbeddedDriver意味着此时 JVM 已经尝试初始化此类,但失败了。

The JVM will fail to initialize a class if an exception is thrown and not caught within the class's static initializer. The only reasons that the JVM would be attempting to initializing the EmbeddedDriver class more than once would be:

如果抛出异常并且未在类的静态初始化程序中捕获,则 JVM 将无法初始化类。JVM 多次尝试初始化 EmbeddedDriver 类的唯一原因是:

  • some exception initializing the class was thrown, this exception was caught elsewhere and the program continued,
  • some exception initializing the class was thrown, but the program then entered a finallyblock, and within this finallyblock the JVM attempted to load the class again.
  • 一些初始化类的异常被抛出,这个异常在别处被捕获,程序继续,
  • 一些初始化类的异常被抛出,但程序随后进入了一个finally块,在这个finally块中 JVM 尝试再次加载该类。

The static initializer for EmbeddedDriver (source) calls a boot()method. However, this boot()method calls a fair bit of other code, so it's difficult to tell where the problem could be. I had a look at some of the sourceof org.apache.commons.dbcp.BasicDataSource, but it seems the line numbers in your stacktrace don't agree with the source. I don't know which version of commons-dbcp you are using.

EmbeddedDriver ( source)的静态初始值设定项调用一个boot()方法。但是,此boot()方法调用了相当多的其他代码,因此很难判断问题出在哪里。我有一个看看一些的来源org.apache.commons.dbcp.BasicDataSource,但似乎在你的堆栈跟踪的行号不与源一致。不知道你用的是哪个版本的commons-dbcp。

If you've got no other output messages nor stacktraces to go on, your best bet may be to attach the source of Derby to your debugger and step through it to see what's going on.

如果您没有其他输出消息或堆栈跟踪,那么最好的办法可能是将 Derby 的源代码附加到您的调试器并逐步查看发生了什么。



顺便说一句,很可能“打印”一个尚未初始化的类。考虑以下类:

class St1 {
    static {
        System.out.println("In static initializer");
    }
}

public class St2 {
    public static void main(String[] args) {
        System.out.println(St1.class);
        System.out.println(new St1());
    }
}

When I run class St2, I get the following output:

当我运行 class 时St2,我得到以下输出:

class St1
In static initializer
St1@65690726

回答by Bryan Pendleton

Sometimes these errors are because you have Derby in your classpath twice, somehow. With modern JDKs, Derby's drivers are 'auto-loaded', meaning that the JDK will look for JDBC drivers on the classpath and automatically load them. So you might check your system classpath as well as your application's libraries; perhaps you have a second copy of Derby hidden away somewhere in the path and the exception is trying to tell you that the two versions of Derby are in conflict.

有时,这些错误是因为不知何故,您的类路径中有两次 Derby。对于现代 JDK,Derby 的驱动程序是“自动加载的”,这意味着 JDK 将在类路径上查找 JDBC 驱动程序并自动加载它们。因此,您可能会检查系统类路径以及应用程序的库;也许您在路径的某处隐藏了第二个 Derby 副本,并且异常试图告诉您这两个版本的 Derby 存在冲突。

回答by matt b

Are you sure that your derby.jar contains the org.apache.derby.jdbc.EmbeddedDriverclass? You may want to check you have the correct version.

您确定您的 derby.jar 包含org.apache.derby.jdbc.EmbeddedDriver该类吗?您可能需要检查您是否拥有正确的版本。

If you are using Maven to package the application then it is strange that the jar name ends up being derby.jarwith no version number attached to it.

如果您使用 Maven 打包应用程序,那么奇怪的是 jar 名称最终derby.jar没有附加版本号。