maven增量編譯


 最近由於不清楚maven(2.2.x)增量編譯的機制,導致應用出現了一個當時覺得非常詭異的一個問題。先描述一下問題。

    背景是應用A有一個公用的base包,版本為1.6.6-SNAPSHOT,應用B依賴於這個公用的base包。我在base包中修改了一個字符串變量的值,該變量是一個緩存的key(如下面代碼的Constants類,中的CACHE_KEY)。然后使用mvn deploy 命令把base包上傳到中心庫中。出現的問題是應用B打包部署,應用上線后,使用后台功能刪除"cache.key.new"對應的緩存值,提示刪除成功。但是前台展示的還是老的值(前台展示取的數據是從緩存取出的,簡化代碼后,參考下面的CategoryManager的showCategory()方法,根據key在緩存中取出值,然后前台展示)。
 
?
 
  public Interface Constants{
        public interface Cache{
            String CACHE_KEY = “cache.key.new”;//舊值為"cache.key"
    }
}

 

public Class CategoryManager{
    private static Map<int, String> keyMaps = new HashMap<String, String>();
        static {
             keyMaps.put(1, Constants. Cache. CACHE_KEY);//把緩存的key存到map中
             .........
    }
 
        public Object showCategory(){
            return  cacheManager.get(keyMaps.get(1));//在緩存中獲取數據
        }
}
 
    一開始懷疑是包沒有成功deploy到中心庫中,然后在中心庫中把1.6.6-SNAPSHOT的源碼包拉了下來,發現里面的代碼是新的。
    我的印象中deploy是maven生命周期的最后一步,執行deploy命令是會執行compile編譯操作的,當時懷疑自己記錯了,以為base包deploy的時候沒有走到compile,就把包發到中心庫中了,后續把base包的1.6.6-SNAPSHOT的編譯后的文件拉下來,並且反編譯Constants類,發現CACHE_KEY的確是新的值"cache.key.new",證明這塊是被重新編譯過了。(后續翻閱了下資料” http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html maven生命周期“發現自己記的的確沒錯)
    最后把CategoryManager.class反編譯過來一看,發現里面的部分代碼是這樣的:
 
?
 
    public Class CategoryManager{
    private static Map<int, String> keyMaps = new HashMap<String, String>();
        static {
             keyMaps.put(1, "cache.key");//問題出在這里,這個"cache.key"沒有替換成新的值"cache.key.new"
             .........
    }
........
}

 

    發現問題了,這里的"cache.key"並沒有替換成新值。也就是說CategoryManager類並沒有重新編譯。這里的原因是maven的增量編譯機制。
    后續找了些資料表明,默認情況下maven是增量編譯的,maven在編譯的時候會先去比較源文件(.java)文件的修改時間和對應類文件(.class)的修改時間,如果源文件的修改時間比類文件的修改時間要晚的話,重新編譯原文件否則不做處理(另外,如果刪除了一個java文件,對應的class文件在增量編譯時是不會被移除的)。
    在這里CategoryManager的源文件並沒有發生過改變,所以不會重新編譯。並且這個地方恰好是靜態代碼塊,這段代碼  keyMaps.put(1, Constants. Cache. CACHE_KEY); 編譯時直接被替換成 keyMaps.put(1, "cache.key"); ,如果是在非靜態代碼塊里面使用的話,這塊地方是不會出問題的。所以之前一直使用mvn deploy都沒有出現過問題。
    那要怎么避免這個問題呢,使用mvn clean deploy。clean會做一些清理的工作,包括移除上一次構建的文件。這樣就能很好的解決這個問題了。
 
參考:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM