IllegalStateException: Already initialized
ksc91u opened this issue ยท 14 comments
Caused by java.lang.IllegalStateException: Already initialized
at org.threeten.bp.zone.ZoneRulesInitializer.setInitializer(ZoneRulesInitializer.java:74)
at com.jakewharton.threetenabp.AndroidThreeTen.init(AndroidThreeTen.java:22)
at com.jakewharton.threetenabp.AndroidThreeTen.init(AndroidThreeTen.java:17)
at com.jakewharton.threetenabp.AndroidThreeTen.init(AndroidThreeTen.java:13)
at com.wave.waveradio.WaveApplication.onCreate(WaveApplication.java:108)
We have seen this exception on some devices since last release.
//jsr310
implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'
testImplementation("org.threeten:threetenbp:1.4.0") {
exclude module: "com.jakewharton.threetenabp:threetenabp:1.2.1"
}
//previously added duplicate entry
//testImplementation("org.threeten:threetenbp:1.4.0")
We have tried remove that testImplementation duplicate entry,
try/catch that exception and continue. But new exception occurred.
Fatal Exception: org.threeten.bp.zone.ZoneRulesException: No time-zone data files registered
at org.threeten.bp.zone.ZoneRulesProvider.getProvider(ZoneRulesProvider.java:165)
at org.threeten.bp.zone.ZoneRulesProvider.getRules(ZoneRulesProvider.java:122)
at org.threeten.bp.ZoneRegion.ofId(ZoneRegion.java:143)
at org.threeten.bp.ZoneId.of(ZoneId.java:358)
at org.threeten.bp.ZoneId.of(ZoneId.java:286)
at org.threeten.bp.ZoneId.systemDefault(ZoneId.java:245)
at org.threeten.bp.Clock.systemDefaultZone(Clock.java:137)
at org.threeten.bp.LocalDateTime.now(LocalDateTime.java:152)
I have seen two library entry in Android Studio,
org.threeten:threetenbp:1.4.0:no-tzdb@jar
org.threeten:threetenbp:1.4.0@jar
But only 1.4.0@jar version when run ./gradlew app::dependencies 2>&1 1> log2
I have also clear AndroidStudio & gradle caches. Do you know what might cause this issue? Thank you.
Yeah that's not going to work as the regular threetenbp jar will initialize itself with the embedded tzdb and then the application will try to initialize it with the asset version. threetenabp is not a dependency of threetenbp (it's the other way around) so your exclude isn't actually doing anything. There's really not a good way to set this up, I don't think.
I do not understand why adding threetenbp to unit test would effect my app on only some devices.
now my configuration is
implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'
try {
AndroidThreeTen.init(this)
} catch (e: Exception) {
Timber.e(e)
}
I removed that testImplementation but ZoneRulesException: No time-zone data files registered
still happen on some devices.
It should have no effect on the app. It will cause tests to always fail though.
Thank you, I will just try D8 java time then.
I got this too with 1.2.2
Caused by java.lang.IllegalStateException: Already initialized
at org.threeten.bp.zone.ZoneRulesInitializer.setInitializer(ZoneRulesInitializer.java:74)
at com.jakewharton.threetenabp.AndroidThreeTen.init(AndroidThreeTen.java:22)
at com.jakewharton.threetenabp.AndroidThreeTen.init(AndroidThreeTen.java:17)
at com.app.app.MainActivity.onCreate(MainActivity.java:161)
I have the following for release:
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
On the emulator it worked, the crash happened only for the first time I opened my app (after adding this lib). After that it seems to work. This is with my device, still waiting to see if it happens on more devices (a new release).
Did I do something wrong?
And it just happened again, any idea? Thanks
Initialize in application, not activity.
Silly me :)
Same error.
Library versions:
"com.jakewharton.threetenabp:threetenabp:1.2.1"
"org.threeten:threetenbp:1.4.0"
Usage:
class App : Application() {
override fun onCreate() {
super.onCreate()
if (LeakCanary.isInAnalyzerProcess(this)) {
return
}
if (ProcessPhoenix.isPhoenixProcess(this)) {
return
}
Fabric.with(this, crashlyticsKit)
AndroidThreeTen.init(this)
}
}
Error:
org.threeten.bp.zone.ZoneRulesInitializer.setInitializer (ZoneRulesInitializer.java:74)
com.jakewharton.threetenabp.AndroidThreeTen.init (AndroidThreeTen.java:22)
com.jakewharton.threetenabp.AndroidThreeTen.init (AndroidThreeTen.java:17)
com.jakewharton.threetenabp.AndroidThreeTen.init (AndroidThreeTen.java:13)
\\ Error like: App.onCreate (App.java:109)
This error does not always occur. We can not reproduce when testing the application. Errors are logged in Crashlytics. Versions of Android 7, 8, 9, 10. Various device manufacturers Samsung, Xiaomi, HUAWEI and others.
Error investigation
It looks like the ZoneRulesProvider
class is loading before calling the ZoneRulesInitializer.setInitializer()
method.
Documentation for method setInitializer()
:
This can only be invoked before the {@link ZoneRulesProvider} class is loaded.
Class ZoneRulesProvider
has a static initializer:
public abstract class ZoneRulesProvider {
static {
ZoneRulesInitializer.initialize();
}
}
I also got that issue on abp 1.2.3, are there any known workarounds? 1.2.4 seems to only add a Japanese time zone.
The crash happens rather randomly when the app is in background for a long time. There is only an abp dependency in my gradle, no org.threeten:threetenbp. Is that mandatory?
Logcat:
05-09 00:45:48.285 10475 10475 E AndroidRuntime: Caused by: java.lang.IllegalStateException: Already initialized
05-09 00:45:48.285 10475 10475 E AndroidRuntime: at org.threeten.bp.zone.ZoneRulesInitializer.setInitializer(ZoneRulesInitializer.java:74)
05-09 00:45:48.285 10475 10475 E AndroidRuntime: at com.jakewharton.threetenabp.AndroidThreeTen.init(AndroidThreeTen.java:22)
05-09 00:45:48.285 10475 10475 E AndroidRuntime: at com.jakewharton.threetenabp.AndroidThreeTen.init(AndroidThreeTen.java:17)
05-09 00:45:48.285 10475 10475 E AndroidRuntime: at com.example.erik.myroom.Frontend.Activity_Main.onCreate(Activity_Main.java:49)
05-09 00:45:48.285 10475 10475 E AndroidRuntime: at android.app.Activity.performCreate(Activity.java:6684)
05-09 00:45:48.285 10475 10475 E AndroidRuntime: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
05-09 00:45:48.285 10475 10475 E AndroidRuntime: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2637)
Code:
Public class Activity_Main extends AppCompatActivity
implements
Fragment_Main.OnCatButtonListener,
Fragment_Main.OnGlobalLIstButtonListener,
Fragment_Main.OnStatisticButtonListener,
Fragment_Main.OnJobListButtonListener,
OnBackToMainListener {
private ActivityMainBinding oBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
//inflates Iconics
LayoutInflaterCompat.setFactory2(getLayoutInflater(), new IconicsLayoutInflater2(getDelegate()));
super.onCreate(savedInstanceState);
//Init Date Framework
AndroidThreeTen.init(this);
//init job
androidx.work.PeriodicWorkRequest periodicWorkRequest = new androidx.work.PeriodicWorkRequest.Builder(
MonthlyWorker.class,
MIN_PERIODIC_INTERVAL_MILLIS, TimeUnit.MILLISECONDS,
MIN_PERIODIC_FLEX_MILLIS, TimeUnit.MILLISECONDS)
.addTag(TAG)
.build();
WorkManager.getInstance(getApplicationContext()).enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.KEEP, periodicWorkRequest);
//init Databinding
oBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
setSupportActionBar(oBinding.toolbar);
if(oBinding.mainContainer != null){
//are we restoring the instance state?
if(savedInstanceState != null){
return; //yes - do nothing
}
this.CreateNewFragment(new Fragment_Main());
}
}
We had this crash too. We use Dagger.Hilt and it injects Application
dependencies during super.onCreate()
. We call AndroidThreeTen.init
after super.onCreate()
. However, recently we used OffsetDateTime
in constructor of one of Application
dependencies. Turns out that doing that triggers AndroidThreeTen
initialization internally since we didn't call AndroidThreeTen.init
yet. And after super.onCreate()
we call AndroidThreeTen.init
and get this crash.
@JakeWharton Here AndroidThreeTen.init
is called after super.onCreate()
. Is it ok to call it before super.onCreate()
? If not then we should either stop injecting dependencies into Application
or we should rigorously check constructors of all our dependencies for not using org.threeten.abp
classes. Or maybe there is another way?
This is less error-prone with plain Dagger since you can't inject Application
dependencies in super.onCreate()
. So previously we called super.onCreate()
then AndroidThreeTen.init
and then injected our Application
.
@JakeWharton
wdyt about adding fallback with force setting initializer to make sure, that we are not crashing?
try {
AndroidThreeTen.init(application)
} catch (e: Exception) {
forceSetInitializer(application)
}
/**
* Copied logic from [com.jakewharton.threetenabp.AssetsZoneRulesInitializer]
*/
private fun forceSetInitializer(context: Context) {
val assetPath = "org/threeten/bp/TZDB.dat"
val provider: TzdbZoneRulesProvider
var inputStream: InputStream? = null
try {
inputStream = context.assets.open(assetPath)
provider = TzdbZoneRulesProvider(inputStream)
} catch (e: IOException) {
throw IllegalStateException("$assetPath missing from assets", e)
} finally {
if (inputStream != null) {
try {
inputStream.close()
} catch (ignored: IOException) {
}
}
}
try {
ZoneRulesProvider.registerProvider(provider)
} catch (ignored : ZoneRulesException){
// if this exception is thrown - means it is already initialized and we are good
}
}
hi @JakeWharton, just checking if there still isn't a solution for this yet?