Как получить список файлов jar и папок в classpath в Java 9? [Дубликат]

Я просто стараюсь, чтобы они фиксировали ширину, чтобы они соответствовали общей ширине страницы - возможно, она работает только в том случае, если вы используете страницу с фиксированной шириной. Также «плавать».

12
задан kaqqao 14 June 2018 в 14:24
поделиться

2 ответа

Следующий код позволяет проверить путь к модулю в Java 9+ (Jigsaw). Он находит все классы в стеке вызовов, затем для каждой ссылки на класс вызывает classRef.getModule().getLayer().getConfiguration().modules(), который возвращает a List<ResolvedModule>, а не только List<Module>. (ResolvedModule дает вам доступ к ресурсам модуля, тогда как Module этого не делает.) Учитывая ссылку ResolvedModule для каждого модуля, вы можете вызвать метод .reference(), чтобы получить ModuleReference для модуля. ModuleReference#open() дает вам ModuleReader, который позволяет вам перечислять ресурсы в модуле с помощью ModuleReader#list() или открывать ресурс с помощью Optional<InputStream> ModuleReader#open(resourcePath) или Optional<ByteBuffer> ModuleReader#read(resourcePath). Затем вы завершите ModuleReader, когда закончите с модулем. Это не документировано нигде, что я видел. Было очень сложно все это понять. Но вот код, в надежде, что кому-то это поможет.

Обратите внимание, что даже в JDK9 + вы все равно можете использовать традиционные элементы classpath вместе с элементами пути к модулю, поэтому для полного пути к модулю + сканирование классов, вы, вероятно, должны использовать правильное решение для проверки пути к классам, такое как FastClasspathScanner , которое поддерживает сканирование модуля с использованием механизма ниже, начиная с версии 3.0.0 (отказ от ответственности, я автор).

import java.lang.module.ModuleReader;
import java.lang.module.ModuleReference;
import java.lang.module.ResolvedModule;
import java.net.URI;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;

public class ModuleScanner {

    private static CallerResolver CALLER_RESOLVER;

    static {
        try {
            // This can fail if the current SecurityManager does not allow
            // RuntimePermission ("createSecurityManager"):
            CALLER_RESOLVER = new CallerResolver();
        } catch (final SecurityException e) {
        }
    }

    private static final class CallerResolver extends SecurityManager {
        /** Get classes in the call stack. */
        @Override
        protected Class<?>[] getClassContext() {
            return super.getClassContext();
        }
    }

    /** Recursively find the topological sort order of ancestral layers. */
    private static void findLayerOrder(ModuleLayer layer,
            Set<ModuleLayer> layerVisited, Deque<ModuleLayer> layersOut) {
        if (layerVisited.add(layer)) {
            List<ModuleLayer> parents = layer.parents();
            for (int i = 0; i < parents.size(); i++) {
                findLayerOrder(parents.get(i), layerVisited, layersOut);
            }
            layersOut.push(layer);
        }
    }

    /**
     * Return true if the given module name is a system module. There can be
     * system modules in layers above the boot layer.
     */
    private static boolean isSystemModule(final String moduleName) {
        return moduleName.startsWith("java.")
                || moduleName.startsWith("javax.")
                || moduleName.startsWith("javafx.")
                || moduleName.startsWith("jdk.")
                || moduleName.startsWith("oracle.");
    }

