【tstt 專案筆記】WAR 包中出現舊 .class 文件的原因與解決方案

| Work Notes | 6 Reads

最近在 tstt 專案的編譯過程中遇到一個比較隱蔽的問題:
雖然 target 下已經正確生成了 WAR 包,但檢查後發現,某些代碼更新後並沒有在最終包裡生效,反而出現了舊的 .class 文件覆蓋新編譯結果的情況。


Maven 專案中殘留 .class 文件問題的根治方案

在 Java 專案開發中,我曾經遇到過一個非常棘手的問題:即使修改了源碼,Maven 編譯後的輸出仍然存在舊的 .class 文件,導致運行時出現明明代碼已修改卻無效的情況。這個問題困擾了我很久,最終我通過修改 pom.xml 找到了一個徹底的解決方法。


問題背景

Maven 在默認情況下會使用增量編譯(Incremental Compilation):

  • 如果某些 .java 檔案沒有變更,它對應的 .class 檔案就不會被重新編譯。

  • 這本意是提升編譯速度,但在某些情況下會導致舊的 .class 殘留,特別是:

    • 調整過 package 結構;

    • 刪除過類文件;

    • 或者修改過注解處理、代碼生成邏輯。

這些舊 .class 文件會干擾執行,造成難以排查的 bug。


解決方案

1. 關閉增量編譯

pom.xmlmaven-compiler-plugin 配置中加入:

<configuration>
    <source>${maven.compiler.source}</source>
    <target>${maven.compiler.target}</target>
    <encoding>${project.build.sourceEncoding}</encoding>
    
    <!-- Disable incremental compilation so changes to existing sources always trigger a rebuild -->
    <useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>

這樣每次編譯都會強制全量重建,避免舊 .class 殘留。


2. 過濾掉 WEB-INF 下的舊 class 文件

有時候 Web 專案會在 src/main/webapp/WEB-INF/classes/ 下殘留已經編譯好的 .class 文件。
我新增了如下配置來忽略它們:

<!-- Ignore any precompiled classes under src/main/webapp/WEB-INF/classes -->
<warSourceExcludes>WEB-INF/classes/**</warSourceExcludes>

這樣打包 WAR 檔時就不會把舊 .class 一併帶進去。


最終效果

通過這兩個關鍵改動,我徹底解決了 Maven 專案中 .class 文件殘留干擾新代碼 的問題。

  • 修改後的代碼能立即生效;

  • 打包的 WAR 不再包含任何歷史遺留的編譯產物;

  • 雖然編譯時間略有增加,但換來的是乾淨、可控的構建結果。


總結

有時候我們追求編譯速度,但忽略了乾淨構建的重要性。對於存在頻繁調整、歷史包袱較重的專案,禁用增量編譯 + 過濾 WEB-INF/classes 是一個務實可靠的做法。

希望這篇文章能幫到和我有同樣困擾的朋友 🙌。

This article was last edited at