正在从一组文件中加载 类

Loading classes from a set of files

我的任务是检查来自 class 路径的未知 classes 集合的一组条件。我想扫描 classes,加载它们中的每一个并执行我的检查。现在我有一组 class 文件的 url,我尝试使用 URLClassLoader。但是要加载 class 我需要指定一个完全限定的 class 名称,但我没有它们(我只有文件路径)。我不认为从 class 文件路径构建 class 名称是可靠的,这是更好的方法吗?

谢谢!

我曾经启动过一个项目来自动测试在 class 路径上找到的 classes 是否存在 运行 时间异常,方法是使用 [=11] 等狡猾的参数反射性地调用构造函数和方法=]、01-1""

该项目有一个名为 Finder 的 class,它大致满足您的需要:

    static List<Class<?>> findClassesForPackage(String packagename, Report report) throws ClassNotFoundException {
            // 'classes' will hold a list of directories matching the package name.
            // There may be more than one if a package is split over multiple
            // jars/paths
            List<Class<?>> classes = new ArrayList<Class<?>>();
            List<File> directories = new ArrayList<File>();
            try {
                    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
                    if (classLoader == null) {
                            throw new ClassNotFoundException("Can't get class loader.");
                    }
                    // Ask for all resources for the path
                    String path = packagename.replace('.', '/');
                    Enumeration<URL> resources = classLoader.getResources(path);
                    while (resources.hasMoreElements()) {
                            URL res = resources.nextElement();
                            if (res.getProtocol().equalsIgnoreCase("jar")) {
                                    JarURLConnection conn = (JarURLConnection) res.openConnection();
                                    JarFile jar = conn.getJarFile();
                                    for (JarEntry entry : Collections.list(jar.entries())) {
                                            if (entry.getName().startsWith(path) && entry.getName().endsWith(".class")
                                                            && !entry.getName().contains("$")) {
                                                    String className = entry.getName().replace("/", ".").substring(0,
                                                                    entry.getName().length() - 6);
                                                    LOG.debug("Adding JAR className " + className);
                                                    try {
                                                            Class<?> clazz = Class.forName(className);
                                                            classes.add(clazz);
                                                            report.addClass(className);
                                                    } catch (Throwable throwable) {
                                                            ParamSet params = new ParamSet();
                                                            params.addParamValue(new ParamValue(className, "fully qualified classname"));
                                                            report.addError(className, new Error("Class.forName()", params, throwable));
                                                    }
                                            }
                                    }
                            } else
                                    directories.add(new File(URLDecoder.decode(res.getPath(), "UTF-8")));
                    }
            } catch (NullPointerException e) {
                    throw new ClassNotFoundException(String.format("%s does not appear to be a valid package", packagename), e);
            } catch (UnsupportedEncodingException e) {
                    throw new ClassNotFoundException(String.format("%s does not appear to be a valid package", packagename), e);
            } catch (IOException e) {
                    throw new ClassNotFoundException(String.format("Could not get all resources for %s", packagename), e);
            }
            List<String> subPackages = new ArrayList<String>();
            // For every directory identified capture all the .class files
            for (File directory : directories) {
                    if (directory.exists()) {
                            // Get the list of the files contained in the package
                            File[] files = directory.listFiles();
                            for (File file : files) {
                                    // add .class files to results
                                    String fileName = file.getName();
                                    if (file.isFile() && fileName.endsWith(".class")) {
                                            // removes the .class extension
                                            String className = packagename + '.' + fileName.substring(0, fileName.length() - 6);
                                            LOG.debug("Adding FILE className " + className);
                                            try {
                                                    Class<?> clazz = Class.forName(className);
                                                    classes.add(clazz);
                                                    report.addClass(className);
                                            } catch (Throwable throwable) {
                                                    ParamSet params = new ParamSet();
                                                    params.addParamValue(new ParamValue(className, "fully qualified classname"));
                                                    report.addError(className, new Error("Class.forName()", params, throwable));
                                            }
                                    }
                                    // keep track of subdirectories
                                    if (file.isDirectory()) {
                                            subPackages.add(packagename + "." + fileName);
                                    }
                            }
                    } else {
                            throw new ClassNotFoundException(String.format("%s (%s) does not appear to be a valid package",
                                            packagename, directory.getPath()));
                    }
            }
            // check all potential subpackages
            for (String subPackage : subPackages) {
                    classes.addAll(findClassesForPackage(subPackage, report));
            }
            return classes;
    }

您可能必须删除一些进行报告等操作的代码。

我只是解析 class 文件的开头,查找 "package" 关键字和第一次出现的 "class" 关键字。然后,当您组合这两个 (packageName + "." + className) 时,它应该会产生一个正确的 class 名称。