NoClassDefFoundError有時不是class找不到,而是其他問題
java.lang.NoClassDefFoundError, 一般只認為是因為某個class找不到, 但其實很多時候class是存在的, 而是在初始這個類的時候出現錯誤, 特別是static區塊出錯的時候, 這就必須深入這個類去除錯, 才能解決問題.
另外ClassLoader載入class出錯, 也會報java.lang.NoClassDefFoundError的錯誤
(The ClassLoader ran into an error while reading the class definition when trying to read the class. Put a try/catch inside your static initializer and look at the exception. )
使用try catch找出錯誤
static {
try {
... your init code here
} catch (Throwable t) {
LOG.error("Failure during static initialization", t);
throw t;
}
}
而 ClassNotFoundException 比較可能是單純的class找不到的情況
以下這一篇個人認為講的還不錯
關於NoClassDefFoundError和ClassNotFoundException異常
2016/05/31 update
出現 NoClassDefFoundError : org.apache.tika.parse.xml.DcXMLParser
org.apache.tika.parse.xml.DcXMLParser明明是存在的, 所以深入追踪原始碼:
EpubParser epubParser = null; if (type.equals("epub")) {
//NoClassDefFoundError出現在下面這一行
epubParser = new EpubParser();
epubParser.parse(inputstream, handler, metadata, pcontext);
}
找到 EpubParser 的原始碼:
public class EpubParser extends AbstractParser { private static final long serialVersionUID = 215176772484050550L; private static final SetSUPPORTED_TYPES = Collections.unmodifiableSet(new HashSet(Arrays.asList
(new MediaType[]{MediaType.application("epub+zip"),MediaType.application("x-ibooks+zip")})));
//DcXMLParser 找不到 private Parser meta = new DcXMLParser();private Parser content = new EpubContentParser(); public EpubParser() { } public Parser getMetaParser() { return this.meta; } public void setMetaParser(Parser meta) { this.meta = meta; } public Parser getContentParser() { return this.content; } public void setContentParser(Parser content) { this.content = content; } public SetgetSupportedTypes(ParseContext context) { // 在這一行出錯, 但這是最後一行返回值, 可見不是這一行的原因, 而是上//方定義 private Parser meta = new DcXMLParser();時出錯 return SUPPORTED_TYPES; }找出 DcXMLParser 的原始碼:
原來是下面有幾個import的元件未加入library中,
將未加入的部分加入就解決了
import org.apache.tika.metadata.Metadata; import org.apache.tika.metadata.Property; import org.apache.tika.metadata.TikaCoreProperties; import org.apache.tika.parser.ParseContext; import org.apache.tika.parser.xml.ElementMetadataHandler; import org.apache.tika.parser.xml.XMLParser; import org.apache.tika.sax.TeeContentHandler; import org.xml.sax.ContentHandler; public class DcXMLParser extends XMLParser { private static final long serialVersionUID = 4905318835463880819L; public DcXMLParser() { } private static ContentHandler getDublinCoreHandler(Metadata metadata, Property property, String element) { return new ElementMetadataHandler("http://purl.org/dc/elements/1.1/", element, metadata, property); } protected ContentHandler getContentHandler(ContentHandler handler, Metadata metadata, ParseContext context) { return new TeeContentHandler(new ContentHandler[]{super.getContentHandler(handler, metadata, context), getDublinCoreHandler(metadata, TikaCoreProperties.TITLE, "title"), getDublinCoreHandler(metadata, TikaCoreProperties.KEYWORDS, "subject"), getDublinCoreHandler(metadata, TikaCoreProperties.CREATOR, "creator"), getDublinCoreHandler(metadata, TikaCoreProperties.DESCRIPTION, "description"), getDublinCoreHandler(metadata, TikaCoreProperties.PUBLISHER, "publisher"), getDublinCoreHandler(metadata, TikaCoreProperties.CONTRIBUTOR, "contributor"), getDublinCoreHandler(metadata, TikaCoreProperties.CREATED, "date"), getDublinCoreHandler(metadata, TikaCoreProperties.TYPE, "type"), getDublinCoreHandler(metadata, TikaCoreProperties.FORMAT, "format"), getDublinCoreHandler(metadata, TikaCoreProperties.IDENTIFIER, "identifier"), getDublinCoreHandler(metadata, TikaCoreProperties.LANGUAGE, "language"), getDublinCoreHandler(metadata, TikaCoreProperties.RIGHTS, "rights")}); } }
2016/06/01 update
令天又遇到一個 NoClassDefFoundError 的問題
基本上與昨天遇到的問題差不多, 同樣是 import 的地方沒把 class 加進來而出問題.
但今天的問題, 即使把 import 的地方的 class 加進來, 一樣報錯.
報 NoClassDefFoundError 的錯誤的是這個 org.apache.tika.io.TikaInputStream class追踪TikaInputStream 的原始碼:
package org.apache.tika.io; //以下三個 import 的class 都加入了, 仍然報錯 import org.apache.tika.io.TaggedInputStream; import org.apache.tika.io.TemporaryResources; import org.apache.tika.metadata.Metadata; //原來問題出在 TaggedInputStream , 因為 TikaInputStream 是繼承 TaggedInputStream//所以要把 TaggedInputStream 的原始碼也挖出來看public class TikaInputStream extends TaggedInputStream { private static final int BLOB_SIZE_THRESHOLD = 1048576; private Path path; private final TemporaryResources tmp; private long length; private long position = 0L;//TikaInputStream 以下原始碼省略...
}TaggedInputStream 的原始碼:
//把以下兩個 class 加入(ProxyInputStream及TaggedIOException), 就解決了,//所以不止看出問題的 class, 如果它繼承自別的 class , 連父類的 class//也要查看是否有import 的 class 未加入.import org.apache.tika.io.ProxyInputStream; import org.apache.tika.io.TaggedIOException; public class TaggedInputStream extends ProxyInputStream { private final Serializable tag = UUID.randomUUID(); public TaggedInputStream(InputStream proxy) { super(proxy); }還有一種情況:所有的 import 都己加入 library 中, 但在程碼中, 卻直接引用
class 如下面的 org.apache.xmlbeans.SchemaComponent.Ref 也要加進來public void setContainerFieldRef(org.apache.xmlbeans.SchemaComponent.Ref ref) { this.assertUnresolved(); this._containerFieldRef = ref; this._containerFieldCode = 0; }