记录一下项目部署在weblogic发生的java.lang.NoSuchMethodError: javax.persistence.Table.indexes()异常。
项目在tomcat中运行正常。部署到 weblogic12c时,运行报错。
Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: javax.persistence.Table.indexes()[Ljavax/persistence/Index;
排错记录
首先,在我们自己项目中搜索 javax.persistence.Table
类,发现其存在于 hibernate-jpa-2.1-api-1.0.0.Final.jar 包中。查看其类文件,发现其有定义 indexs()
方法。
我们可以确定,在weblogic环境中,项目运行时加载的 javax.persistence.Table
类并不是我们项目中提供的,可能来源于weblogic本身的类库。虽然包名类名相同,可能版本不同,导致其定义不同,缺少了 indexs() 方法。
那么,我们只要保证我们需要的类始终都从项目的类库加载,就不会出问题。
当程序需要加载一个类时,weblogic默认的类加载机制是会优先在weblogic本身的类库中查找,找到了就返回该class,找不到才会在web项目的类库中查找。
好在weblogic提供了一种方式,可以通过weblogic.xml配置文件显式配置哪些类优先从项目中加载。
解决办法
在项目 WEB-INF目录下新建一个 weblogic.xml 文件,内容如下:(更多配置项,详见文末参考链接)
配置说明了,在javax.persistence包下的类优先从 项目中加载。即可解决上述问题。
<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app">
<container-descriptor>
<!-- 该包名下的类,优先从项目中加载 -->
<prefer-application-packages>
<package-name>javax.persistence</package-name>
<package-name>org.hibernate.jpa.internal</package-name>
</prefer-application-packages>
</container-descriptor>
</weblogic-web-app>
另附:
其实问题到这已经解决了,不过总感觉少了点什么,我们好像还不知道从哪来的Table类导致了错误。
这里只提供方法:
方法1:通过 java提供的-verbose:class
运行参数,能够显示类的加载路径。
修改 opt/Oracle/Middleware/user_projects/domains/base_domain/bin/setDomainEnv.sh,
在文件顶部添加一行内容:JAVA_OPTIONS="$JAVA_OPTIONS -verbose:class"
。
重启weblogic,即可在日志查看具体的类加载信息。
方式2:通过weblogic自带的类加载分析工具 Classloader Analysis Tool
具体使用参考此文档:
https://blogs.perficient.com/2012/10/19/an-introduction-to-weblogic-server-classloader-analysis-tool/
https://docs.oracle.com/middleware/12213/wls/WLPRG/classloading.htm#WLPRG495
reference:
Weblogic 类加载分析工具
理解 WebLogic 类加载机制
weblogic.xml 配置文档
WebLogic 类加载错误帮助文档
WebLogic 各版本
WebLogic 8.1文档