kotlin.UninitializedPropertyAccessException 由获取实例引起
kotlin.UninitializedPropertyAccessException caused by get Instance
我的经理有以下代码 class :
11 class MyManager private constructor(application: Application) {
12 companion object {
13 val TAG = MyManager::class.java.simpleName
14
15 private val initialized = AtomicBoolean(false)
16 private lateinit var instance: MyManager
17
18 fun initialize(application: Application) {
19 synchronized(initialized) {
20 if (!initialized.getAndSet(true)) {
21 instance = MyManager(application)
22 }
23 }
24 }
25
26 val INSTANCE get() = instance
27 }
我的一些应用程序用户崩溃了
val INSTANCE get() = instance
行
具有以下崩溃堆栈
kotlin.UninitializedPropertyAccessException:
at my.package.MyManager$Companion.getINSTANCE (MyManager.kt:26)
at my.package.MyOtherManager.systemInitialization (MyOtherManager.kt:585)
at my.package.MyOtherManager.doRun (MyOtherManager.kt:433)
at my.package.MyOtherManager.access$doRun (MyOtherManager.kt:56)
at my.package.MyOtherManager$launchThread$launched.invoke (MyOtherManager.kt:126)
at my.package.MyOtherManager$launchThread$launched.invoke (MyOtherManager.kt:56)
at my.package.MyOtherManagerKt$sam$i$java_lang_Runnable[=13=].run (Unknown Source:2)
at java.lang.Thread.run (Thread.java:919)
我从类似的错误中了解到,我在设置它之前获取实例,但我不知道如果我的 initialized
布尔值默认为 false 并且我正在设置 instance
视情况而定。
我实例化 Class 的方式有问题吗?
我的第 19 行的行为是什么,当我调用 synchronized
时,它是先等待执行它再转到第 26 行(获取实例)还是存在在 [=16 中的代码之前获取实例的风险=] 阻止被调用?
这段代码有一些问题。
What's the behaviour for my line 19, when I call synchronized
, does it wait to execute it first before going to line 26 (getting the instance)
这几行代码没有强制关系。在 INSTANCE
属性 的任何读取之前调用 initialize(...)
没有任何强制要求。您需要确保在 每次 访问 INSTANCE
(或 instance
)之前调用 initialize
。
另一个问题是你在这里使用同步有点奇怪。你有一个 synchronized
块,就好像你希望从多个线程调用 initiaize
一样,但它只是用 Application
初始化的。这不是必需的,只需在应用程序启动时调用一次即可。
另一个问题是,根据您的具体设置方式,您可能会遇到 thread-safety 问题。如果您正在从另一个线程读取此内容,并且 instance
的初始化不是 happens-before 另一个线程的开始,则该初始化可能对另一个线程不可见。您可以通过 instance
volatile
.
来解决这个问题
我的经理有以下代码 class :
11 class MyManager private constructor(application: Application) {
12 companion object {
13 val TAG = MyManager::class.java.simpleName
14
15 private val initialized = AtomicBoolean(false)
16 private lateinit var instance: MyManager
17
18 fun initialize(application: Application) {
19 synchronized(initialized) {
20 if (!initialized.getAndSet(true)) {
21 instance = MyManager(application)
22 }
23 }
24 }
25
26 val INSTANCE get() = instance
27 }
我的一些应用程序用户崩溃了
val INSTANCE get() = instance
行
具有以下崩溃堆栈
kotlin.UninitializedPropertyAccessException:
at my.package.MyManager$Companion.getINSTANCE (MyManager.kt:26)
at my.package.MyOtherManager.systemInitialization (MyOtherManager.kt:585)
at my.package.MyOtherManager.doRun (MyOtherManager.kt:433)
at my.package.MyOtherManager.access$doRun (MyOtherManager.kt:56)
at my.package.MyOtherManager$launchThread$launched.invoke (MyOtherManager.kt:126)
at my.package.MyOtherManager$launchThread$launched.invoke (MyOtherManager.kt:56)
at my.package.MyOtherManagerKt$sam$i$java_lang_Runnable[=13=].run (Unknown Source:2)
at java.lang.Thread.run (Thread.java:919)
我从类似的错误中了解到,我在设置它之前获取实例,但我不知道如果我的 initialized
布尔值默认为 false 并且我正在设置 instance
视情况而定。
我实例化 Class 的方式有问题吗?
我的第 19 行的行为是什么,当我调用 synchronized
时,它是先等待执行它再转到第 26 行(获取实例)还是存在在 [=16 中的代码之前获取实例的风险=] 阻止被调用?
这段代码有一些问题。
What's the behaviour for my line 19, when I call
synchronized
, does it wait to execute it first before going to line 26 (getting the instance)
这几行代码没有强制关系。在 INSTANCE
属性 的任何读取之前调用 initialize(...)
没有任何强制要求。您需要确保在 每次 访问 INSTANCE
(或 instance
)之前调用 initialize
。
另一个问题是你在这里使用同步有点奇怪。你有一个 synchronized
块,就好像你希望从多个线程调用 initiaize
一样,但它只是用 Application
初始化的。这不是必需的,只需在应用程序启动时调用一次即可。
另一个问题是,根据您的具体设置方式,您可能会遇到 thread-safety 问题。如果您正在从另一个线程读取此内容,并且 instance
的初始化不是 happens-before 另一个线程的开始,则该初始化可能对另一个线程不可见。您可以通过 instance
volatile
.