【分享排雷經(jīng)歷】系統(tǒng)引入Apache-Tika產(chǎn)生的NoClassDefFoundError錯誤
今天,我們的重點工作是對monorepo系統(tǒng)的文件導(dǎo)入做安全控制,主要是通過判斷文件的擴展名和類型,來限定用戶導(dǎo)入文件的合法性,防止非法文件進(jìn)入系統(tǒng)造成風(fēng)險。
我們借用了此前在另一個系統(tǒng)zfquan基于Apache Tika的解決方案。
不巧,在運行main程序時,出現(xiàn)了一個 NoClassDefFoundError 錯誤-未找到Apache Commons IO(commons-io)類庫的一個class的定義。
20:25:14.667 [main] DEBUG org.apache.tika.config.TikaConfig - loading tika config from defaults; no config file specified
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/io/input/UnsynchronizedByteArrayInputStream
at org.apache.tika.config.TikaConfig.getDefaultMimeTypes(TikaConfig.java:317)
at org.apache.tika.config.TikaConfig.<init>(TikaConfig.java:246)
at org.apache.tika.config.TikaConfig.getDefaultConfig(TikaConfig.java:390)
at org.apache.tika.Tika.<init>(Tika.java:119)
at com.emax.zhenghe.common.util.TikaFileSecurityUtils.<init>(TikaFileSecurityUtils.java:20)
at com.emaxcard.car.TestMain.main(TestMain.java:38)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.io.input.UnsynchronizedByteArrayInputStream
at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
... 6 more
Process finished with exit code 1
NoClassDefFoundError(而不是 ClassNotFoundException) 表示編譯時類存在,但運行時找不到。
常見原因:
-
依賴未正確引入。
-
依賴沖突導(dǎo)致類加載失敗。
-
打包時遺漏了 commons-io.jar(如 maven-shade-plugin 未正確包含依賴)。
同樣的Tika,為什么搬到monorepo就不行了呢?
經(jīng)查maven依賴,monorepo系統(tǒng)與zfquan系統(tǒng)所依賴的 commons-io 的版本不同,zfquan是2.16.1,monorepo是2.6,這導(dǎo)致了問題的發(fā)生。
與單體結(jié)構(gòu)的zfquan所不同的是,monorepo是一個龐大的同時擁有基礎(chǔ)lib庫和上層應(yīng)用的工程。我們是在lib庫的 sby-component-dfs 包 中添加的Tika依賴。
我嘗試在其中一個應(yīng)用層pom里顯式添加 commons-io:2.16.1,是可以解決問題的。
但,monorepo有多達(dá)數(shù)十個應(yīng)用,我顯然不能在這么多應(yīng)用層里顯式添加 commons-io:2.16.1 依賴。而且,這不符合我們的系統(tǒng)開發(fā)規(guī)范————maven包依賴統(tǒng)一在頂層pom來管理。
那么,如何繼續(xù)解決呢?
通過應(yīng)用的maven依賴樹(dependency:tree)得知,commons-io:commons-io:jar:2.6 是直接作為頂層依賴引入的(沒有被其他庫傳遞依賴)
然后我在IDE中全局查找 <artifactId>commons-io</artifactId>,發(fā)現(xiàn)在頂層maven依賴管理文件 spring-base.pom 中,的確顯式定義了 commons-io 的版本號!
<properties>
...
<commons.version>2.6</commons.version>
</properties>
<dependencyManagement>
<dependencies>
...
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
如此,我把這個版本號變更為 2.16.1 ,也是可以解決問題的。
但,monorepo項目龐大,這樣可能會拆東墻補西墻————可能影響其他用到commons-io的系統(tǒng)功能。
so,我們得針對 Tika 版本來做文章,找到適配 commons-io:2.6 的版本。
DeepSeek很快給出答案:Tika 2.4.1依賴commons-io:2.6。開發(fā)者將 Tika 版本從 2.9.1 降級到 2.4.1,不再出現(xiàn)NoClassDefFoundError錯誤,并且經(jīng)測試,這個版本的Tika可以滿足我們對系統(tǒng)文件導(dǎo)入的安全控制。
當(dāng)看到一些不好的代碼時,會發(fā)現(xiàn)我還算優(yōu)秀;當(dāng)看到優(yōu)秀的代碼時,也才意識到持續(xù)學(xué)習(xí)的重要!--buguge
本文來自博客園,轉(zhuǎn)載請注明原文鏈接:http://www.rzrgm.cn/buguge/p/19027683
浙公網(wǎng)安備 33010602011771號