【问题标题】:Kotlin classes cannot be found when reflecting filepaths to source directories or jars将文件路径反射到源目录或 jar 时找不到 Kotlin 类
【发布时间】:2019-01-18 14:57:06
【问题描述】:

===更新:使用 org.reflections:reflections:0.9.11

希望使用以下行从 Kotlin 源中提取类名列表...

Reflections.getSubTypesOf(Any::class.java)

但是,当我运行以下脚本时,我收到一条消息说没有看到 Kotlin 类文件...

val classLoader = URLClassLoader(this.getDirectoryUrls(), null)
println("retrieved class loader")

val config = getConfig(classLoader)
println("retrieved source config")

val reflections = Reflections(config)
println("retrieved reflections")

// For 3 paths: Reflections took 3 ms to scan 3 urls, producing 0 keys and 0 values

=== 更新:“getDirectoryUrls()”添加的 3 个 url 是包含 kotlin 类源文件的目录。

以下是我的配置...想法?

private fun getConfig(classLoader: ClassLoader): ConfigurationBuilder {
    val config = ConfigurationBuilder().setUrls(ClasspathHelper.forClassLoader(classLoader))
    //                .setScanners(SubTypesScanner(false), ResourcesScanner())

    if (!packagePath.isNullOrBlank()){
        System.out.println("looking in package [$packagePath]")
        config.filterInputsBy(FilterBuilder().include(FilterBuilder.prefix(packagePath)))
    }

    config.addClassLoader(classLoader)
    config.setScanners(SubTypesScanner(), TypeAnnotationsScanner())

    return config
}

【问题讨论】:

  • 您应该提及您使用的反射库。 getDirectoryUrls() 返回什么?
  • 按要求添加详细信息。见上文...

标签: reflection jar kotlin classloader


【解决方案1】:

似乎需要设置SubTypesScanner(false) 以获取具有getSubTypesOf(Any::class.java) 的任何类型(该参数本身代表excludeObjectClass)。查看 Kotlin 类的字节码,您会立即看到,它们实际上看起来与 Java 类相同。那里没有Any-superclass。请注意,Kotlins Any 实际上在其他方面也与 Javas Object 非常相似(但不一样,请检查以下answer to 'does Any == Object')。因此,我们需要在扫描Any 的子类型(即excludeObjectClass=false)时包含Object-class。

另一个问题可能是您的URL 数组的设置。我只是使用以下设置反射工具:

val reflections = Reflections(ConfigurationBuilder()
            .addUrls(ClasspathHelper.forPackage("my.test.package"))
            .setScanners(TypeAnnotationsScanner(), SubTypesScanner(false)))

这将解析所有匹配的子类型,并将返回 Any 的子类型。

reflections.getSubTypesOf(MyCustomSuperType::class.java).forEach(::println)
reflections.getSubTypesOf(Any::class.java).forEach(::println)

进一步分析:您提到“Kotlin 类 source 文件”...如果这意味着您指向包含 .kt-files 的目录,那么可能是你的问题。尝试改用包含.class-files 的目录。此外,确保类在类路径上。

也许你已经知道了,也许还没有?还要注意,如果你有一个(类)目录,比如/sample/directory,它在类路径上并且包含一个包,比如org.example(对应于文件夹结构org/example或完整路径/sample/directory/org/example)然后您必须确保添加类似于以下内容的URL

 YourClass::class.java.classLoader.getResource("")

而不是:

 YourClass::class.java.classLoader.getResource("org.example")
 // nor:
 YourClass::class.java.classLoader.getResource("org/example")

您基本上需要“基本”目录(在示例中为/sample/directory 或从类加载器的角度来看只是""))在哪里查找包而不是包本身。如果您提供后者URLs 中的一个,则实际上只会找到默认包(/sample/directory/org/example 内)中的类,但这是一种相当少见的设置。

【讨论】:

  • while SubTypesScanner(false) 我已经试过了(你可以看到它在 cmets 中被注释掉了)。 getSubTypesOf Any 和 Object 都不返回任何反射。我还尝试了几种将包加载到类路径的不同组合(包括包位置和查找我知道在类路径上有对象的特定 jar)。最后,我决定绕过增加查看包或罐子的复杂性,直接进入包含类文件的目录,以排除不把东西放在罐子里的可能性。这就是我使用上面示例的原因。
  • 这听起来像是一件苦差事,但在上述示例的上下文中工作是有原因的。我试图弄清为什么我什至不能反映一个目录。如果您可以使用上面的示例重现结果,请告诉我。
  • 嗯.. 是的,对不起.. 我总是忽略注释掉的代码 ;-) 所以我理解正确吗?您想加载任何文件夹(例如,不在类路径上的文件夹?)?明天将尝试您的确切示例,但也显示其中一个 URL,也许还显示包含的包..
  • 为答案添加了更多分析...您可以继续阅读“进一步分析”...请注意,使用getSubTypesOf(Any::class.java) 时需要SubTypesScanner(false) 才能返回适当的类型。只要您处理类文件(最好在类路径上),扫描应该没有问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-05
  • 2014-11-10
  • 2014-08-08
  • 1970-01-01
相关资源
最近更新 更多