【问题标题】:ClassFormatError Exception after adding javaee-web-api dependency添加 javaee-web-api 依赖项后出现 ClassFormatError 异常
【发布时间】:2011-10-17 17:32:30
【问题描述】:

我想将 EL 2.2tomcat 7 一起使用 所以我在我的 pom 文件中添加了以下依赖项:

   <dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-web-api</artifactId>
    <version>6.0</version>
    <scope>provided</scope>
   </dependency>

但是在我添加它之后,我得到以下休眠异常:

ERROR [main] (DefaultSingletonBeanRegistry.java:490) - Destroy method on bean with name 'dataSource' threw an exception
java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/persistence/TransactionRequiredException
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
        at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
        at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessBeforeDestruction(PersistenceAnnotationBeanPostProcessor.java:356)
        at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:166)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:487)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:463)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingletons(DefaultSingletonBeanRegistry.java:431)
        at org.springframework.context.support.AbstractApplicationContext.destroyBeans(AbstractApplicationContext.java:1048)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:433)
        at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:84)
        at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
        at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:280)
        at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:304)
        at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
        at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
        at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:220)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:301)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:303)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
        at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
        at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
        at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62)
        at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140)
        at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127)
        at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:345)
        at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1009)

在我添加此依赖项之前一切正常,我认为它与其他依赖项冲突,也许我不知道,你们怎么看?

【问题讨论】:

  • 我对 Maven 部分一无所知,但是 - 正如您之前的一个问题所述 - Tomcat 不是符合 Java EE Web 配置文件的容器。它只是一个基本的 JSP/Servlet 容器。您必须改为声明单独的 JSP/Servlet 依赖项。

标签: hibernate spring jakarta-ee tomcat maven


【解决方案1】:

正如 BalusC 所指出的 - Tomcat 不符合 web 配置文件。所以你不能只拥有provided 的范围。

您可以查看最近发布的TomEE,它是一个符合 web-profile 的容器,并且使用了 tomcat。

您的例外情况似乎与 JPA 有关 - 确保您的 JPA 依赖项正常(例如,确保您的类路径中没有 1.0 和 2.0)。还有一件事——使用 EL 你不需要添加依赖项。它包含在 Tomcat 中。

【讨论】:

  • 异常与 JPA 并没有直接关联,尤其是与版本没有关联。如果您使用通过 javaee-web-api 工件提供的其他东西,也会出现此异常。 javaee-web-api 工件中的“实现”并不是真正的实现,它们错过了方法的主体。尝试执行此类方法时,结果就是此异常。
  • 它很可能与 JPA 异常类有关——它是一个完全正常的异常类。只有接口“错过了方法的主体”。
  • 在正常情况下,本地和抽象方法也往往会丢失正文。这种实现不是“完全正常的”。只需在 javax.persistence.TransactionRequiredException 的构造函数中查看字节码(当然是通过此依赖项,而不是其他一些实现),您就会明白。我认为“...的方法中的缺失代码属性”很好地描述了您将看到的内容
  • 您能否指出一个参考,指出 JPA api 类(以及其他 API 和 SPI)有一些仅通过编译源代码无法实现的自定义字节码?
  • 我没有这样的参考资料,也没有源代码,也没有关于它是如何编译的信息。如果你有,我也有兴趣拥有它。现在,当我们缺乏参考资料和来源时,我们可以改为检查结果(因为最终这很重要)。如果您不想自己检查,请查看:maunu.org/show/differences_PersistenceException.txt。你会在运行时发现这两个问题的区别。
【解决方案2】:

如果您使用 Tomcat 执行此操作,那么问题是什么,只需查看 BalusC 的评论即可。

你看到这个堆栈跟踪的原因是你得到的 javaee-web-api 依赖是一种你可以编译的骨架(只是公共接口)。背后没有任何真正的实现。这就是您尝试使用外观的示例类 javap -c TransactionRequiredException

Compiled from "TransactionRequiredException.java"
public class javax.persistence.TransactionRequiredException extends javax.persistence.PersistenceException{
public javax.persistence.TransactionRequiredException();

public javax.persistence.TransactionRequiredException(java.lang.String);

}

http://download.java.net/maven/2/javax/javaee-web-api/6.0/javaee-web-api-6.0.jar 文件中找到的任何类中也没有任何类型的返回指令。 您可以从

阅读使用此类库的其他实验

为这些类调用任何方法或构造函数都会失败。这意味着您可能永远不应该使用运行时来自此依赖项的任何内容。

  • 不适用于单元测试
  • 不适用于某些 Hibernate 生成

在单元测试期间使用 javax.persistence.TransactionRequiredException 的一些实际实现之前,现在它是来自新依赖项的空壳。

【讨论】:

    猜你喜欢
    • 2019-05-19
    • 2019-08-20
    • 2019-03-11
    • 1970-01-01
    • 2021-03-11
    • 2020-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多