关于WAS当中FFDC报告java.util.zip.ZipException: error in opening zip file剖析及解决
问题:
WAS下FFDC日志目录中出现如下的错误,打开zip文件错误
Java代码
- FFDC Exception:java.util.zip.ZipException SourceId:com.ibm.ws.classloader.ClassLoaderUtils.addDependents ProbeId:238 Reporter:java.lang.Class@7c537c91
- java.util.zip.ZipException: error in opening zip file
- at java.util.zip.ZipFile.open(Native Method)
- at java.util.zip.ZipFile.<init>(ZipFile.java:114)
- at java.util.jar.JarFile.<init>(JarFile.java:133)
- at java.util.jar.JarFile.<init>(JarFile.java:70)
- at com.ibm.ws.classloader.ClassLoaderUtils.addDependents(ClassLoaderUtils.java:96)
- at com.ibm.ws.classloader.ClassLoaderUtils.addDependents(ClassLoaderUtils.java:143)
- at com.ibm.ws.classloader.ClassLoaderUtils.addDependentJars(ClassLoaderUtils.java:61)
- at com.ibm.ws.classloader.ClassGraph.<init>(ClassGraph.java:115)
- at com.ibm.ws.classloader.ClassLoaderManager.initialize(ClassLoaderManager.java:202)
- at com.ibm.ws.classloader.ClassLoaderManager.<init>(ClassLoaderManager.java:166)
- at com.ibm.ws.runtime.component.DeployedApplicationImpl.start(DeployedApplicationImpl.java:891)
- at com.ibm.ws.runtime.component.ApplicationMgrImpl.startApplication(ApplicationMgrImpl.java:740)
- at com.ibm.ws.runtime.component.ApplicationMgrImpl.start(ApplicationMgrImpl.java:2092)
- at com.ibm.ws.runtime.component.CompositionUnitMgrImpl.start(CompositionUnitMgrImpl.java:437)
- at com.ibm.ws.runtime.component.CompositionUnitImpl.start(CompositionUnitImpl.java:122)
- at com.ibm.ws.runtime.component.CompositionUnitMgrImpl.start(CompositionUnitMgrImpl.java:380)
- at com.ibm.ws.runtime.component.CompositionUnitMgrImpl.access$300(CompositionUnitMgrImpl.java:105)
- at com.ibm.ws.runtime.component.CompositionUnitMgrImpl$CUInitializer.run(CompositionUnitMgrImpl.java:928)
- at com.ibm.wsspi.runtime.component.WsComponentImpl$_AsynchInitializer.run(WsComponentImpl.java:349)
- at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1527)
那到底是哪个文件在打开时发生错误了呢?一头雾水了吧,汗。。。估计你会。。。
分析:
1、通过对文件的排查,确认排除了应用程序中引用jar文件损坏的可能性以及由于jar文件权限设置导致无法读取的可能性
2、打开跟踪日志级别进行剖析
Java代码
- Application servers > memXXX > Logging and Tracing > Change log detail levels
设置ClassLoaderUtils跟踪级别如下
Java代码
- *=info: com.ibm.ws.classloader.ClassLoaderUtils=finest
重新启动后,在trace.log里可以发现如下信息
Java代码
- 0000001e ClassLoaderUt > addDependents Entry
- /home/xxx/lib/struts/commons-logging.jar
- 0000001e ClassLoaderUt 3 dependent classpath detected: log4j.jar log4j-core.jar
- 0000001e ClassLoaderUt 3 adding /home/xxx/lib/struts/log4j.jar
- 0000001e ClassLoaderUt > addDependents Entry
- /home/xxx/lib/struts/log4j.jar
- 0000001e FfdcProvider I com.ibm.ws.ffdc.impl.FfdcProvider logIncident FFDC1003I: FFDC Incident emitted on /usr/IBM/WebSphere/AppServer/profiles/XXX/logs/ffdc/memXXX_f3c3750_08.12.23_16.26.42.85048008.txt com.ibm.ws.classloader.ClassLoaderUtils.addDependents 238
- 0000001e ClassLoaderUt 3 WARNING: could not open /home/xxx/lib/struts/log4j.jar : error in opening zip file
- 0000001e ClassLoaderUt < addDependents Exit
- /home/xxx/lib/struts/log4j.jar
- 0000001e ClassLoaderUt 3 adding /home/xxx/lib/struts/log4j-core.jar
- 0000001e ClassLoaderUt > addDependents Entry
- /home/xxx/lib/struts/log4j-core.jar
- 0000001e ClassLoaderUt 3 WARNING: could not open /home/xxx/lib/struts/log4j-core.jar : error in opening zip file
- 0000001e ClassLoaderUt < addDependents Exit
- /home/xxx/lib/struts/log4j-core.jar
- 0000001e ClassLoaderUt < addDependents Exit
- /home/xxx/lib/struts/commons-logging.jar
- ......
- 0000001e ClassLoaderUt > addDependents Entry
- /home/xxx/lib/struts/struts.jar
- 0000001e ClassLoaderUt 3 dependent classpath detected: commons-beanutils.jar commons-collections.jar commons-digester.jar commons-logging.jar commons-validator.jar jakarta-oro.jar struts-legacy.jar
- 0000001e ClassLoaderUt 3 adding /home/xxx/lib/struts/jakarta-oro.jar
- 0000001e ClassLoaderUt > addDependents Entry
- /home/xxx/lib/struts/jakarta-oro.jar
- 0000001e ClassLoaderUt 3 WARNING: could not open /home/xxx/lib/struts/jakarta-oro.jar : error in opening zip file
- 0000001e ClassLoaderUt < addDependents Exit
- /home/xxx/lib/struts/jakarta-oro.jar
- 0000001e ClassLoaderUt 3 adding /home/xxx/lib/struts/struts-legacy.jar
- 0000001e ClassLoaderUt > addDependents Entry
- /home/xxx/lib/struts/struts-legacy.jar
- 0000001e ClassLoaderUt 3 WARNING: could not open /home/xxx/lib/struts/struts-legacy.jar : error in opening zip file
- 0000001e ClassLoaderUt < addDependents Exit
- /home/xxx/lib/struts/struts-legacy.jar
- 0000001e ClassLoaderUt < addDependents Exit
- ......
继续分析:
首先,可以确认的是WARNING所报的是正确的,因为可以通过确认所依赖的log4j.jar log4j-core.jar jakarta-oro.jar struts-legacy.jar之类的文件不存在。
其次,这些不存在的包是由谁依赖并需要加载的,通过日志的层次关系可以知道,commons-logging.jar需要log4j.jar log4j-core.jar,struts.jar需要jakarta-oro.jar struts-legacy.jar
这样唯一的可能就是各自的jar包中META-INF\MANIFEST.MF里声明了这些jar的依赖关系了。
打开commons-logging.jar,发现其中的META-INF\MANIFEST.MF里包含了
Class-Path: log4j.jar log4j-core.jar
打开struts.jar,发现其中的META-INF\MANIFEST.MF里包含了
Class-Path: commons-beanutils.jar commons-collections.jar commons-dig
ester.jar commons-logging.jar commons-validator.jar jakarta-oro.jar s
truts-legacy.jar
于是真相大白了,解决的办法要么增加相应版本所依赖的jar包,要么就是简单地删除Class-Path,根据应用程序的需要进行确认并使用之,[
color=red]建议用前者进行解决。要么就升级这些组件包。
代码解读
Java代码
- ClassLoaderUtils.java
public static String[] addDependentJars(String paths[]) - {
- ArrayList newPaths = new ArrayList(Arrays.asList(paths));
- for(int i = 0; i < paths.length; i++)
- if(paths.toLowerCase().endsWith(".jar"))
- addDependents(paths, newPaths);
-
- String result[] = new String[newPaths.size()];
- result = (String[])(String[])newPaths.toArray(result);
- return result;
- }
-
private static void addDependents(String jarFileName, List classpath) - {
// ...省略。。。 - jar = new JarFile(jarFileName);// 错误在这一行
- manifest = jar.getManifest();
- attrs = manifest.getMainAttributes();
- dependents = attrs.getValue(java.util.jar.Attributes.Name.CLASS_PATH);// 获取依赖包路径
- StringTokenizer tokens = new StringTokenizer(dependents, " ");
do - {
- if(!tokens.hasMoreTokens())
- break;
- String nextDependent = tokens.nextToken();
- String nextDependentFullPath = (new StringBuilder()).append(prefix).append(nextDependent).
- if(PathUtils.listAddNoDup(classpath, nextDependentFullPath))
- {
- addDependents(nextDependentFullPath, classpath); // 迭代加载之
- }
- } while(true);
// ...省略。。。 - 在catch代码块中
catch(ZipException ze) - {
- Manager.Ffdc.log(ze, ClassLoaderUtils.class, "com.ibm.ws.classloader.ClassLoaderUtils.addDependents", "238" + jarFileName);
- if(debugEnabled)
- Tr.debug(tc, (new StringBuilder()).append("WARNING: could not open ").append(jarFileName).append(" : ").append(ze.getLocalizedMessage()).toString());
- }
catch(IOException ioe) - {
- Manager.Ffdc.log(ioe, ClassLoaderUtils.class, "com.ibm.ws.classloader.ClassLoaderUtils.addDependents", "246");
- if(debugEnabled)
- Tr.debug(tc, (new StringBuilder()).append("WARNING: I/O exception ").append(jarFileName).append(" : ").append(ioe.getLocalizedMessage()).toString());
- }
不厚道,在Manager.Ffdc.log里把jarFileName也打印出来,就更容易知道是什么问题了。
可见打印出有意义的信息对于分析问题是多少的重要。。。