Java: Какой из нескольких ресурсов на classpath JVM занимает? - PullRequest
46 голосов
/ 11 июля 2011

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

Ответы [ 3 ]

48 голосов
/ 11 июля 2011

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

Подробное описание того, «как найти классы», можно найти здесь , где раздел JAR-class-path Classes описывает логику JAR-файловпоиск.

7 голосов
/ 11 июля 2011

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

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

Так что где бы в вашем коде ни вызывался Class # getResource или Class # 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 среды, в которой вы находитесь.

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

0 голосов
/ 13 августа 2018

Я привожу доказанный случай, что, если classpath - это, скажем, все jar-файлы в папке, и вы хотите назначить приоритет одному (или нескольким) из них, это не работает:

Windows:

bin/prioritized.jar;bin/*

Linux:

bin/prioritized.jar:bin/*

Похоже, что первый путь bin / prioritized.jar игнорируется только потому, что второй путь с подстановочным знаком включает его в свою собственную область.Это то, что эффективно нарушает заданный порядок путей к классам.

Поэтому, чтобы выделить несколько ресурсов по приоритетам (протестировано на Java 10.0.1), вам нужно поместить их в непересекающиеся области, и тогда они будут работать.

...