Как получить список всех имен пакетов, загруженных JVM

Мне нужно получить имена всех пакетов Java, загруженных JVM. Это нужно для отображения обозревателя пакетов, подобного тем, которые можно найти в IDE. Я могу получить список пакетов текущего загрузчика классов и его предков, обратившись к защищенному полю «пакеты» класса ClassLoader. Но я не могу загрузить пакеты другими веб-приложениями, поскольку у них есть свои собственные загрузчики классов. Я тестирую это на сервере Weblogic


person maneesh    schedule 22.06.2009    source источник
comment
Package.getPackages() был бы более обычным.   -  person Tom Hawtin - tackline    schedule 22.06.2009


Ответы (4)


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

person stevedbrown    schedule 22.06.2009
comment
Мне тоже интересно, что он задумал. Может быть, он пытается найти способ сканировать веб-приложения других людей на наличие дыр в безопасности? - person Aaron Digulla; 22.06.2009
comment
Возможно, он пытается выяснить, какие библиотеки используются несколькими веб-приложениями, чтобы выделить их в общую область. Разве менеджеры JMX не могут узнать такого рода информацию? - person ThaDon; 22.06.2009
comment
Я действительно не уверен - если они смогут, разместите это, вы обязательно получите мой голос. - person stevedbrown; 22.06.2009
comment
Да, я пытаюсь получить имена библиотек, используемые всеми приложениями, развернутыми на сервере. Этот ответ верен, насколько мне известно, поскольку я не смог найти способ получить ссылку на загрузчики классов других веб-приложений. Так что я закончил сканирование развернутого уха, войны, банок и расширенных папок. Смотрите мой ответ ниже. - person maneesh; 06.11.2009

Вам нужно пройтись по дереву загрузчиков классов, используя getParent(), найти все классы, которые расширяют ClassLoader, найти все текущие экземпляры (здесь должен помочь API отладки). Но это, вероятно, не сработает для веб-серверов из-за политики безопасности (веб-приложениям не разрешено просматривать друг друга).

Для Tomcat есть возможность регистрировать все классы по мере их загрузки. Это довольно сильно замедляет работу сервера, но это может быть вариант на сервере разработки.

Тем не менее, мне очень любопытно, зачем вам это нужно. Самым простым решением было бы перечислить все файлы JAR, которые приносит ваше приложение, с jar tvf и удалить последнюю часть пути (файл класса).

person Aaron Digulla    schedule 22.06.2009

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

Если вам не нужна эта информация в каком-то приятном пользовательском интерфейсе, тогда у Sun JVM есть несколько опций -XX vm, которые покажут вам, что происходит с загрузкой классов.

http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp

Я не очень хорошо знаком с JRockit, но был бы удивлен, если бы у него не было подобных опций.

person Nick Holt    schedule 22.06.2009

Хорошо, мне удалось заставить это работать на Weblogic. Моя цель снова состояла в том, чтобы получить имена пакетов Java во всех приложениях, развернутых на данном сервере WebLogic. Почему? У меня были свои причины :)

Сначала вам нужно получить информацию о расположении файлов ear, war или jar всех развернутых приложений. Для этого мы получаем MBean-компоненты AppDeployment из WebLogic и выполняем итерацию, как показано ниже.

    Set<ObjectName> set = utils.getConfigMBeansByType("AppDeployment");
    for (ObjectName objectName : set) {
        String name = objectName.getKeyProperty("Name");            

        if (!appCache.contains(name)) {
            //System.out.println("Config bean: " + objectName);
            Object path = utils.getPropertyValue(objectName,
                    "AbsoluteSourcePath");
            //System.out.println("Path: " + path);
            if(path != null){
                PackageFinder finder = new PackageFinder();
                packages.addAll(finder.findPackages(path.toString()));
            }
            appCache.add(name);
        }
    }

В приведенном выше коде мы получаем путь к файлу war, ear, jar или взорванной папке и передаем его методу findPakages класса PackageFinder, который выполняет всю работу.

 public Set<String> findPackages(String path){
    File file = new File(path);
    if(file.exists() && file.isFile()){
        InputStream in = null;
        try {
            in = new BufferedInputStream(new FileInputStream(file));
            if(path.toLowerCase().endsWith(".war")){
                processWar(in);
            }else if(path.toLowerCase().endsWith(".ear")){
                processEar(in);
            }/*
    Rest of the method body removed, I guess you get the idea 
    */              
    return packageNames;

}


public void processJar(InputStream in){
    ZipInputStream zin = null;
    try {
        zin = new ZipInputStream(in);
        ZipEntry entry;
        while((entry = zin.getNextEntry()) != null){
            if(entry.getName().endsWith(".class")){
                addPackage(entry.getName());
            }
        }
    } catch (Exception e) {
    }
}
person maneesh    schedule 06.11.2009
comment
Примечание. Это не возвращает имена пакетов всех загруженных классов в JVM. Он просто возвращает все имена пакетов классов, связанных со всеми развернутыми приложениями на сервере WebLogic, что служит моей цели. - person maneesh; 06.11.2009