天天看點

關于WAS當中FFDC報告error in opening zip file剖析及解決 部落格分類: Java Strutslog4jIBM

閱讀更多

關于WAS當中FFDC報告java.util.zip.ZipException: error in opening zip file剖析及解決

問題:

WAS下FFDC日志目錄中出現如下的錯誤,打開zip檔案錯誤

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、打開跟蹤日志級别進行剖析

Application servers > memXXX > Logging and Tracing > Change log detail levels           

複制

設定ClassLoaderUtils跟蹤級别如下

*=info: com.ibm.ws.classloader.ClassLoaderUtils=finest           

複制

重新啟動後,在trace.log裡可以發現如下資訊

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]建議用前者進行解決。要麼就更新這些元件包。[/color]

代碼解讀

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[i].toLowerCase().endsWith(".jar"))
            addDependents(paths[i], 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也列印出來,就更容易知道是什麼問題了。

可見列印出有意義的資訊對于分析問題是多少的重要。。。

附帶資訊:将commons-logging.jar與struts.jar與Spring 2.5.5釋出所帶的包進行對比分析,發現Spring帶的commons-logging.jar包沒有帶有Class-Path這個條目。

Manifest-Version: 1.0
Created-By: Apache Ant 1.5.1
Extension-Name: org.apache.commons.logging
Specification-Vendor: Apache Software Foundation
Specification-Version: 1.0
Implementation-Vendor: Apache Software Foundation
Implementation-Version: 1.0.3
Class-Path: log4j.jar log4j-core.jar           

複制

對比

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: dlg01
Build-Jdk: 1.4.2_16
Implementation-Title: Commons Logging
Implementation-Vendor: Apache Software Foundation
Implementation-Vendor-Id: org.apache
Implementation-Version: 1.1.1
Specification-Title: Commons Logging
Specification-Vendor: Apache Software Foundation
Specification-Version: 1.0
X-Compile-Source-JDK: 1.2
X-Compile-Target-JDK: 1.1
Extension-Name: org.apache.commons.logging           

複制

注意實作的版本問題是不同的

struct.jar包的條目内容不同

Manifest-Version: 1.0
Created-By: Apache Ant 1.5.1
Extension-Name: Struts Framework
Specification-Title: Struts Framework
Specification-Vendor: Apache Software Foundation
Specification-Version: 1.1
Implementation-Title: Struts Framework
Implementation-Vendor: Apache Software Foundation
Implementation-Vendor-Id: org.apache
Implementation-Version: 1.1
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           

複制

對比

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.6.1
Created-By: 1.3.1_04-b02 (Sun Microsystems Inc.)
Extension-Name: Struts Framework
Specification-Title: Struts Framework
Specification-Vendor: The Apache Software Foundation
Specification-Version: 1.2.9
Implementation-Title: Struts Framework
Implementation-Vendor: The Apache Software Foundation
Implementation-Vendor-Id: org.apache
Implementation-Version: 1.2.9
Class-Path:  commons-beanutils.jar commons-digester.jar commons-fileup
 load.jar commons-logging.jar commons-validator.jar jakarta-oro.jar           

複制

也要注意實作的版本問題是不同的