从一组文件加载类

时间:2015-07-02 08:42:08

标签: java classloader urlclassloader

我有一项任务是从类路径检查未知类集的一组条件。我想扫描它的类,加载它们并执行我的检查。现在我有一组类文件的URL,我尝试使用URLClassLoader。但是要加载一个类我需要指定一个完全限定的类名,但我没有它们(我只有文件路径)。我不认为从类文件路径构建类名是可以解除的,这是一种更好的方法吗?

谢谢!

2 个答案:

答案 0 :(得分:3)

我只是解析类文件的开头,寻找" package"关键字和第一次出现" class"关键词。然后,当你将这两者(packageName + "." + className)结合起来时,它应该产生一个合适的类名。

答案 1 :(得分:1)

我启动了一个项目,自动测试在类路径上找到的运行时异常类,通过使用null01等狡猾的参数反射调用构造函数和方法, -1""等。

该项目有一个名为Finder的类,大致可以满足您的需求:

    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;
    }

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