    public static void main(String[] args) throws Exception {
        Deque<ModuleLayer> layerOrder = new ArrayDeque<>();
        Set<ModuleLayer> layerVisited = new HashSet<>();

        // Get ModuleReferences for modules of all classes in call stack
        if (CALLER_RESOLVER == null) {
            throw new RuntimeException("Current SecurityManager does not grant "
                    + "RuntimePermission(\"createSecurityManager\")");
        } else {
            final Class<?>[] callStack = CALLER_RESOLVER.getClassContext();
            if (callStack == null) {
                throw new RuntimeException(CallerResolver.class.getSimpleName()
                        + "#getClassContext() returned null");
            } else {
                for (int i = 0; i < callStack.length; i++) {
                    ModuleLayer layer = callStack[i].getModule().getLayer();
                    if (layer != null) {
                        findLayerOrder(layer, layerVisited, layerOrder);
                    } else {
                        System.out.println(
                                "layer is null for unnamed modules -- have to "
                                + "find their URLs by reading java.class.path");
                    }
                }
            }
        }

        // Lastly add system modules from boot layer
        ModuleLayer bootLayer = ModuleLayer.boot();
        findLayerOrder(bootLayer, layerVisited, layerOrder);

        Set<ModuleReference> addedModules = new HashSet<>();
        List<Entry<ModuleReference, ModuleLayer>> systemModuleRefs 
                = new ArrayList<>();
        List<Entry<ModuleReference, ModuleLayer>> nonSystemModuleRefs
                = new ArrayList<>();

        for (ModuleLayer layer : layerOrder) {
            List<ResolvedModule> modulesInLayer = new ArrayList<>(
                    layer.configuration().modules());
            Collections.sort(modulesInLayer, (e1, e2) -> 
                    e1.reference().descriptor().name()
                        .compareTo(e2.reference().descriptor().name()));
            for (ResolvedModule module : modulesInLayer) {
                ModuleReference moduleReference = module.reference();
                if (addedModules.add(moduleReference)) {
                    String moduleName = moduleReference.descriptor().name();
                    (isSystemModule(moduleName) ? systemModuleRefs
                            : nonSystemModuleRefs).add(
                                    new SimpleEntry<>(moduleReference, layer));
                }
            }
        }

        // List system modules
        System.out.println("\nSYSTEM MODULES:\n");
        for (Entry<ModuleReference, ModuleLayer> e : systemModuleRefs) {
            ModuleReference ref = e.getKey();
            System.out.println("  " + ref.descriptor().name());
        }

        // Show info for non-system modules
        System.out.println("\nNON-SYSTEM MODULES:");
        for (Entry<ModuleReference, ModuleLayer> e : nonSystemModuleRefs) {
            ModuleReference ref = e.getKey();
            ModuleLayer layer = e.getValue();
            System.out.println("\n  " + ref.descriptor().name());
            System.out.println(
                    "    Version: " + ref.descriptor().toNameAndVersion());
            System.out.println("    Packages: " + ref.descriptor().packages());
            System.out.println("    ClassLoader: "
                    + layer.findLoader(ref.descriptor().name()));
            Optional<URI> location = ref.location();
            if (location.isPresent()) {
                System.out.println("    Location: " + location.get());
            }
            try (ModuleReader moduleReader = ref.open()) {
                Stream<String> stream = moduleReader.list();
                stream.forEach(s -> System.out.println("      File: " + s));
            }
        }
    }
}
10
ответ дан Luke Hutchison 15 August 2018 в 15:12
поделиться
  • 1
    Удивительно, наконец, некоторые реальные подсказки! Спасибо за это! – kaqqao 10 August 2017 в 11:27
  • 2
    Вот более подробные исследования того же автора: github.com/lukehutch/fast-classpath-scanner/issues/36 – Vadzim 20 October 2017 в 17:36
  • 3
    @kaqqao Я обновил свой ответ с полным кодом сканирования. – Luke Hutchison 13 June 2018 в 10:38
  • 4
    @LukeHutchison Вы, сэр, являетесь богом-императором человеческого рода :) Означает ли это, что FastClasspathScanner теперь имеет дело с Java 9 с модулем (и без classpath)? – kaqqao 14 June 2018 в 13:51
  • 5
    @kaqqao FastClasspathScanner теперь сканирует как путь к модулю, так и традиционный путь к классам в этом порядке (так как даже модульные среды выполнения по-прежнему поддерживают традиционный путь к классам), и оба обратно совместимы с JDK 7 и 8 (для проверки только для классов) и пересылаются, совместимые с JDK 9, 10 и более поздних версий (для проверки пути к модулю и пути к классам). – Luke Hutchison 14 June 2018 в 16:40
  • 6
    – Joakim Erdfelt 26 September 2018 в 12:08

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

Я сделал следующее:

  • получить текущий дескриптор модуля для текущего класса
  • get все requires модули
  • для каждого такого открытого ресурса модуля MANIFEST.MF
  • удаляют путь MANIFEST.MF из ресурса url
  • , что остается classpath модуля, то есть к его jar или папке.

Я делаю то же самое для текущего модуля, чтобы получить путь к классу для текущего кода.

Таким образом, я собираю classpath текущего работающего модуля и всех его необходимых модулей (в 1 шаге). Это работало для меня - и мой сканер Java8 все еще мог выполнять эту работу. Этот подход не требует каких-либо дополнительных флагов VM и т. Д.

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

Код .

1
ответ дан igr 15 August 2018 в 15:12
поделиться
  • 1
    Модульные банки на пути к модулю не указаны в традиционном пути к классам в Java 9+. – Luke Hutchison 13 June 2018 в 07:36
Другие вопросы по тегам:

Похожие вопросы: