Есть ли способ заставить загрузчик классов загружать пакет, даже если ни один из его классов не был загружен?

Скажем, что java-кодовая база имеет пакет под названием "com.example".

Во время выполнения мы можем получить этот пакет, вызвав

Package p = Package.getPackage( "com.example" ); //(returns null)

или даже получить список всех пакетов, вызвав

Packages[] ps = Package.getPackages();

Проблема заключается в том, что если ClassLoader еще не загрузил какой-либо класс из пакета, он не будет доступен для этих вызовов функций. Мы можем заставить его загрузить пакет путем принудительной загрузки одного из классов в пакете сначала, например:

this.getClass().getClassLoader().loadClass( "com.example.SomeClass" );
Package p = Package.getPackage( "com.example" ); //(returns non-null)

Однако это взломанно и требует знания заранее определенного класса, принадлежащего к пакету.

Итак, вопрос в том, есть ли способ получить экземпляр пакета по имени, независимо от того, сделал ли ClassLoader что-либо? Являются ли мои предположения о том, как классная загрузка/пакеты, похоже, работают в этой ситуации точно?

Ответ 1

В качестве альтернативы вы можете использовать корневой каталог класса как отправную точку и пройти через все *.class файлы и подкаталоги. Это будет работать, только если вы знаете, где все ваши файлы .class будут находиться заранее.

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

Ответ 2

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

Вы можете передать подстановочный знак на ClassLoader.getResources и заставить его забрать классы в пакете, что в свою очередь сделает работу.

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

Ответ 3

Я предполагаю, что вам это нужно, потому что вам нужно проверить его аннотации. В противном случае вам не будет интересно иметь ссылку на пакет, для которой доступны только операции с аннотациями. Это приводит к предположению, что у вас также есть package-info.java, определенный там с некоторыми аннотациями.

Если вы отметите java.lang.Package, вы увидите, что getPackageInfo просто загружает класс package-info как обычный класс.

У меня была такая же проблема, и я придумал это решение.

public static Package getPackage(String packageName) throws ClassNotFoundException {
    Class.forName(packageName+".package-info"); // makes sure package info exist and that the class loader already knows about the package
    return Package.getPackage(packageName);
}