diff --git a/mirai-console/backend/integration-test/src/AbstractTestPointAsPlugin.kt b/mirai-console/backend/integration-test/src/AbstractTestPointAsPlugin.kt
index 61735b7d1..262a62be0 100644
--- a/mirai-console/backend/integration-test/src/AbstractTestPointAsPlugin.kt
+++ b/mirai-console/backend/integration-test/src/AbstractTestPointAsPlugin.kt
@@ -12,6 +12,7 @@ package net.mamoe.console.integrationtest
 import net.mamoe.mirai.console.extension.PluginComponentStorage
 import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription
 import net.mamoe.mirai.console.plugin.jvm.KotlinPlugin
+import net.mamoe.mirai.utils.createInstanceOrNull
 
 /**
  * IntegrationTest 测试单元 (Plugin mode)
@@ -29,7 +30,6 @@ public abstract class AbstractTestPointAsPlugin : AbstractTestPoint() {
     protected open fun KotlinPlugin.onDisable0() {}
 
 
-
     @Suppress("unused")
     @PublishedApi
     internal abstract class TestPointPluginImpl(
@@ -43,7 +43,9 @@ public abstract class AbstractTestPointAsPlugin : AbstractTestPoint() {
         @PublishedApi
         internal constructor(
             impl: Class<out AbstractTestPointAsPlugin>
-        ) : this(impl.kotlin.objectInstance ?: impl.newInstance())
+        ) : this(
+            impl.kotlin.createInstanceOrNull() ?: impl.getConstructor().newInstance()
+        )
 
         override fun onDisable() {
             try {
diff --git a/mirai-console/backend/mirai-console/src/internal/data/reflectionUtils.kt b/mirai-console/backend/mirai-console/src/internal/data/reflectionUtils.kt
index 785c508ea..99789b871 100644
--- a/mirai-console/backend/mirai-console/src/internal/data/reflectionUtils.kt
+++ b/mirai-console/backend/mirai-console/src/internal/data/reflectionUtils.kt
@@ -13,6 +13,7 @@ package net.mamoe.mirai.console.internal.data
 
 import net.mamoe.mirai.console.data.PluginData
 import net.mamoe.mirai.console.data.ValueName
+import net.mamoe.mirai.utils.createInstanceOrNull
 import kotlin.reflect.*
 import kotlin.reflect.full.findAnnotation
 import kotlin.reflect.full.isSubclassOf
@@ -63,14 +64,6 @@ internal fun KType.classifierAsKClassOrNull() = when (val t = classifier) {
     else -> null
 } as KClass<Any>?
 
-@JvmSynthetic
-internal fun <T : Any> KClass<T>.createInstanceOrNull(): T? {
-    val noArgsConstructor = constructors.singleOrNull { it.parameters.all(KParameter::isOptional) }
-        ?: return null
-
-    return noArgsConstructor.callBy(emptyMap())
-}
-
 @JvmSynthetic
 internal fun KClass<*>.findValueName(): String =
     findAnnotation<ValueName>()?.value
diff --git a/mirai-console/backend/mirai-console/src/internal/data/valueFromKTypeImpl.kt b/mirai-console/backend/mirai-console/src/internal/data/valueFromKTypeImpl.kt
index dc2b8cd7d..ace3df43c 100644
--- a/mirai-console/backend/mirai-console/src/internal/data/valueFromKTypeImpl.kt
+++ b/mirai-console/backend/mirai-console/src/internal/data/valueFromKTypeImpl.kt
@@ -16,6 +16,7 @@ import net.mamoe.mirai.console.data.PluginData
 import net.mamoe.mirai.console.data.SerializableValue.Companion.serializableValueWith
 import net.mamoe.mirai.console.data.SerializerAwareValue
 import net.mamoe.mirai.console.data.valueFromKType
+import net.mamoe.mirai.utils.createInstanceOrNull
 import java.util.concurrent.ConcurrentHashMap
 import java.util.concurrent.ConcurrentMap
 import kotlin.contracts.contract
diff --git a/mirai-console/backend/mirai-console/src/internal/util/PluginServiceHelper.kt b/mirai-console/backend/mirai-console/src/internal/util/PluginServiceHelper.kt
index d0cd6e4ff..2cd1823fb 100644
--- a/mirai-console/backend/mirai-console/src/internal/util/PluginServiceHelper.kt
+++ b/mirai-console/backend/mirai-console/src/internal/util/PluginServiceHelper.kt
@@ -12,8 +12,8 @@
 package net.mamoe.mirai.console.internal.util
 
 import net.mamoe.mirai.console.internal.data.cast
-import net.mamoe.mirai.console.internal.data.createInstanceOrNull
 import net.mamoe.mirai.console.internal.plugin.BuiltInJvmPluginLoaderImpl
+import net.mamoe.mirai.utils.createInstanceOrNull
 import java.lang.reflect.Modifier
 import java.util.*
 import kotlin.reflect.KClass
diff --git a/mirai-core-utils/src/commonMain/kotlin/Reflections.kt b/mirai-core-utils/src/commonMain/kotlin/Reflections.kt
new file mode 100644
index 000000000..920b18712
--- /dev/null
+++ b/mirai-core-utils/src/commonMain/kotlin/Reflections.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2019-2021 Mamoe Technologies and contributors.
+ *
+ * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
+ * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
+ *
+ * https://github.com/mamoe/mirai/blob/dev/LICENSE
+ */
+
+package net.mamoe.mirai.utils
+
+import kotlin.reflect.KClass
+import kotlin.reflect.KParameter
+
+public fun <T : Any> KClass<T>.createInstanceOrNull(): T? {
+    objectInstance?.let { return it }
+    val noArgsConstructor = constructors.singleOrNull { it.parameters.all(KParameter::isOptional) }
+        ?: return null
+
+    return noArgsConstructor.callBy(emptyMap())
+}