Я просто стараюсь, чтобы они фиксировали ширину, чтобы они соответствовали общей ширине страницы - возможно, она работает только в том случае, если вы используете страницу с фиксированной шириной. Также «плавать».
Следующий код позволяет проверить путь к модулю в 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));
}
}
}
}
Настоящая проблема заключается в том, чтобы найти пути ко всем баночкам и папкам в пути к классам. Когда вы их получите, вы можете сканировать.
Я сделал следующее:
requires
модули MANIFEST.MF
MANIFEST.MF
из ресурса url Я делаю то же самое для текущего модуля, чтобы получить путь к классу для текущего кода.
Таким образом, я собираю classpath текущего работающего модуля и всех его необходимых модулей (в 1 шаге). Это работало для меня - и мой сканер Java8 все еще мог выполнять эту работу. Этот подход не требует каких-либо дополнительных флагов VM и т. Д.
Я мог бы расширить этот подход, чтобы получить все необходимые модули легко (не только на первом уровне), но на данный момент я не Это нужно.
Код .