1、环境说明
1、jdk1.8
2、spring3
2、问题现象
原来部署在centos 服务器上是可以跑得,后面迁移到麒麟 V10上,启动报如下错误:
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.jbpm.api.ProcessEngine org.jbpm.pvm.internal.processengine.SpringHelper.createProcessEngine()] threw exception; nested exception is java.lang.NoSuchMethodError: org.apache.log4j.Logger.trace(Ljava/lang/Object;)V
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:561)
... 55 more
Caused by: java.lang.NoSuchMethodError: org.apache.log4j.Logger.trace(Ljava/lang/Object;)V
at org.jbpm.internal.log.Log4jLog.trace(Log4jLog.java:74)
at org.jbpm.pvm.internal.wire.xml.WireParser.<clinit>(WireParser.java:289)
at org.jbpm.pvm.internal.cfg.ConfigurationParser.<init>(ConfigurationParser.java:46)
at org.jbpm.pvm.internal.cfg.ConfigurationParser.<clinit>(ConfigurationParser.java:49)
at org.jbpm.pvm.internal.cfg.ConfigurationImpl.parse(ConfigurationImpl.java:137)
at org.jbpm.pvm.internal.cfg.ConfigurationImpl.setResource(ConfigurationImpl.java:116)
at org.jbpm.pvm.internal.processengine.SpringHelper.createProcessEngine(SpringHelper.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:142)
... 56 more
3、处理思路
因为该服务原来在centos 上是可以跑的,所以代码是没有问题的,那为什么迁移到麒麟上会出现找不到方法的错误呢,java.lang.NoSuchMethodError: org.apache.log4j.Logger.trace(Ljava/lang/Object;)V,这种情况应该是版本冲突导致的,要怎么处理呢,首先我在想一定要找到这个类,看下这个类出自哪个包,但是这个服务我们是没有源码的,只有部署包,这时我想到arthas这个工具,它可以在运行环境反编译类,ok ,让我们来看看查找过程。
4、查找过程
1、先来看看原来环境的类:
jad org.apache.log4j.Logger
因为存在多个相同的类,会列出多个
2、可以用另外一个命令
jad -c 4967288a org.apache.log4j.Logger
ClassLoader:
+-ModuleClassLoader for Module "deployment.jbpm-rest-standalone-1.3.0.war:main" from Service Module Loader
+-sun.misc.Launcher$AppClassLoader@58644d46
+-sun.misc.Launcher$ExtClassLoader@b7f23d9
Location:
/content/jbpm-rest-standalone-1.3.0.war/WEB-INF/lib/log4j-over-slf4j-1.7.21.jar
/*
* Decompiled with CFR.
*
* Could not load the following classes:
* org.apache.log4j.Category
* org.apache.log4j.Log4jLoggerFactory
* org.apache.log4j.spi.LoggerFactory
*/
package org.apache.log4j;
import org.apache.log4j.Category;
import org.apache.log4j.Log4jLoggerFactory;
import org.apache.log4j.spi.LoggerFactory;
public class Logger
extends Category {
private static final String LOGGER_FQCN = Logger.class.getName();
protected Logger(String name) {
/*37*/ super(name);
}
public static Logger getLogger(String name) {
/*41*/ return Log4jLoggerFactory.getLogger((String)name);
}
public static Logger getLogger(String name, LoggerFactory loggerFactory) {
/*45*/ return Log4jLoggerFactory.getLogger((String)name, (LoggerFactory)loggerFactory);
}
public static Logger getLogger(Class clazz) {
/*49*/ return Logger.getLogger(clazz.getName());
}
public static Logger getRootLogger() {
/*58*/ return Log4jLoggerFactory.getLogger((String)"ROOT");
}
public boolean isTraceEnabled() {
/*66*/ return this.slf4jLogger.isTraceEnabled();
}
public void trace(Object message) {
/*73*/ this.differentiatedLog(null, LOGGER_FQCN, 0, message, null);
}
public void trace(Object message, Throwable t) {
/*81*/ this.differentiatedLog(null, LOGGER_FQCN, 0, message, null);
}
}
查了三个类都有 public void trace(Object message)这个方法,注意这边会同时列出来在哪个包。
3、在麒麟环境查找
找到一个没有 public void trace(Object message)这个方法的类,存在于/content/yna_report_temp_tianwen_linux.ear/yna_report_war-1.0.war/WEB-INF/lib/log4j_128-1.0.jar这个包里。哈哈,找到问题原因啦,是因为版本冲突了,在麒麟环境加载了另外一个版本的log4j
ClassLoader:
+-ModuleClassLoader for Module "deployment.yna_report_temp_tianwen_linux.ear.yna_report_war-1.0.war:main" from Service Module Loader
+-sun.misc.Launcher$AppClassLoader@18b4aac2
+-sun.misc.Launcher$ExtClassLoader@516be40f
Location:
/content/yna_report_temp_tianwen_linux.ear/yna_report_war-1.0.war/WEB-INF/lib/log4j_128-1.0.jar
/*
* Decompiled with CFR.
*
* Could not load the following classes:
* org.apache.log4j.Category
* org.apache.log4j.LogManager
* org.apache.log4j.spi.LoggerFactory
*/
package org.apache.log4j;
import org.apache.log4j.Category;
import org.apache.log4j.LogManager;
import org.apache.log4j.spi.LoggerFactory;
public class Logger
extends Category {
private static final String FQCN = (class$org$apache$log4j$Level == null ? (class$org$apache$log4j$Level = Logger.class$("org.apache.log4j.Level")) : class$org$apache$log4j$Level).getName();
static /* synthetic */ Class class$org$apache$log4j$Level;
protected Logger(String name) {
/* 30*/ super(name);
}
public static Logger getLogger(String name) {
/* 85*/ return LogManager.getLogger((String)name);
}
public static Logger getLogger(Class clazz) {
/* 94*/ return LogManager.getLogger((String)clazz.getName());
}
public static Logger getRootLogger() {
/*104*/ return LogManager.getRootLogger();
}
public static Logger getLogger(String name, LoggerFactory factory) {
/*124*/ return LogManager.getLogger((String)name, (LoggerFactory)factory);
}
static /* synthetic */ Class class$(String x0) {
try {
/* 25*/ return Class.forName(x0);
}
catch (ClassNotFoundException x1) {
throw new NoClassDefFoundError(x1.getMessage());
}
}
}
5、处理过程
删除低版本的jar就可以了。