在一次项目启动中,碰着了一个报错
"java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log"
简朴Google一下,是jar包斗嘴的问题。
凭据网上的思路,首先查察mvn中斗嘴的包
利用呼吁:
mvn dependency:tree -Dverbose | grep "omitted for conflict with”
凡是上面的显示的信息很是多,假如已经明晰了斗嘴的包,好比本场景下是log4j/slf4j
利用呼吁:
mvn dependency:tree -Dverbose -Dincludes=log4j:log4j
详细查察pom文件,修改斗嘴的包。
把一些明明的斗嘴修改了今后,再次启动,仍然报错,报错信息变了:
Exception in thread "main" java.lang.IllegalAccessError: tried to access field org.slf4j.impl.StaticLoggerBinder.SINGLETON from class org.slf4j.LoggerFactory at org.slf4j.LoggerFactory.<clinit>(LoggerFactory.java:60)
通过Google找到原因如下:
是由于低版本的slf4j的bug,详细原因查察这个Blog,按理说找到对应的pom设置,进级下version就可以了。
但是我将pom中的slf4j-api和slf4j-log4j12进级到1.7+,仍然报同样的错误。
查察当地M2_REPO,将低版本的slf4j-api和slf4j-log4j12删除,软件开发,仍然报同样的错。
开始猜疑是从其他jar包中加载了LoggerFactory。
如何查察一个类加载的来历信息呢?
VM的-verbose参数办理了这个问题
-verbose[:class|gc|jni] 在输出设备上显示虚拟机运行信息。
在措施运行的时候有几多类被加载!你可以用verbose:class来监督,在呼吁行输入java -verbose:class XXX (XXX为措施名)你会在节制台看到加载的类的环境。
verbose和verbose:class寄义沟通,输出虚拟机装入的类的信息,显示的信息名目如下:
[Opened D:\Java\jdk1.6.0_25\jre\lib\rt.jar] [Loaded java.lang.Object from D:\Java\jdk1.6.0_25\jre\lib\rt.jar] [Loaded java.io.Serializable from D:\Java\jdk1.6.0_25\jre\lib\rt.jar] [Loaded java.lang.Comparable from D:\Java\jdk1.6.0_25\jre\lib\rt.jar] [Loaded java.lang.CharSequence from D:\Java\jdk1.6.0_25\jre\lib\rt.jar] [Loaded java.lang.String from D:\Java\jdk1.6.0_25\jre\lib\rt.jar] [Loaded java.lang.reflect.GenericDeclaration from D:\Java\jdk1.6.0_25\jre\lib\rt.jar] [Loaded java.lang.reflect.Type from D:\Java\jdk1.6.0_25\jre\lib\rt.jar] [Loaded java.lang.reflect.AnnotatedElement from D:\Java\jdk1.6.0_25\jre\lib\rt.jar] [Loaded java.lang.Class from D:\Java\jdk1.6.0_25\jre\lib\rt.jar] [Loaded java.lang.Cloneable from D:\Java\jdk1.6.0_25\jre\lib\rt.jar] [Loaded java.lang.ClassLoader from D:\Java\jdk1.6.0_25\jre\lib\rt.jar] [Loaded java.lang.System from D:\Java\jdk1.6.0_25\jre\lib\rt.jar] [Loaded java.lang.Throwable from D:\Java\jdk1.6.0_25\jre\lib\rt.jar]
当虚拟机陈诉类找不到或类斗嘴时可用此参数来诊断来查察虚拟机从装入类的环境。
在本场景排盘查题时,发明类LoggerFactory加载来历于com.springsource.slf4j.api,将对应的jar包移除,问题办理。
值得留意的是,-verbose参数在jvm妨碍诊断时同样有着重要的浸染
java –verbose:gc
在虚拟机产生内存接纳时在输出设备显示信息,名目如下:
[Full GC 256K->160K(124096K), 0.0042708 secs]
该参数用来监督虚拟机内存接纳的环境。
public class JvmVerbose { /** * JVM -verbose[:class|gc|jni] 参数测试 * @param args */ public static void main(String[] args) { JvmVerbose jvmVerbose = new JvmVerbose(); System.gc(); } }
在这个例子中,一个新的工具被建设,由于它没有利用,所以该工具迅速地变为可达,措施编译后,执行呼吁:
java -verbose:gc JvmVerbose
功效:
[GC 647K->256K(124096K), 0.0274253 secs] [Full GC 256K->160K(124096K), 0.0042708 secs]
箭头前后的数据256K和160K别离暗示垃圾收集GC前后所有存活工具利用的内存容量,说明有256K-160K=96K的工具容量被接纳,括号内的数据124096K为堆内存的总容量,劳务派遣管理系统,收集所需要的时间是0.0042708秒(这个时间在每次执行的时候会有所差异)。
java –verbose:jni
-verbose:jni输出native要领挪用的相关环境,一般用于诊断jni挪用错误信息。
在虚拟机挪用native要领时输出设备显示信息,名目如下:
[Dynamic-linking native method java.lang.Object.registerNatives ... JNI]
该参数用来监督虚拟机挪用当处所法的环境,劳务派遣管理系统,在产生jni错误时可为诊断提供便利。
Reference: