加载包和内部类 [英] Load a package and inside classes

查看:86
本文介绍了加载包和内部类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用一个由wsimport即时生成的类创建一个包,现在我正试图加载它以使用,我该怎么做?本机?或像字节伙伴这样的lib,我尝试了下面的代码将每个类加载到包中:

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? natively? or with some lib like byte-buddy, I tried the bellow code to load each class in a package:

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)

But I still getting (Package: 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.

因此,如果要加载的类是com.abc.external.resources.genwn239aqyhmfz.SomeClass,则类路径条目必须是包含com目录的目录,该目录包含abc目录,依此类推.如果您知道其中一个类别的预期全限定名称,则可以轻松找到正确的目录.只需遍历文件层次结构多次,只要合格名称具有包组件即可.但是,如果您事先不知道名称,发现它可能很棘手.这是一个草图:

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

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

The predictName implementation is a very simple one. 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. 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…

这篇关于加载包和内部类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