2016-02-23 4 views
3

Мне кажется, что JAR file indexing нарушает работу механики ClassLoader.getResources(). Рассмотрим следующую программу:JAR индексирование и getResources

import java.io.*; 
import java.net.*; 
import java.util.*; 

public class TryIt { 
    public static void main(String[] args) throws Exception { 
     URL[] urls = { 
      (new File("a.jar")).getAbsoluteFile().toURI().toURL(), 
      (new File("b.jar")).getAbsoluteFile().toURI().toURL() 
     }; 
     URLClassLoader cl = URLClassLoader.newInstance(urls); 
     String[] res = { "foo", "foo/", "foo/arb", "foo/bar", "foo/cab" }; 
     for (String r: res) { 
      System.out.println("'" + r + "':"); 
      for (URL u: Collections.list(cl.getResources(r))) 
       System.out.println(" " + u); 
     } 
    } 
} 

Теперь подготовить JAR-файлы, упомянутые в этой программе:

mkdir a/foo b/foo 
touch a/foo/arb a/foo/bar b/foo/bar b/foo/cab 
echo "Class-Path: b.jar" > mf 
jar cfm a.jar mf -C a foo 
jar cf b.jar -C b foo 

Если вы запустите java TryIt, вы получите такой вывод:

'foo': 
jar:file:…/a.jar!/foo 
jar:file:…/b.jar!/foo 
'foo/': 
jar:file:…/a.jar!/foo/ 
jar:file:…/b.jar!/foo/ 
'foo/arb': 
jar:file:…/a.jar!/foo/arb 
'foo/bar': 
jar:file:…/a.jar!/foo/bar 
jar:file:…/b.jar!/foo/bar 
'foo/cab': 
jar:file:…/b.jar!/foo/cab 

Но если вы запустите jar -i a.jar, чтобы создать индекс, то та же самая команда, что и выше, печатает это:

'foo': 
jar:file:…/a.jar!/foo 
'foo/': 
jar:file:…/a.jar!/foo/ 
'foo/arb': 
jar:file:…/a.jar!/foo/arb 
'foo/bar': 
jar:file:…/a.jar!/foo/bar 
'foo/cab': 
jar:file:…/b.jar!/foo/cab 

Сам индекс выглядит следующим образом:

JarIndex-Version: 1.0 

a.jar 
foo 

b.jar 
foo 

ли не договор getResources означает, что все имеющиеся ресурсы, соответствующие данному имени должны быть возвращены?

Находит все ресурсы с заданным именем.

the JAR File Specification Разрешить индексированные пакеты для размещения нескольких файлов JAR?

Обычно одно имя пакета сопоставляется с одним файлом jar, но если конкретный пакет охватывает более одного файла jar, тогда отображаемое значение этого пакета будет списком файлов jar.

Есть ли какая-то спецификация где-то, где говорится, что то, что я наблюдаю, действительно является правильным (или, по крайней мере, допустимым) поведением?

Есть ли какое-либо обходное решение для получения всех названных ресурсов, несмотря на индекс?

ответ

1

Это, кажется, ошибка.
Я сообщил об этом Oracle, и теперь он находится в своей базе данных ошибок как bug 8150615.


Я немного искал источники OpenJDK и нашел для этого поведения резонанс.

Соответствующий класс здесь sun.misc.URLClassPath. Он содержит (лениво построенный) list of loaders и queries each loader in turn, чтобы собрать его результат. Однако, если файл JAR contains an index, то файлы JAR в нем будут explicitely be excludedfrom getting added в список загрузчиков. Вместо этого загрузчик для JAR, содержащий индекс, будет query said index для имени, о котором идет речь, и traversed the resulting list. Но вот улов: это происходит в методе URLClassPath$JarLoader.getResource, который возвращает один объектResource. Этот метод не может возвращать несколько ресурсов. И поскольку все объекты в индексе обрабатываются одним загрузчиком, мы получаем единственный ресурс.

Смежные вопросы