Ресурсы Java Runtime vs Compile Time

При настройке веб-приложения Java с использованием Tomcat в качестве сервера приложений меня часто путают, когда библиотеки доступны. Посредством обсуждения Qaru я узнал, что некоторые файлы библиотек (.jar) доступны во время выполнения, а другие доступны во время компиляции. Часто я получаю ошибки и разрешу их путем проб и ошибок, помещая файлы jar в разные каталоги до тех пор, пока приложение не запустится или не скомпилируется. Недавно мне сообщили, что вы можете создавать библиотеки .jar во время выполнения через папку WEB-INF/lib. Я начал об этом думать и имел несколько вопросов. Я прочитал эту тему в прошлом и не нашел источник, который помещает информацию в контекст, который я легко понимаю и сохраняю.

  • Есть ли путь к классу времени компиляции и путь к классам выполнения, который вы можете установить для проекта?

    а. Является ли classpath даже применимым термином для обсуждения библиотек, доступных во время выполнения?

  • Является ли WEB-INF/lib единственным способом сделать библиотеки доступными во время выполнения? Что относительно папки lib в Tomcat это доступно во время выполнения?

  • Как это относится к загрузчикам классов? Я знаю, что создается иерархия классов-загрузчиков. Являются ли они строго для выполнения Runtime?

Ответ 1

Компиляция classpath - это путь к классам, используемый для компиляции исходных файлов Java (с помощью javac -cp ... или вашей среды IDE). Каждый класс, указанный в исходном файле, должен присутствовать в пути к компиляции, иначе компилятор будет жаловаться, что он не может найти класс.

После того как вы скомпилировали классы, вы можете запустить программу, используя их (используя java -cp ...). Очевидно, что библиотеки, от которых напрямую зависит ваш исходный код, должны быть в пути к среде выполнения. Но это не все. Если вы напрямую зависите от CoolLibrary.jar, и эта библиотека внутренне зависит от Guava.jar, то Guava.jar также должен быть в пути к среде выполнения, хотя при компиляции он не нужен.

Webapps немного особенный. Спецификация сервлета указывает, что путь к классам, используемый для выполнения webapp, состоит из каталога WEB-INF/classes развернутого webapp и всех банок, содержащихся в WEB-INF/lib. Все веб-приложения также имеют доступ к встроенным сервлетом и JSP-банкам, которые напрямую предоставляются Tomcat. На самом деле, внутренние классы Tomcat (например, классы реализации интерфейсов servlet-api) также доступны для webapp, но полагаться на эти классы не очень хорошо, поскольку это привяжет ваш webapp к tomcat.

Говоря о пути класса runtime, в случае webapp, немного упрощается. В действительности, каждый класс webapp загружается динамически определенным загрузчиком классов tomcat. И этот загрузчик классов webapp является дочерним элементом загрузчика классов tomcat. Итак, теоретически, вы можете разместить баны webapp в классе Tomcat напрямую, но это будет означать, что все веб-приложения будут делиться этими библиотеками и что у вас возникнут проблемы с развертыванием и перераспределением webapps. Цель иметь определенный загрузчик классов для каждого webapp - иметь возможность иметь в одном JVM приложение, основанное на Guava 11.0, и другое, например, на основе Guava 12.0.

Для получения дополнительной информации о загрузчиках классов tomcat прочитайте документацию.

Ответ 2

  • в eclipse у вас есть java build path, который включает библиотеки во время компиляции, и у вас есть order and export, который для среды выполнения.

  • только библиотеки tomcat по умолчанию