繁体   English   中英

使用 NIO 加载外部 JAR 中的所有类

[英]Loading all classes in an external JAR using NIO

我有一个包含一些 JARs 的插件文件夹,我想加载它们的所有 *.class。 我看到很多关于JarFileZipEntry的答案。 但是,我想使用 java.nio package 而不是 io 来执行此操作。

我可以做什么:

  1. 使用Files.list(Path)
  2. 加载 a.class 在 JAR 中,知道它在所述 JAR 中的确切位置。

我还不能做什么:

  1. 使用 NIO 列出 JAR/ZIP 中的文件。

最终,我想要:

  1. 遍历几个JARs中的每个class并加载它们来寻找一种插件系统的注解

我应该补充一点,我不需要使用像 Guava 或 Apache 这样的 API 的工作解决方案,但我只想知道它是如何完成的。

我当前的代码:

import java.io.IOException;
import java.nio.file.*;
import java.security.SecureClassLoader;
import java.util.*;
public class PluginManager {

public final Path pluginFolder;

public PluginManager(Path pluginFolder) {
    this.pluginFolder = pluginFolder;
}


public void load() {
    final var pluginClassLoader = new SecureClassLoader(getClass().getClassLoader()){

        FileSystem jar;

        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            String pluginClassName = jar.getSeparator() + name.replaceAll("\\.", jar.getSeparator()) + ".class";
            try{
                byte[] bytes = Files.readAllBytes(jar.getPath(pluginClassName));
                return defineClass(name, bytes, 0, bytes.length);
            }catch(IOException e){
                e.printStackTrace();
            }
            throw new ClassNotFoundException("Failed to found "+name);
        }
    };

    try(Stream<Path> files = Files.list(pluginFolder)){
        files.filter((file) -> !Files.isDirectory(file) &&
                (file.toString().endsWith(".jar") || file.toString().endsWith(".zip")))
                .forEach(jar -> {

                    try(FileSystem fileSystem = FileSystems.newFileSystem(jar)){
                        pluginClassLoader.jar = fileSystem;
                        loadPlugin(fileSystem, pluginClassLoader);
                    }catch(IOException | ClassNotFoundException e){
                        e.printStackTrace();
                    }

                });
    }catch(IOException e){
        e.printStackTrace();
        throw new IllegalStateException("Failed to scan plugin folder. Cannot continue.");
    }

}

private void loadPlugin(FileSystem jar, SecureClassLoader classLoader) throws IOException, ClassNotFoundException{
    String className = ...  // here, we retrieve the plugin class name from a manifest file using FileSystem.getPath().
// what I want is to get rid of that manifest and to load and test every class.

    Class<?> clazz = classLoader.loadClass(className);
    // do stuff with loaded class
}

我想避免这样的 java.io 代码: How to load Classes at runtime from a folder or JAR?

我偶然发现了 zip 文件夹及其子文件夹中的文件列表 我最初错过了这种方法的是不使用文件夹中的 jar 路径调用Files.walkFileTree(Path, FileVisitor) ,而是使用创建的文件系统的根路径(使用FileSystem FileSystem.getPath("/") )。 这非常适合我。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM