diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/util/ServiceHelper.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/util/ServiceHelper.kt index 0824d2a02..04e8db113 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/util/ServiceHelper.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/util/ServiceHelper.kt @@ -12,7 +12,9 @@ package net.mamoe.mirai.console.internal.util import net.mamoe.mirai.console.internal.data.cast import net.mamoe.mirai.console.internal.data.createInstanceOrNull import java.io.InputStream +import java.lang.reflect.Modifier import kotlin.reflect.KClass +import java.lang.reflect.Member as JReflectionMember @Suppress("unused") internal class ServiceList( @@ -37,13 +39,16 @@ internal object ServiceHelper { fun ClassLoader.loadService( classname: String ): T? { + @Suppress("UNCHECKED_CAST") return kotlin.runCatching { val clazz = Class.forName(classname, true, this).cast>() - @Suppress("UNCHECKED_CAST") clazz.kotlin.objectInstance + ?: kotlin.runCatching { + clazz.declaredFields.firstOrNull { it.isStatic() && it.name == "INSTANCE" }?.get(null) + }.getOrNull() ?: clazz.kotlin.createInstanceOrNull() - ?: clazz.constructors.firstOrNull { it.parameterCount == 0 }?.newInstance() as T? + ?: clazz.constructors.firstOrNull { it.parameterCount == 0 }?.newInstance() ?: error("Cannot find a no-arg constructor") }.getOrElse { throw ServiceLoadException("Could not load service ${classname}.", it) @@ -53,10 +58,12 @@ internal object ServiceHelper { { "Could not load PluginLoader ${pluginQualifiedName}." }, PluginLoadException("Could not load PluginLoader ${pluginQualifiedName}.", it) )*/ - } + } as T? } } +internal fun JReflectionMember.isStatic(): Boolean = this.modifiers.and(Modifier.STATIC) != 0 + @Suppress("unused", "RedundantVisibilityModifier") internal open class ServiceLoadException : RuntimeException { public constructor() : super()