這確實應該是一個簡單的區別,但是我一直在回答有關Stackoverflow的許多類似問題,并且經常有人誤解此事。
那么,什么是類路徑? 應用程序所需的一組所有類(以及帶有類的jar)的集合。 但是有兩個或實際上三個不同的類路徑:
- 編譯時的類路徑。 包含您在IDE中添加的類(假設您使用IDE)以編譯代碼。 換句話說,這是傳遞給“ javac”的類路徑(盡管您可能正在使用其他編譯器)。
- 運行時類路徑。 包含運行應用程序時使用的類。 那就是傳遞給“ java”可執行文件的類路徑。 對于Web應用程序,這是您的/ lib文件夾,以及應用程序服務器/ Servlet容器提供的任何其他jar
- 測試類路徑–這也是一種運行時類路徑,但是在運行測試時使用。 測試不在您的應用程序服務器/ servlet容器中運行,因此它們的類路徑有些不同
Maven定義了依賴范圍,這對于解釋不同類型的類路徑之間的區別非常有用。 閱讀每個范圍的簡短說明 。
許多人認為,如果他們在存在給定的jar文件的情況下成功編譯了該應用程序,則意味著該應用程序將正常運行。 但這并不需要-您需要與用于編譯應用程序的jar相同的jar才能出現在運行時類路徑中。 好吧,不一定所有的人,也不一定只有他們。 一些例子:
- 您可以使用編譯時類路徑上的給定庫來編譯代碼,但是忘記將其添加到運行時類路徑中。 JVM拋出NoClasDefFoundError,這意味著缺少一個類,該類在編譯代碼時存在。 此錯誤是一個清楚的信號,表明您在運行時類路徑上缺少編譯時類路徑上的jar文件。 反過來,您依賴的jar也有可能取決于您在任何地方都沒有的jar。 這就是為什么(必須)聲明庫的依賴關系的原因,以便您知道要在運行時類路徑上放置哪些jar
- 容器(Servlet容器,應用程序服務器)具有一些內置庫。 通常,您不能覆蓋內置的依賴項,即使可以,它也需要其他配置。 因此,例如,您使用提供了servlet-api.jar的Tomcat。 您可以使用編譯時類路徑上的servlet-api.jar來編譯應用程序,以便可以在類中使用HttpServletRequest,但不要將其包含在WEB-INF / lib文件夾中,因為tomcat會將其自己的jar放入運行時類路徑。 如果您重復依賴項,則可能會得到奇怪的結果,因為類加載器會感到困惑。
- 您正在使用的框架(例如spring-mvc)依賴于另一個庫進行JSON序列化(通常是Jackson)。 實際上,您在編譯時的類路徑上不需要Jackson,因為您沒有引用它的任何類,甚至沒有引用它們的spring類。 但是spring內部需要Jackson,因此jackson jar必須位于WEB-INF / lib(運行時類路徑)中,才能進行JSON序列化。
當您考慮編譯時常量和版本不匹配時,情況可能會更加復雜,但是一般的要點是:您用于編譯和運行應用程序的類路徑是不同的,您應該意識到這一點。
參考: Bozho的技術博客博客中的JCG合作伙伴 Bozhidar Bozhanov的 運行時類路徑與編譯時類路徑 。
翻譯自: https://www.javacodegeeks.com/2012/04/runtime-vs-compile-time-classpath.html