Должен ли ClassPath.getTopLevelClasses () возвращать пакеты java. *? - PullRequest
0 голосов
/ 27 апреля 2018

Я использую ClassPath guava для получения доступных классов. С Java 8 это работало хорошо, но я перехожу на Java 10, и теперь это не работает. Я пробовал и guava 24.1 (последний jarfile, доступный в Maven Central), и последние источники на github (по состоянию на 27 апреля 2018 года) - предположительно более или менее guava 25.0, учитывая, что они выпустили его вчера.

Я могу получить некоторые классы, но что-либо в любых java.* пакетах не отображается. Это на самом деле ошибка, или я неправильно использую Java 10 (т.е. означает ли модульность, что мне нужно сделать что-то особенное)? Я вижу тот же симптом в Java 9. Я пытался собрать и запустить с Java 10 (или 9), а также с Java 8 и запустить с Java 10 (или 9), поведение одинаково в любом случае.

Я создал фиктивный пример с двумя классами в пакетах com.just.me и com.just.another:

com.just.me.Main.java

package com.just.me;

import com.google.common.reflect.ClassPath;
import com.just.another.Dummy;
import java.lang.String;
import java.util.Collections;
import java.util.List;

import java.io.IOException;

public class Main {

    public static void main(String[] args) {
        List<String> dummyList = Collections.emptyList();
        printClassCount("com.just.me", Main.class);
        printClassCount("com.just.another", Main.class);
        printClassCount("com.just", Main.class);
        printClassCount("com.google", Main.class);
        printClassCount("java.lang", Main.class);
        printClassCount("java.util", Main.class);
        printClassCount("java", Main.class);
    }

    private static void printClassCount(String packageName, Class classForClassLoader) {
        System.out.println("Number of toplevel classes in " + packageName + ": " + countTopleveClassesInPackage(packageName, classForClassLoader));
    }

    private static int countTopleveClassesInPackage(String packageName, Class clazz) {
        try {
            ClassPath classPath = ClassPath.from(clazz.getClassLoader());
            return classPath.getTopLevelClassesRecursive(packageName).size();
        } catch (IOException e) {
            return 0;
        }
    }
}

com.just.another.Dummy.java

package com.just.another;

public class Dummy {
    private String s;
    Dummy(String s) {
        this.s = s;
    }

    @Override
    public String toString() {
        return s;
    }
}

Вывод (Java 8)

Number of toplevel classes in com.just.me: 1
Number of toplevel classes in com.just.another: 1
Number of toplevel classes in com.just: 2
Number of toplevel classes in com.google: 569
Number of toplevel classes in java.lang: 232
Number of toplevel classes in java.util: 367
Number of toplevel classes in java: 1878

Вывод (Java 9/10)

Number of toplevel classes in com.just.me: 1
Number of toplevel classes in com.just.another: 1
Number of toplevel classes in com.just: 2
Number of toplevel classes in com.google: 569
Number of toplevel classes in java.lang: 0
Number of toplevel classes in java.util: 0
Number of toplevel classes in java: 0

1 Ответ

0 голосов
/ 24 мая 2018

Я думаю, в ClassPath нет ошибки. Он представляет путь к классам, но системные классы не находятся на пути к классам в Java 10:

// doesn't print rt.jar because there is no rt.jar anymore
System.out.println(StandardSystemProperty.JAVA_CLASS_PATH.value());

Так что это правильное поведение, что getTopLevelClasses не возвращает никаких классов для пакета java.*.

Если вы все еще хотите перечислить системные классы верхнего уровня, вы можете сделать что-то подобное (не точный код, просто набросок):

FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));

Files
    .list(fs.getPath("modules", "java.base", "java/lang"))
    .map(Path::getFileName)
    .filter(p -> p.toString().endsWith(".class") && !p.toString().contains("$"))
    .forEach(System.out::println);
...