Class 加载包并在类内加载

Class 加载包并在类内加载,class,java-8,byte-buddy,Class,Java 8,Byte Buddy,我正在创建一个包,其中包含一些使用wsimport动态生成的类,现在我正在尝试加载它以供使用,我如何才能做到这一点?天生的?或者使用类似于byte buddy的lib,我尝试使用下面的代码将每个类加载到一个包中: File [] files = new File("<Path to package in filesystem with classes (*.class)>").listFiles(); List<URL> classUrls = new Array

我正在创建一个包,其中包含一些使用wsimport动态生成的类,现在我正在尝试加载它以供使用,我如何才能做到这一点?天生的?或者使用类似于byte buddy的lib,我尝试使用下面的代码将每个类加载到一个包中:

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
,则类路径条目必须是包含
com
目录的目录,其中包含
abc
目录,依此类推。如果您知道其中一个类的预期完整限定名,那么很容易找到正确的目录。只要遍历到文件层次结构的次数与限定名称包含包组件的次数相同。然而,当你事先不知道它的名字时,找到它可能会很困难。这是一张草图:

// 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();
}
//传递f中包含的一个类的预期名称,如果未知,则传递null
静态void加载类(文件f,字符串predictedName)
抛出IOException,ClassNotFoundException{
File[]classes=f.listFiles((d,n)->n.endsWith(“.class”);
if(classes==null | | classes.length==0){
System.err.println(“没有类或没有目录”);
返回;
}
如果(predictedName==null)predictedName=predictName(类[0]);
对于(int p=predictedName.indexOf('.');p>=0;p=predictedName.indexOf('.',p+1))
f=f.getParentFile();
URLClassLoader classLoader=新的URLClassLoader(新的URL[]{f.toURI().toURL()});
字符串packageName=predictedName.substring(0,predictedName.lastIndexOf('.')+1);
用于(文件cf:classes){
字符串名称=cf.getName();
name=name.substring(0,name.length()-6);//剥离“.class”
Class cl=classLoader.loadClass(packageName+name);
//你想用这些课程做什么?
系统输出打印项次(cl);
}
}
私有静态字符串predictName(文件类文件)引发IOException{
byte[]data=Files.readAllBytes(classFile.toPath());
返回新的类加载器(){
字符串getName(){
返回defineClass(null,data,0,data.length).getName();
}
}.getName();
}

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

请确保生成的类位于与包结构匹配的目录中,并且根目录位于类路径中。@Holder我正在传递完整的类路径,我在上面的代码中遗漏了,我现在编辑了
// 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();
}