交叉编译指定运行时库路径
这确实应该是一个简单的区别,但是我一直在回答有关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
交叉编译指定运行时库路径