Подтвердить что ты не робот

Java: Какое из нескольких ресурсов на пути к классам JVM?

Если у меня есть несколько файлов с одинаковым именем в пути к классам (например, у меня есть несколько .jar с log4j.properties), каковы правила JVM следует выбрать один?

4b9b3361

Ответ 1

Он задается порядком, в котором ресурсы (т.е. обычно файлы jar) задаются с помощью опции -classpath. Ресурсы "раньше" в classpath имеют приоритет над ресурсами, которые указаны после них. Это также можно установить в файле манифеста вашего приложения, а затем вам не нужно указывать опцию -classpath. Вы можете проверить эти статьи о том, как работать с файлами манифеста.

Подробное описание "как найти классы" можно найти здесь, где описывается раздел классов класса JAR-класса логика поиска JAR файлов.

Ответ 2

ClassLoader определяет, где будет располагаться ресурс (взятый из ClassLoader JavaDoc):

Класс ClassLoader использует модель делегирования для поиска классов и ресурсов. Каждый экземпляр класса ClassLoader имеет связанный загрузчик родительского класса. При запросе на поиск класса или ресурса экземпляр ClassLoader делегирует поиск класса или ресурса его загрузчику родительского класса, прежде чем пытаться найти сам класс или ресурс. Встроенный загрузчик классов виртуальной машины, называемый загрузчиком загрузки bootstrap, сам по себе не имеет родителя, но может служить родителем экземпляра ClassLoader.

Поэтому везде, где в вашем коде вызывается класС# getResource или класС# getResourceAsStream, это происходит (взято из Class.java)

public java.net.URL getResource(String name) {
    name = resolveName(name);
    ClassLoader cl = getClassLoader0();
    if (cl==null) {
        // A system class.
        return ClassLoader.getSystemResource(name);
    }
    return cl.getResource(name);
}

ClassLoader.java:

public URL getResource(String name) {
    URL url;
    if (parent != null) {
        url = parent.getResource(name);
    } else {
        url = getBootstrapResource(name);
    }
    if (url == null) {
        url = findResource(name);
    }
    return url;
}

где ClassLoader # findResource на самом деле должен быть перезаписан реализацией ClassLoader. Это означает, что поведение отличается от сервера приложений, TomCat, или если вы работаете из файла jar, это зависит от реализаций ClassLoader среды, в которой вы сейчас находитесь.

Здесь приведен пример, который вы можете использовать для отслеживания того, что происходит под капотом в вашем конкретном случае.