加载一个包并在里面 类

Load a package and inside classes

我正在创建一个包,其中包含我使用 wsimport 动态生成的一些 classes,现在我正在尝试加载它以供使用,我该怎么做?天生的?或者使用像 byte-buddy 这样的库,我尝试使用下面的代码将每个 class 加载到一个包中:

File [] files = new File("<Path to package in filesystem with classes (*.class)>").listFiles();
    List<URL> classUrls = new ArrayList<>();

    for(File file : files) {
        classUrls.add(new URL("file://" + file.getAbsolutePath()));
    }

    URL[] classz = new URL[classUrls.size()];
    classz = classUrls.toArray(classz);

    URLClassLoader child = new URLClassLoader(classz);
    Class.forName("com.abc.external.resources.genwn239aqyhmfz.SomeClass", true, child);

但我仍然收到(包裹:com.abc.external.resources.genwn239aqyhmfz.SomeClass)

java.lang.ClassNotFoundException: com.abc.external.resources.genwn239aqyhmfz.SomeClass

class 路径的规则与启动应用程序时必须遵守的规则没有什么不同。 class 路径条目是 不是 class 文件或包含它们的目录,而是包结构的根目录。

所以如果你要加载的class是com.abc.external.resources.genwn239aqyhmfz.SomeClass,class路径条目必须是包含com目录的目录,其中包含abc目录等。如果您知道 classes 之一的预期全限定名,则很容易找到正确的目录。只需遍历文件层次结构,直到限定名称包含包组件的次数。但是,当您事先不知道名称时,查找它可能会很棘手。这是一个草图:

// pass the expected name of one class contained in f or null if not known
static void loadClasses(File f, String predictedName)
        throws IOException, ClassNotFoundException {
    File[] classes = f.listFiles((d,n)->n.endsWith(".class"));
    if(classes == null || classes.length == 0) {
        System.err.println("no classes or not a directory");
        return;
    }
    if(predictedName == null) predictedName = predictName(classes[0]);
    for(int p = predictedName.indexOf('.'); p >= 0; p = predictedName.indexOf('.', p+1))
        f = f.getParentFile();
    URLClassLoader classLoader = new URLClassLoader(new URL[] { f.toURI().toURL() });
    String packageName = predictedName.substring(0, predictedName.lastIndexOf('.')+1);
    for(File cf: classes) {
        String name = cf.getName();
        name = name.substring(0, name.length()-6); // strip off ".class"
        Class<?> cl = classLoader.loadClass(packageName+name);
        // what do you wanna do with the classes?
        System.out.println(cl);
    }
}

private static String predictName(File classFile) throws IOException {
    byte[] data = Files.readAllBytes(classFile.toPath());
    return new ClassLoader() {
        String getName() {
            return defineClass(null, data, 0, data.length).getName();
        }
    }.getName();
}

predictName 实现非常简单。如果 class 依赖于 JVM 立即尝试解析的同一文件层次结构中的 classes,它将失败,因为我们还没有必要的信息。在那种情况下,只有允许在不加载 class 的情况下提取名称的字节码解析库才有帮助。但这超出了这个问题的范围......