简体   繁体   English

加载包和内部类

[英]Load a package and inside classes

I'm creating a package with some classes that I generated with wsimport on the fly and now I'm trying to load it to use, how can I do this? 我正在创建一个包,其中包含一些由wsimport动态生成的类,现在我正在尝试加载它以使用,该怎么做? natively? 本机? or with some lib like byte-buddy, I tried the bellow code to load each class in a package: 或使用类似字节码的库之类的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);

But I still getting (Package: com.abc.external.resources.genwn239aqyhmfz.SomeClass) 但是我仍然得到(包装:com.abc.external.resources.genwn239aqyhmfz.SomeClass)

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

The rules for the class path are not different to the rules you have to obey when launching your application. 类路径的规则与启动应用程序时必须遵循的规则没有什么不同。 The class path entries are not class files nor directories containing them, but the roots of your package structure. 类路径条目不是类文件或包含它们的目录,而是包结构的根。

So if the class you want to load is com.abc.external.resources.genwn239aqyhmfz.SomeClass , the class path entry has to be the directory containing the com directory, which contains the abc directory, and so on. 因此,如果要加载的类是com.abc.external.resources.genwn239aqyhmfz.SomeClass ,则类路径条目必须是包含com目录的目录,该目录包含abc目录,依此类推。 If you know the expected full qualified name of one of the classes, it's easy to find the right directory. 如果您知道其中一个类别的预期全限定名称,则很容易找到正确的目录。 Just traverse to the file hierarchy up as many times as the qualified name has package components. 只要合格名称具有包组件,就遍历文件层次结构多次。 However, when you don't know the name beforehand, finding it can be tricky. 但是,当您事先不知道名称时,很难找到它。 Here is a sketch: 这是一个草图:

// 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();
}

The predictName implementation is a very simple one. predictName实现是一个非常简单的实现。 If the class has dependencies to classes within the same file hierarchy which the JVM immediately tries to resolve, it will fail as we don't have the necessary information yet. 如果该类依赖于JVM立即尝试解析的同一文件层次结构中的类,则它将失败,因为我们还没有必要的信息。 In that case, only a bytecode parsing library allowing to extract the name without loading the class would help. 在这种情况下,只有字节码解析库允许提取名称而无需加载类才有帮助。 But that exceeds the scope of this question… 但这超出了这个问题的范围……

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

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