我有一個我們寫的內部工具來爲我們的應用程序創建補丁。 它在scm中檢查哪些類已更改並使用javac
進行編譯。
然後我們將創建的jar添加到類路徑中。 在過去,我們發現有一個問題: 如果我改變了A類中的方法返回類型,並且B類使用了那個方法,那麼A類簽名改變了,當B類調用該方法時,我們得到NoSuchMethodError
。
但是,現在我有一個不同的情況,類靜態變量發生了變化,我得到: java.lang.NoClassDefFoundError: Could not initialize class
。
你知道這是什麼原因嗎?
有沒有什麼辦法可以告訴我們在更改類時需要編譯哪些類?當班級改變時,我需要編譯哪些類?
回答
這聽起來像是很多努力來開發我懷疑是不可靠的解決方案。
我會爲每個版本構建整個應用程序。要創建一個補丁,我會比較生成的類或文件與原始發行版中的類或文件。任何已更改的文件都將包含在內。
這是更好,因爲
- 你不必瞭解不斷變化的一個常數,方法或類的所有後果。
- 如果您更改偶然的格式或註釋等內容,則無需更新文件。
- 你可以有信心,應用補丁是完全一樣的,並給予完整的分佈。
如果更改類A的簽名,則不必重新編譯調用此類的所有類。你必須改變這些類的實現。
例如,如果你的A類有方法foo()
這是所謂的B類,現在你更名爲bar()
你必須改變B類的源代碼,否則你會得到NoSuchMethodError
。
但是,如果您不改變接口但只是修改類A的內部實現,則不必重新編譯除此類之外的任何內容。編譯時只需創建適當的類路徑。類路徑必須包含類A的直接依賴關係和依賴關係的依賴關係。它不能包含第三級依賴關係(即依賴關係依賴關係的依賴關係)。但恕我直言,編譯補丁時處理類路徑的最簡單方法就是提供現有應用程序的完整類路徑。
有些簽名更改可以簡單地重新編譯(至少有一些)用法,而無需更改任何源 - 例如,如果返回類型仍可分配給之前使用的相同類型,或者參數類型現在更寬。類似於常量的變化。 – 2011-12-25 11:34:16
此外,內聯public
常量可能是難以定位的問題的來源,因爲它們不會導致異常或錯誤,但會導致沉默的錯誤行爲。
比方說你有一個類一個一些public static final
字段是一個基本類型或一個String
的,其值可以在編譯時確定。
public class A {
public static final String GREETING = "Hello";
...
}
然後,如果另一個類乙訪問該字段,編譯器內聯常數 - 即將A.GREETING
參考替換爲其值"Hello"
。沒有關於恆定值來自哪裏的信息。
現在到了麻煩 - 如果你改變GREETING
價值可以說"Hi"
並重新編譯只有類一個,直到你重新編譯過的類乙內聯值將保持不變。因此,像其他人已經指出的那樣,從零開始重建整個應用程序通常是一個更好的主意。
一個很好的文章討論這個問題: http://marxsoftware.blogspot.com/2009/09/inconstant-constants-in-java.html
一些相關的SO問題:
Is Java guaranteed to inline string constants if they can be determined at compile time
- 1. 一個班級需要另一個班級,其他班級需要第一個班級。我怎麼做?
- 2. 班級不改變
- 3. 我需要哪些子類遷移?
- 4. 爲什麼當我的班級打電話給我的班級工作時,需要兩個參數?
- 5. 我需要延遲當我改變一些文字
- 6. 當PayPal更新政策時需要進行哪些修改
- 7. 我可以改變班級的超級班嗎?
- 8. 在aspectJ編譯時織入後,我仍然需要哪些類文件在類路徑上?
- 9. 編碼時我需要考慮哪些安全問題?
- 10. 單擊拇指組時改變班級
- 11. 我們需要在Android 6.0運行時需要哪些權限
- 12. 當擴展Magento的核心類時,我需要更改哪些XML結構才能使更改生效?
- 13. .ASP我需要編譯嗎?
- 14. 當位置改變時調用一個班級
- 15. MSVC預編譯頭文件:哪些文件需要#include「stdafx.h」?
- 16. 從bootstrap.less編譯bootstrap.css需要哪些資源?
- 17. Java - 讓其他班級需要的班級
- 18. 每當我做出改變時,我是否需要辭職APK?
- 19. 「班級未註冊」哪個班級?
- 20. 需要做些什麼來編譯?
- 21. 需要幫助編譯一些東西! (:
- 22. 我需要預編譯資產,每當我做出任何改變以查看瀏覽器的差異時
- 23. 哪些編程語言需要IDE?
- 24. 級聯在(N)Hibernate中,我需要哪些規則?
- 25. 支持IPv6需要哪些更改
- 26. 我如何確定CPAN分佈的哪些依賴需要編譯器?
- 27. 我需要在Ubuntu上安裝哪些軟件包才能讓ruby-opengl編譯?
- 28. 從Bing Maps v7升級到v8時需要更改哪些內容?
- 29. 反思/改變班級的變化
- 30. 哪些EC2類型不需要VPC?
我想知道,如果它不會是更容易重新編譯一切,使用diff工具來查找實際更改的二進制文件。 – 2011-12-25 11:25:46
我已閱讀了有關此問題的幾個詳細討論。簡單的答案是,知道需要重新編譯的東西並不簡單,並且沒有獨立的工具可以實現。 Eclipse增量式編譯器可以做到這一點,但只能作爲編譯的一部分。 @ JensSchauder的建議看起來很不錯。 – 2011-12-25 15:07:08