栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

在Java 9中的运行时中扫描类路径/模块路径

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在Java 9中的运行时中扫描类路径/模块路径

以下代码在Java 9+(Jigsaw /JPMS)中实现了模块路径扫描。它在调用堆栈中查找所有类,然后为每个类引用调用

classRef.getModule().getLayer().getConfiguration().modules()
,它们返回aa
List<ResolvedModule>
,而不仅仅是a
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元素与模块路径元素一起使用,因此对于完整的模块路径+类路径扫描,您可能应该使用适当的类路径扫描解决方案,例如ClassGraph,该解决方案支持使用以下内容进行模块扫描机制(免责声明,我是作者)。您可以在此处找到以下代码的基于反射的版本。

还请注意,在JDK
9之后的几个JDK版本中,StackWalker中存在一个错误,必须解决,有关详细信息,请参见上面的基于反射的代码。

package main;import java.lang.StackWalker;import java.lang.StackWalker.Option;import java.lang.StackWalker.Stackframe;import java.lang.module.ModuleReader;import java.lang.module.ModuleReference;import java.lang.module.ResolvedModule;import java.net.URI;import java.security.AccessController;import java.security.PrivilegedAction;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 Java9Scanner {        private static void findLayerOrder(ModuleLayer layer, Set<ModuleLayer> visited, Deque<ModuleLayer> layersOut) {        if (visited.add(layer)) { List<ModuleLayer> parents = layer.parents(); for (int i = 0; i < parents.size(); i++) {     findLayerOrder(parents.get(i), visited, layersOut); } layersOut.push(layer);        }    }        private static List<Entry<ModuleReference, ModuleLayer>> findModuleRefs( Class<?>[] callStack) {        Deque<ModuleLayer> layerOrder = new ArrayDeque<>();        Set<ModuleLayer> visited = new HashSet<>();        for (int i = 0; i < callStack.length; i++) { ModuleLayer layer = callStack[i].getModule().getLayer(); findLayerOrder(layer, visited, layerOrder);        }        Set<ModuleReference> addedModules = new HashSet<>();        List<Entry<ModuleReference, ModuleLayer>> moduleRefs = new ArrayList<>();        for (ModuleLayer layer : layerOrder) { Set<ResolvedModule> modulesInLayerSet = layer.configuration()         .modules(); final List<Entry<ModuleReference, ModuleLayer>> modulesInLayer =         new ArrayList<>(); for (ResolvedModule module : modulesInLayerSet) {     modulesInLayer  .add(new SimpleEntry<>(module.reference(), layer)); } // Sort modules in layer by name for consistency Collections.sort(modulesInLayer,         (e1, e2) -> e1.getKey().descriptor().name()      .compareTo(e2.getKey().descriptor().name())); // To be safe, dedup ModuleReferences, in case a module occurs in multiple // layers and reuses its ModuleReference (no idea if this can happen) for (Entry<ModuleReference, ModuleLayer> m : modulesInLayer) {     if (addedModules.add(m.getKey())) {         moduleRefs.add(m);     } }        }        return moduleRefs;    }        private static Class<?>[] getCallStack() {        // Try StackWalker (JDK 9+)        PrivilegedAction<Class<?>[]> stackWalkerAction =     (PrivilegedAction<Class<?>[]>) () ->         StackWalker.getInstance(      Option.RETAIN_CLASS_REFERENCE)         .walk(s -> s.map(      Stackframe::getDeclaringClass)      .toArray(Class[]::new));        try { // Try with doPrivileged() return AccessController         .doPrivileged(stackWalkerAction);        } catch (Exception e) {        }        try { // Try without doPrivileged() return stackWalkerAction.run();        } catch (Exception e) {        }        // Try SecurityManager        PrivilegedAction<Class<?>[]> callerResolverAction =      (PrivilegedAction<Class<?>[]>) () ->         new SecurityManager() {  @Override  public Class<?>[] getClassContext() {      return super.getClassContext();  }         }.getClassContext();        try { // Try with doPrivileged() return AccessController         .doPrivileged(callerResolverAction);        } catch (Exception e) {        }        try { // Try without doPrivileged() return callerResolverAction.run();        } catch (Exception e) {        }        // As a fallback, use getStackTrace() to try to get the call stack        try { throw new Exception();        } catch (final Exception e) { final List<Class<?>> classes = new ArrayList<>(); for (final StackTraceElement elt : e.getStackTrace()) {     try {         classes.add(Class.forName(elt.getClassName()));     } catch (final Throwable e2) {         // Ignore     } } if (classes.size() > 0) {     return classes.toArray(new Class<?>[0]); } else {     // Last-ditch effort -- include just this class     return new Class<?>[] { Java9Scanner.class }; }        }    }        private static boolean isSystemModule( final ModuleReference moduleReference) {        String name = moduleReference.descriptor().name();        if (name == null) { return false;        }        return name.startsWith("java.") || name.startsWith("jdk.") || name.startsWith("javafx.") || name.startsWith("oracle.");    }    public static void main(String[] args) throws Exception {        // Get ModuleReferences for modules of all classes in call stack,        List<Entry<ModuleReference, ModuleLayer>> systemModuleRefs = new ArrayList<>();        List<Entry<ModuleReference, ModuleLayer>> nonSystemModuleRefs = new ArrayList<>();        Class<?>[] callStack = getCallStack();        List<Entry<ModuleReference, ModuleLayer>> moduleRefs = findModuleRefs(     callStack);        // Split module refs into system and non-system modules based on module name        for (Entry<ModuleReference, ModuleLayer> m : moduleRefs) { (isSystemModule(m.getKey()) ? systemModuleRefs         : nonSystemModuleRefs).add(m);        }        // 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)); }        }    }}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/399937.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号